1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-24 11:19:35 +01:00

Add a dedicated error type for file-related operations

This commit is contained in:
regnat 2021-07-07 14:29:38 +02:00
parent 9fe0343bfd
commit e1db5992ec
2 changed files with 29 additions and 16 deletions

View file

@ -205,4 +205,17 @@ public:
virtual const char* sname() const override { return "SysError"; } virtual const char* sname() const override { return "SysError"; }
}; };
class FileError : public SysError
{
public:
const Path path;
template<typename... Args>
FileError(const std::string & fs, const Path & path, const Args & ... args)
:SysError(fs, path, args...)
, path(path)
{
}
};
} }

View file

@ -216,7 +216,7 @@ struct stat lstat(const Path & path)
{ {
struct stat st; struct stat st;
if (lstat(path.c_str(), &st)) if (lstat(path.c_str(), &st))
throw SysError("getting status of '%1%'", path); throw FileError("getting status of '%1%'", path);
return st; return st;
} }
@ -228,7 +228,7 @@ bool pathExists(const Path & path)
res = lstat(path.c_str(), &st); res = lstat(path.c_str(), &st);
if (!res) return true; if (!res) return true;
if (errno != ENOENT && errno != ENOTDIR) if (errno != ENOENT && errno != ENOTDIR)
throw SysError("getting status of %1%", path); throw FileError("getting status of %1%", path);
return false; return false;
} }
@ -244,7 +244,7 @@ Path readLink(const Path & path)
if (errno == EINVAL) if (errno == EINVAL)
throw Error("'%1%' is not a symlink", path); throw Error("'%1%' is not a symlink", path);
else else
throw SysError("reading symbolic link '%1%'", path); throw FileError("reading symbolic link '%1%'", path);
else if (rlSize < bufSize) else if (rlSize < bufSize)
return string(buf.data(), rlSize); return string(buf.data(), rlSize);
} }
@ -276,7 +276,7 @@ DirEntries readDirectory(DIR *dir, const Path & path)
#endif #endif
); );
} }
if (errno) throw SysError("reading directory '%1%'", path); if (errno) throw FileError("reading directory '%1%'", path);
return entries; return entries;
} }
@ -284,7 +284,7 @@ DirEntries readDirectory(DIR *dir, const Path & path)
DirEntries readDirectory(const Path & path) DirEntries readDirectory(const Path & path)
{ {
AutoCloseDir dir(opendir(path.c_str())); 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); return readDirectory(dir.get(), path);
} }
@ -314,7 +314,7 @@ string readFile(const Path & path)
{ {
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd) if (!fd)
throw SysError("opening file '%1%'", path); throw FileError("opening file '%1%'", path);
return readFile(fd.get()); 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); AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd) if (!fd)
throw SysError("opening file '%s'", path); throw FileError("opening file '%s'", path);
drainFD(fd.get(), sink); 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); AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
if (!fd) if (!fd)
throw SysError("opening file '%1%'", path); throw FileError("opening file '%1%'", path);
try { try {
writeFull(fd.get(), s); writeFull(fd.get(), s);
} catch (Error & e) { } 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); AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
if (!fd) if (!fd)
throw SysError("opening file '%1%'", path); throw FileError("opening file '%1%'", path);
std::vector<char> buf(64 * 1024); std::vector<char> buf(64 * 1024);
@ -400,7 +400,7 @@ static void _deletePath(int parentfd, const Path & path, uint64_t & bytesFreed)
struct stat st; struct stat st;
if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) { if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) {
if (errno == ENOENT) return; 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) 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; const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR;
if ((st.st_mode & PERM_MASK) != PERM_MASK) { if ((st.st_mode & PERM_MASK) != PERM_MASK) {
if (fchmodat(parentfd, name.c_str(), st.st_mode | PERM_MASK, 0) == -1) 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); int fd = openat(parentfd, path.c_str(), O_RDONLY);
@ -511,7 +511,7 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
// FIXME: use O_TMPFILE. // FIXME: use O_TMPFILE.
AutoCloseFD fd(mkstemp((char *) tmpl.c_str())); AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
if (!fd) if (!fd)
throw SysError("creating temporary file '%s'", tmpl); throw FileError("creating temporary file '%s'", tmpl);
return {std::move(fd), 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) 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); 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<time_t> mtime) std::optional<time_t> mtime)
{ {
if (symlink(target.c_str(), link.c_str())) 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) { if (mtime) {
struct timeval times[2]; struct timeval times[2];
times[0].tv_sec = *mtime; 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_sec = *mtime;
times[1].tv_usec = 0; times[1].tv_usec = 0;
if (lutimes(link.c_str(), times)) 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); deletePath(path);
else { else {
if (remove(path.c_str()) == -1) if (remove(path.c_str()) == -1)
throw SysError("cannot unlink '%1%'", path); throw FileError("cannot unlink '%1%'", path);
} }
} }
} catch (...) { } catch (...) {