From e1db5992ec068a5f544b7ade55ee8bbe5046c2f2 Mon Sep 17 00:00:00 2001 From: regnat Date: Wed, 7 Jul 2021 14:29:38 +0200 Subject: [PATCH] Add a dedicated error type for file-related operations --- src/libutil/error.hh | 13 +++++++++++++ src/libutil/util.cc | 32 ++++++++++++++++---------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/libutil/error.hh b/src/libutil/error.hh index ff58d3e00..c38364b98 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -205,4 +205,17 @@ public: virtual const char* sname() const override { return "SysError"; } }; +class FileError : public SysError +{ +public: + const Path path; + + template + FileError(const std::string & fs, const Path & path, const Args & ... args) + :SysError(fs, path, args...) + , path(path) + { + } +}; + } diff --git a/src/libutil/util.cc b/src/libutil/util.cc index a6552ebca..16b1d2adf 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -216,7 +216,7 @@ struct stat lstat(const Path & path) { struct stat st; if (lstat(path.c_str(), &st)) - throw SysError("getting status of '%1%'", path); + throw FileError("getting status of '%1%'", path); return st; } @@ -228,7 +228,7 @@ bool pathExists(const Path & path) res = lstat(path.c_str(), &st); if (!res) return true; if (errno != ENOENT && errno != ENOTDIR) - throw SysError("getting status of %1%", path); + throw FileError("getting status of %1%", path); return false; } @@ -244,7 +244,7 @@ Path readLink(const Path & path) if (errno == EINVAL) throw Error("'%1%' is not a symlink", path); else - throw SysError("reading symbolic link '%1%'", path); + throw FileError("reading symbolic link '%1%'", path); else if (rlSize < bufSize) return string(buf.data(), rlSize); } @@ -276,7 +276,7 @@ DirEntries readDirectory(DIR *dir, const Path & path) #endif ); } - if (errno) throw SysError("reading directory '%1%'", path); + if (errno) throw FileError("reading directory '%1%'", path); return entries; } @@ -284,7 +284,7 @@ DirEntries readDirectory(DIR *dir, const Path & path) DirEntries readDirectory(const Path & path) { AutoCloseDir dir(opendir(path.c_str())); - if (!dir) throw SysError("opening directory '%1%'", path); + if (!dir) throw FileError("opening directory '%1%'", path); return readDirectory(dir.get(), path); } @@ -314,7 +314,7 @@ string readFile(const Path & path) { AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); if (!fd) - throw SysError("opening file '%1%'", path); + throw FileError("opening file '%1%'", path); return readFile(fd.get()); } @@ -323,7 +323,7 @@ void readFile(const Path & path, Sink & sink) { AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); if (!fd) - throw SysError("opening file '%s'", path); + throw FileError("opening file '%s'", path); drainFD(fd.get(), sink); } @@ -332,7 +332,7 @@ void writeFile(const Path & path, std::string_view s, mode_t mode) { AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode); if (!fd) - throw SysError("opening file '%1%'", path); + throw FileError("opening file '%1%'", path); try { writeFull(fd.get(), s); } catch (Error & e) { @@ -346,7 +346,7 @@ void writeFile(const Path & path, Source & source, mode_t mode) { AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode); if (!fd) - throw SysError("opening file '%1%'", path); + throw FileError("opening file '%1%'", path); std::vector buf(64 * 1024); @@ -400,7 +400,7 @@ static void _deletePath(int parentfd, const Path & path, uint64_t & bytesFreed) struct stat st; if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) { if (errno == ENOENT) return; - throw SysError("getting status of '%1%'", path); + throw FileError("getting status of '%1%'", path); } if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) @@ -411,7 +411,7 @@ static void _deletePath(int parentfd, const Path & path, uint64_t & bytesFreed) const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR; if ((st.st_mode & PERM_MASK) != PERM_MASK) { if (fchmodat(parentfd, name.c_str(), st.st_mode | PERM_MASK, 0) == -1) - throw SysError("chmod '%1%'", path); + throw FileError("chmod '%1%'", path); } int fd = openat(parentfd, path.c_str(), O_RDONLY); @@ -511,7 +511,7 @@ std::pair createTempFile(const Path & prefix) // FIXME: use O_TMPFILE. AutoCloseFD fd(mkstemp((char *) tmpl.c_str())); if (!fd) - throw SysError("creating temporary file '%s'", tmpl); + throw FileError("creating temporary file '%s'", tmpl); return {std::move(fd), tmpl}; } @@ -591,7 +591,7 @@ Paths createDirs(const Path & path) } if (S_ISLNK(st.st_mode) && stat(path.c_str(), &st) == -1) - throw SysError("statting symlink '%1%'", path); + throw FileError("statting symlink '%1%'", path); if (!S_ISDIR(st.st_mode)) throw Error("'%1%' is not a directory", path); @@ -603,7 +603,7 @@ void createSymlink(const Path & target, const Path & link, std::optional mtime) { if (symlink(target.c_str(), link.c_str())) - throw SysError("creating symlink from '%1%' to '%2%'", link, target); + throw FileError("creating symlink from '%1%' to '%2%'", link, target); if (mtime) { struct timeval times[2]; times[0].tv_sec = *mtime; @@ -611,7 +611,7 @@ void createSymlink(const Path & target, const Path & link, times[1].tv_sec = *mtime; times[1].tv_usec = 0; if (lutimes(link.c_str(), times)) - throw SysError("setting time of symlink '%s'", link); + throw FileError("setting time of symlink '%s'", link); } } @@ -727,7 +727,7 @@ AutoDelete::~AutoDelete() deletePath(path); else { if (remove(path.c_str()) == -1) - throw SysError("cannot unlink '%1%'", path); + throw FileError("cannot unlink '%1%'", path); } } } catch (...) {