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) {
|
static void try_remove(path const &path, bool all = false) {
|
||||||
//try {
|
try {
|
||||||
if (all) {
|
if (all) {
|
||||||
fs::remove_all(path);
|
fs::remove_all(path);
|
||||||
} else {
|
} else {
|
||||||
fs::remove(path);
|
fs::remove(path);
|
||||||
}
|
}
|
||||||
//} catch (fs::fs_error const &) {}
|
} catch (fs::fs_error const &) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
|
|
44
ostd/path.hh
44
ostd/path.hh
|
@ -30,6 +30,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <stdexcept>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include <ostd/platform.hh>
|
#include <ostd/platform.hh>
|
||||||
|
@ -57,6 +58,13 @@ namespace detail {
|
||||||
) noexcept;
|
) noexcept;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct path_error: std::runtime_error {
|
||||||
|
using std::runtime_error::runtime_error;
|
||||||
|
|
||||||
|
/* empty, for vtable placement */
|
||||||
|
virtual ~path_error();
|
||||||
|
};
|
||||||
|
|
||||||
struct path {
|
struct path {
|
||||||
#ifdef OSTD_PLATFORM_WIN32
|
#ifdef OSTD_PLATFORM_WIN32
|
||||||
static constexpr char native_separator = '\\';
|
static constexpr char native_separator = '\\';
|
||||||
|
@ -277,8 +285,7 @@ struct path {
|
||||||
path &remove_name() {
|
path &remove_name() {
|
||||||
auto nm = name();
|
auto nm = name();
|
||||||
if (nm.empty()) {
|
if (nm.empty()) {
|
||||||
/* TODO: throw */
|
throw path_error{"path has no name"};
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
p_path.erase(p_path.size() - nm.size() - 1, nm.size() + 1);
|
p_path.erase(p_path.size() - nm.size() - 1, nm.size() + 1);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -734,6 +741,37 @@ struct format_traits<path> {
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
namespace fs {
|
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
|
/** @addtogroup Utilities
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
@ -1179,7 +1217,7 @@ namespace detail {
|
||||||
* context (i.e. not as entire filename/directory name) will be treated
|
* context (i.e. not as entire filename/directory name) will be treated
|
||||||
* as two regular `*` patterns.
|
* 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`.
|
* @returns The forwarded `out`.
|
||||||
*/
|
*/
|
||||||
template<typename OutputRange>
|
template<typename OutputRange>
|
||||||
|
|
12
src/path.cc
12
src/path.cc
|
@ -15,6 +15,18 @@
|
||||||
# error "Unsupported platform"
|
# error "Unsupported platform"
|
||||||
#endif
|
#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 ostd {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,21 @@ static file_type mode_to_type(mode_t mode) {
|
||||||
return file_type::unknown;
|
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) {
|
OSTD_EXPORT file_mode mode(path const &p) {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (stat(p.string().data(), &sb) < 0) {
|
if (stat(p.string().data(), &sb) < 0) {
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
return file_mode{file_type::not_found, perms::none};
|
return file_mode{file_type::not_found, perms::none};
|
||||||
}
|
}
|
||||||
/* FIXME: throw */
|
throw fs_error{"stat failure", p, errno_ec()};
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
return file_mode{mode_to_type(sb.st_mode), perms(sb.st_mode & 07777)};
|
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) {
|
if (errno == ENOENT) {
|
||||||
return file_mode{file_type::not_found, perms::none};
|
return file_mode{file_type::not_found, perms::none};
|
||||||
}
|
}
|
||||||
/* FIXME: throw */
|
throw fs_error{"lstat failure", p, errno_ec()};
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
return file_mode{mode_to_type(sb.st_mode), perms(sb.st_mode & 07777)};
|
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;
|
struct dirent *o;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (readdir_r(dh, &d, &o)) {
|
if (readdir_r(dh, &d, &o)) {
|
||||||
/* FIXME: throw */
|
throw fs_error{"readdir_r failure", base, errno_ec()};
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
if (!o) {
|
if (!o) {
|
||||||
cur = path{};
|
cur = path{};
|
||||||
|
@ -100,8 +105,7 @@ static void dir_read_next(
|
||||||
OSTD_EXPORT void dir_range_impl::open(path const &p) {
|
OSTD_EXPORT void dir_range_impl::open(path const &p) {
|
||||||
DIR *d = opendir(p.string().data());
|
DIR *d = opendir(p.string().data());
|
||||||
if (!d) {
|
if (!d) {
|
||||||
/* FIXME: throw */
|
throw fs_error{"opendir failure", p, errno_ec()};
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
p_dir = p;
|
p_dir = p;
|
||||||
p_handle = d;
|
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) {
|
OSTD_EXPORT void rdir_range_impl::open(path const &p) {
|
||||||
DIR *d = opendir(p.string().data());
|
DIR *d = opendir(p.string().data());
|
||||||
if (!d) {
|
if (!d) {
|
||||||
/* FIXME: throw */
|
throw fs_error{"opendir failure", p, errno_ec()};
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
p_dir = p;
|
p_dir = p;
|
||||||
p_handles.push(d);
|
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 */
|
/* directory, recurse into it and if it contains stuff, return */
|
||||||
DIR *nd = opendir(p_current.path().string().data());
|
DIR *nd = opendir(p_current.path().string().data());
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
abort();
|
throw fs_error{"opendir failure", p_current, errno_ec()};
|
||||||
}
|
}
|
||||||
directory_entry based = p_current;
|
directory_entry based = p_current;
|
||||||
dir_read_next(nd, curd, tp, based);
|
dir_read_next(nd, curd, tp, based);
|
||||||
|
@ -196,7 +199,7 @@ OSTD_EXPORT path current_path() {
|
||||||
auto p = getcwd(rbuf.data(), rbuf.capacity());
|
auto p = getcwd(rbuf.data(), rbuf.capacity());
|
||||||
if (!p) {
|
if (!p) {
|
||||||
if (errno != ERANGE) {
|
if (errno != ERANGE) {
|
||||||
abort();
|
throw fs_error{"getcwd failure", errno_ec()};
|
||||||
}
|
}
|
||||||
rbuf.reserve(rbuf.capacity() * 2);
|
rbuf.reserve(rbuf.capacity() * 2);
|
||||||
continue;
|
continue;
|
||||||
|
@ -221,7 +224,7 @@ OSTD_EXPORT path home_path() {
|
||||||
buf.reserve(bufs);
|
buf.reserve(bufs);
|
||||||
getpwuid_r(getuid(), &pwd, buf.data(), buf.capacity(), &ret);
|
getpwuid_r(getuid(), &pwd, buf.data(), buf.capacity(), &ret);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
abort();
|
throw fs_error{"getpwuid_r failure", errno_ec()};
|
||||||
}
|
}
|
||||||
return path{string_range{pwd.pw_dir}};
|
return path{string_range{pwd.pw_dir}};
|
||||||
}
|
}
|
||||||
|
@ -239,7 +242,7 @@ OSTD_EXPORT path temp_path() {
|
||||||
|
|
||||||
OSTD_EXPORT void current_path(path const &p) {
|
OSTD_EXPORT void current_path(path const &p) {
|
||||||
if (chdir(p.string().data())) {
|
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 */
|
/* TODO: legacy system support */
|
||||||
char *rp = realpath(p.string().data(), nullptr);
|
char *rp = realpath(p.string().data(), nullptr);
|
||||||
if (!rp) {
|
if (!rp) {
|
||||||
abort();
|
throw fs_error{"realpath failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
path ret{string_range{rp}};
|
path ret{string_range{rp}};
|
||||||
free(rp);
|
free(rp);
|
||||||
|
@ -264,7 +267,7 @@ OSTD_EXPORT path canonical(path const &p) {
|
||||||
static inline bool try_access(path const &p) {
|
static inline bool try_access(path const &p) {
|
||||||
bool ret = !access(p.string().data(), F_OK);
|
bool ret = !access(p.string().data(), F_OK);
|
||||||
if (!ret && (errno != ENOENT)) {
|
if (!ret && (errno != ENOENT)) {
|
||||||
abort();
|
throw fs_error{"access failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -303,12 +306,12 @@ OSTD_EXPORT bool exists(path const &p) {
|
||||||
OSTD_EXPORT bool equivalent(path const &p1, path const &p2) {
|
OSTD_EXPORT bool equivalent(path const &p1, path const &p2) {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (stat(p1.string().data(), &sb) < 0) {
|
if (stat(p1.string().data(), &sb) < 0) {
|
||||||
abort();
|
throw fs_error{"stat failure", p1, p2, errno_ec()};
|
||||||
}
|
}
|
||||||
auto stdev = sb.st_dev;
|
auto stdev = sb.st_dev;
|
||||||
auto stino = sb.st_ino;
|
auto stino = sb.st_ino;
|
||||||
if (stat(p2.string().data(), &sb) < 0) {
|
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));
|
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) {
|
static bool mkdir_p(path const &p, mode_t mode) {
|
||||||
if (mkdir(p.string().data(), mode)) {
|
if (mkdir(p.string().data(), mode)) {
|
||||||
if (errno != EEXIST) {
|
if (errno != EEXIST) {
|
||||||
abort();
|
throw fs_error{"mkdir failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
|
int eno = errno;
|
||||||
auto tp = fs::mode(p);
|
auto tp = fs::mode(p);
|
||||||
if (tp.type() != file_type::directory) {
|
if (tp.type() != file_type::directory) {
|
||||||
|
throw fs_error{"mkdir failure", p, ec_from_int(eno)};
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -347,7 +352,7 @@ OSTD_EXPORT bool remove(path const &p) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (::remove(p.string().data())) {
|
if (::remove(p.string().data())) {
|
||||||
abort();
|
throw fs_error{"remove failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
return true;
|
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) {
|
OSTD_EXPORT void rename(path const &op, path const &np) {
|
||||||
if (::rename(op.string().data(), np.string().data())) {
|
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) {
|
OSTD_EXPORT file_time_t last_write_time(path const &p) {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (stat(p.string().data(), &sb) < 0) {
|
if (stat(p.string().data(), &sb) < 0) {
|
||||||
abort();
|
throw fs_error{"stat failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
return mtime::get(sb);
|
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())}
|
{0, UTIME_OMIT}, {time_t(sec.count()), long(nsec.count())}
|
||||||
};
|
};
|
||||||
if (utimensat(0, p.string().data(), times, 0)) {
|
if (utimensat(0, p.string().data(), times, 0)) {
|
||||||
abort();
|
throw fs_error{"utimensat failure", p, errno_ec()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue