forked from OctaForge/libostd
replace path aborts with exceptions
This commit is contained in:
parent
9aa03b8a9f
commit
049ce44d3a
4
build.cc
4
build.cc
|
@ -129,13 +129,13 @@ static void add_args(strvec &args, std::string const &cmdl) {
|
|||
}
|
||||
|
||||
static void try_remove(path const &path, bool all = false) {
|
||||
//try {
|
||||
try {
|
||||
if (all) {
|
||||
fs::remove_all(path);
|
||||
} else {
|
||||
fs::remove(path);
|
||||
}
|
||||
//} catch (fs::fs_error const &) {}
|
||||
} catch (fs::fs_error const &) {}
|
||||
}
|
||||
|
||||
static bool verbose = false;
|
||||
|
|
44
ostd/path.hh
44
ostd/path.hh
|
@ -30,6 +30,7 @@
|
|||
#include <memory>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
#include <ostd/platform.hh>
|
||||
|
@ -57,6 +58,13 @@ namespace detail {
|
|||
) noexcept;
|
||||
}
|
||||
|
||||
struct path_error: std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
|
||||
/* empty, for vtable placement */
|
||||
virtual ~path_error();
|
||||
};
|
||||
|
||||
struct path {
|
||||
#ifdef OSTD_PLATFORM_WIN32
|
||||
static constexpr char native_separator = '\\';
|
||||
|
@ -277,8 +285,7 @@ struct path {
|
|||
path &remove_name() {
|
||||
auto nm = name();
|
||||
if (nm.empty()) {
|
||||
/* TODO: throw */
|
||||
return *this;
|
||||
throw path_error{"path has no name"};
|
||||
}
|
||||
p_path.erase(p_path.size() - nm.size() - 1, nm.size() + 1);
|
||||
return *this;
|
||||
|
@ -734,6 +741,37 @@ struct format_traits<path> {
|
|||
namespace ostd {
|
||||
namespace fs {
|
||||
|
||||
struct fs_error: std::system_error {
|
||||
fs_error(std::string const &warg, std::error_code ec):
|
||||
std::system_error::system_error(ec, warg)
|
||||
{}
|
||||
|
||||
fs_error(std::string const &warg, path const &p1, std::error_code ec):
|
||||
std::system_error::system_error(ec, warg), p_p1(p1)
|
||||
{}
|
||||
|
||||
fs_error(
|
||||
std::string const &warg, path const &p1,
|
||||
path const &p2, std::error_code ec
|
||||
):
|
||||
std::system_error::system_error(ec, warg), p_p1(p1), p_p2(p2)
|
||||
{}
|
||||
|
||||
/* empty, for vtable placement */
|
||||
virtual ~fs_error();
|
||||
|
||||
path const &path1() const noexcept {
|
||||
return p_p1;
|
||||
}
|
||||
|
||||
path const &path2() const noexcept {
|
||||
return p_p1;
|
||||
}
|
||||
|
||||
private:
|
||||
path p_p1{}, p_p2{};
|
||||
};
|
||||
|
||||
/** @addtogroup Utilities
|
||||
* @{
|
||||
*/
|
||||
|
@ -1179,7 +1217,7 @@ namespace detail {
|
|||
* context (i.e. not as entire filename/directory name) will be treated
|
||||
* as two regular `*` patterns.
|
||||
*
|
||||
* @throws std::filesystem_error if a filesystem error occurs.
|
||||
* @throws fs::fs_error if a filesystem error occurs.
|
||||
* @returns The forwarded `out`.
|
||||
*/
|
||||
template<typename OutputRange>
|
||||
|
|
12
src/path.cc
12
src/path.cc
|
@ -15,6 +15,18 @@
|
|||
# error "Unsupported platform"
|
||||
#endif
|
||||
|
||||
namespace ostd {
|
||||
|
||||
/* place the vtables in here */
|
||||
|
||||
path_error::~path_error() {}
|
||||
|
||||
namespace fs {
|
||||
fs_error::~fs_error() {}
|
||||
} /* namespace fs */
|
||||
|
||||
} /* namespace ostd */
|
||||
|
||||
namespace ostd {
|
||||
namespace detail {
|
||||
|
||||
|
|
|
@ -31,14 +31,21 @@ static file_type mode_to_type(mode_t mode) {
|
|||
return file_type::unknown;
|
||||
}
|
||||
|
||||
static std::error_code errno_ec() {
|
||||
return std::error_code{errno, std::system_category()};
|
||||
}
|
||||
|
||||
static std::error_code ec_from_int(int v) {
|
||||
return std::error_code(v, std::system_category());
|
||||
}
|
||||
|
||||
OSTD_EXPORT file_mode mode(path const &p) {
|
||||
struct stat sb;
|
||||
if (stat(p.string().data(), &sb) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
return file_mode{file_type::not_found, perms::none};
|
||||
}
|
||||
/* FIXME: throw */
|
||||
abort();
|
||||
throw fs_error{"stat failure", p, errno_ec()};
|
||||
}
|
||||
return file_mode{mode_to_type(sb.st_mode), perms(sb.st_mode & 07777)};
|
||||
}
|
||||
|
@ -49,8 +56,7 @@ OSTD_EXPORT file_mode symlink_mode(path const &p) {
|
|||
if (errno == ENOENT) {
|
||||
return file_mode{file_type::not_found, perms::none};
|
||||
}
|
||||
/* FIXME: throw */
|
||||
abort();
|
||||
throw fs_error{"lstat failure", p, errno_ec()};
|
||||
}
|
||||
return file_mode{mode_to_type(sb.st_mode), perms(sb.st_mode & 07777)};
|
||||
}
|
||||
|
@ -69,8 +75,7 @@ static void dir_read_next(
|
|||
struct dirent *o;
|
||||
for (;;) {
|
||||
if (readdir_r(dh, &d, &o)) {
|
||||
/* FIXME: throw */
|
||||
abort();
|
||||
throw fs_error{"readdir_r failure", base, errno_ec()};
|
||||
}
|
||||
if (!o) {
|
||||
cur = path{};
|
||||
|
@ -100,8 +105,7 @@ static void dir_read_next(
|
|||
OSTD_EXPORT void dir_range_impl::open(path const &p) {
|
||||
DIR *d = opendir(p.string().data());
|
||||
if (!d) {
|
||||
/* FIXME: throw */
|
||||
abort();
|
||||
throw fs_error{"opendir failure", p, errno_ec()};
|
||||
}
|
||||
p_dir = p;
|
||||
p_handle = d;
|
||||
|
@ -124,8 +128,7 @@ OSTD_EXPORT void dir_range_impl::read_next() {
|
|||
OSTD_EXPORT void rdir_range_impl::open(path const &p) {
|
||||
DIR *d = opendir(p.string().data());
|
||||
if (!d) {
|
||||
/* FIXME: throw */
|
||||
abort();
|
||||
throw fs_error{"opendir failure", p, errno_ec()};
|
||||
}
|
||||
p_dir = p;
|
||||
p_handles.push(d);
|
||||
|
@ -150,7 +153,7 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
|||
/* directory, recurse into it and if it contains stuff, return */
|
||||
DIR *nd = opendir(p_current.path().string().data());
|
||||
if (!nd) {
|
||||
abort();
|
||||
throw fs_error{"opendir failure", p_current, errno_ec()};
|
||||
}
|
||||
directory_entry based = p_current;
|
||||
dir_read_next(nd, curd, tp, based);
|
||||
|
@ -196,7 +199,7 @@ OSTD_EXPORT path current_path() {
|
|||
auto p = getcwd(rbuf.data(), rbuf.capacity());
|
||||
if (!p) {
|
||||
if (errno != ERANGE) {
|
||||
abort();
|
||||
throw fs_error{"getcwd failure", errno_ec()};
|
||||
}
|
||||
rbuf.reserve(rbuf.capacity() * 2);
|
||||
continue;
|
||||
|
@ -221,7 +224,7 @@ OSTD_EXPORT path home_path() {
|
|||
buf.reserve(bufs);
|
||||
getpwuid_r(getuid(), &pwd, buf.data(), buf.capacity(), &ret);
|
||||
if (!ret) {
|
||||
abort();
|
||||
throw fs_error{"getpwuid_r failure", errno_ec()};
|
||||
}
|
||||
return path{string_range{pwd.pw_dir}};
|
||||
}
|
||||
|
@ -239,7 +242,7 @@ OSTD_EXPORT path temp_path() {
|
|||
|
||||
OSTD_EXPORT void current_path(path const &p) {
|
||||
if (chdir(p.string().data())) {
|
||||
abort();
|
||||
throw fs_error{"chdir failure", p, errno_ec()};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +257,7 @@ OSTD_EXPORT path canonical(path const &p) {
|
|||
/* TODO: legacy system support */
|
||||
char *rp = realpath(p.string().data(), nullptr);
|
||||
if (!rp) {
|
||||
abort();
|
||||
throw fs_error{"realpath failure", p, errno_ec()};
|
||||
}
|
||||
path ret{string_range{rp}};
|
||||
free(rp);
|
||||
|
@ -264,7 +267,7 @@ OSTD_EXPORT path canonical(path const &p) {
|
|||
static inline bool try_access(path const &p) {
|
||||
bool ret = !access(p.string().data(), F_OK);
|
||||
if (!ret && (errno != ENOENT)) {
|
||||
abort();
|
||||
throw fs_error{"access failure", p, errno_ec()};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -303,12 +306,12 @@ OSTD_EXPORT bool exists(path const &p) {
|
|||
OSTD_EXPORT bool equivalent(path const &p1, path const &p2) {
|
||||
struct stat sb;
|
||||
if (stat(p1.string().data(), &sb) < 0) {
|
||||
abort();
|
||||
throw fs_error{"stat failure", p1, p2, errno_ec()};
|
||||
}
|
||||
auto stdev = sb.st_dev;
|
||||
auto stino = sb.st_ino;
|
||||
if (stat(p2.string().data(), &sb) < 0) {
|
||||
abort();
|
||||
throw fs_error{"stat failure", p1, p2, errno_ec()};
|
||||
}
|
||||
return ((sb.st_dev == stdev) && (sb.st_ino == stino));
|
||||
}
|
||||
|
@ -316,10 +319,12 @@ OSTD_EXPORT bool equivalent(path const &p1, path const &p2) {
|
|||
static bool mkdir_p(path const &p, mode_t mode) {
|
||||
if (mkdir(p.string().data(), mode)) {
|
||||
if (errno != EEXIST) {
|
||||
abort();
|
||||
throw fs_error{"mkdir failure", p, errno_ec()};
|
||||
}
|
||||
int eno = errno;
|
||||
auto tp = fs::mode(p);
|
||||
if (tp.type() != file_type::directory) {
|
||||
throw fs_error{"mkdir failure", p, ec_from_int(eno)};
|
||||
abort();
|
||||
}
|
||||
return false;
|
||||
|
@ -347,7 +352,7 @@ OSTD_EXPORT bool remove(path const &p) {
|
|||
return false;
|
||||
}
|
||||
if (::remove(p.string().data())) {
|
||||
abort();
|
||||
throw fs_error{"remove failure", p, errno_ec()};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -366,7 +371,7 @@ OSTD_EXPORT std::uintmax_t remove_all(path const &p) {
|
|||
|
||||
OSTD_EXPORT void rename(path const &op, path const &np) {
|
||||
if (::rename(op.string().data(), np.string().data())) {
|
||||
abort();
|
||||
throw fs_error{"rename failure", op, np, errno_ec()};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +424,7 @@ using mtime = mtime_impl<test_mtim<struct stat>::value>;
|
|||
OSTD_EXPORT file_time_t last_write_time(path const &p) {
|
||||
struct stat sb;
|
||||
if (stat(p.string().data(), &sb) < 0) {
|
||||
abort();
|
||||
throw fs_error{"stat failure", p, errno_ec()};
|
||||
}
|
||||
return mtime::get(sb);
|
||||
}
|
||||
|
@ -433,7 +438,7 @@ OSTD_EXPORT void last_write_time(path const &p, file_time_t new_time) {
|
|||
{0, UTIME_OMIT}, {time_t(sec.count()), long(nsec.count())}
|
||||
};
|
||||
if (utimensat(0, p.string().data(), times, 0)) {
|
||||
abort();
|
||||
throw fs_error{"utimensat failure", p, errno_ec()};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue