replace path aborts with exceptions

master
Daniel Kolesa 2018-04-18 10:55:56 +02:00
parent 9aa03b8a9f
commit 049ce44d3a
4 changed files with 83 additions and 28 deletions

View File

@ -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;

View File

@ -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>

View File

@ -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 {

View File

@ -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()};
}
}