diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index ffb14c42ec7..0324d98f040 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -710,7 +710,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS) try { cwd = std::filesystem::current_path(); } catch (std::filesystem::filesystem_error & e) { - throw SysError("cannot determine current working directory"); + throw SystemError(e.code(), "cannot determine current working directory"); } auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, cwd.string(), true); diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 9b33d8e91eb..e3bce13b215 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -247,7 +247,8 @@ static void initRepoAtomically(std::filesystem::path & path, GitRepo::Options op || e.code() == std::errc::directory_not_empty) { return; } else - throw SysError("moving temporary git repository from %s to %s", PathFmt(tmpDir), PathFmt(path)); + throw SystemError( + e.code(), "moving temporary git repository from %s to %s", PathFmt(tmpDir), PathFmt(path)); } // we successfully moved the repository, so the temporary directory no longer exists. delTmpDir.cancel(); diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index 317cbe9ef1f..f1b30572d88 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -36,8 +36,8 @@ static void builtinUnpackChannel(const BuiltinBuilderContext & ctx) auto target = out / channelName; try { std::filesystem::rename(fileName, target); - } catch (std::filesystem::filesystem_error &) { - throw SysError("failed to rename %1% to %2%", fileName, target.string()); + } catch (std::filesystem::filesystem_error & e) { + throw SystemError(e.code(), "failed to rename %1% to %2%", fileName, target.string()); } } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 15642dcd6d4..2424bdce55d 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -272,7 +272,7 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R || e.code() == std::errc::not_a_directory) printInfo("cannot read potential root '%1%'", path); else - throw; + throw SystemError(e.code(), "finding GC roots in '%1%'", path); } catch (SystemError & e) { diff --git a/src/libstore/local-gc.cc b/src/libstore/local-gc.cc index 9e3bbfb5ccc..681ac28c514 100644 --- a/src/libstore/local-gc.cc +++ b/src/libstore/local-gc.cc @@ -35,7 +35,7 @@ static void readProcLink(const std::filesystem::path & file, UncheckedRoots & ro if (e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::permission_denied || e.code() == std::errc::no_such_process) return; - throw; + throw SystemError(e.code(), "reading symlink '%s'", PathFmt(file)); } if (buf.is_absolute()) roots[buf.string()].emplace(file.string()); diff --git a/src/libstore/machines.cc b/src/libstore/machines.cc index f5f630ad01d..1a97f96a250 100644 --- a/src/libstore/machines.cc +++ b/src/libstore/machines.cc @@ -111,8 +111,8 @@ static std::vector expandBuilderLines(const std::string & builders) std::string text; try { text = readFile(path); - } catch (const SysError & e) { - if (e.errNo != ENOENT) + } catch (const SystemError & e) { + if (!e.is(std::errc::no_such_file_or_directory)) throw; debug("cannot find machines file '%s'", path); continue; diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index efdf748826f..9e5cc77ab5c 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -202,14 +202,13 @@ void LocalStore::optimisePath_( full. When that happens, it's fine to ignore it: we just effectively disable deduplication of this file. - TODO: Get rid of errno, use error code. */ - printInfo("cannot link %s to '%s': %s", PathFmt(linkPath), path, strerror(errno)); + printInfo("cannot link %s to '%s': %s", PathFmt(linkPath), path, e.code().message()); return; } else - throw; + throw SystemError(e.code(), "creating hard link from %1% to %2%", PathFmt(linkPath), path); } } @@ -250,7 +249,7 @@ void LocalStore::optimisePath_( printInfo("%1% has maximum number of links", PathFmt(linkPath)); return; } - throw; + throw SystemError(e.code(), "creating hard link from %1% to %2%", PathFmt(linkPath), PathFmt(tempLink)); } /* Atomically replace the old file with the new hard link. */ @@ -271,7 +270,7 @@ void LocalStore::optimisePath_( debug("%s has reached maximum number of links", PathFmt(linkPath)); return; } - throw; + throw SystemError(e.code(), "renaming %1% to %2%", PathFmt(tempLink), path); } stats.filesLinked++; diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc index b0126351a21..c90ed1e5023 100644 --- a/src/libstore/profiles.cc +++ b/src/libstore/profiles.cc @@ -103,7 +103,7 @@ static void removeFile(const std::filesystem::path & path) try { std::filesystem::remove(path); } catch (std::filesystem::filesystem_error & e) { - throw SysError("removing file %1%", PathFmt(path)); + throw SystemError(e.code(), "removing file %1%", PathFmt(path)); } } @@ -324,8 +324,6 @@ std::filesystem::path getDefaultProfile(ProfileDirsOptions settings) return absPath(readLink(profileLink), &linkDir); } catch (Error &) { return profileLink; - } catch (std::filesystem::filesystem_error &) { - return profileLink; } } diff --git a/src/libutil-tests/file-system.cc b/src/libutil-tests/file-system.cc index e96694ff7c6..6bfcb7d0c00 100644 --- a/src/libutil-tests/file-system.cc +++ b/src/libutil-tests/file-system.cc @@ -319,7 +319,7 @@ TEST(chmodIfNeeded, works) TEST(chmodIfNeeded, nonexistent) { - ASSERT_THROW(chmodIfNeeded("/schnitzel/darmstadt/pommes", 0755), SysError); + ASSERT_THROW(chmodIfNeeded("/schnitzel/darmstadt/pommes", 0755), SystemError); } /* ---------------------------------------------------------------------------- @@ -340,7 +340,7 @@ TEST(DirectoryIterator, works) TEST(DirectoryIterator, nonexistent) { - ASSERT_THROW(DirectoryIterator("/schnitzel/darmstadt/pommes"), SysError); + ASSERT_THROW(DirectoryIterator("/schnitzel/darmstadt/pommes"), SystemError); } /* ---------------------------------------------------------------------------- diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 2f671627ff9..4458a3a8362 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -40,9 +40,9 @@ DirectoryIterator::DirectoryIterator(const std::filesystem::path & p) // **Attempt to create the underlying directory_iterator** it_ = std::filesystem::directory_iterator(p); } catch (const std::filesystem::filesystem_error & e) { - // **Catch filesystem_error and throw SysError** - // Adapt the error message as needed for SysError - throw SysError("cannot read directory %s", PathFmt(p)); + // **Catch filesystem_error and throw SystemError** + // Adapt the error message as needed for SystemError + throw SystemError(e.code(), "cannot read directory %s", PathFmt(p)); } } @@ -280,7 +280,11 @@ bool pathAccessible(const std::filesystem::path & path) std::filesystem::path readLink(const std::filesystem::path & path) { checkInterrupt(); - return std::filesystem::read_symlink(path); + try { + return std::filesystem::read_symlink(path); + } catch (std::filesystem::filesystem_error & e) { + throw SystemError(e.code(), "reading symbolic link '%s'", PathFmt(path)); + } } Path readLink(const Path & path) @@ -463,7 +467,7 @@ void createDirs(const std::filesystem::path & path) try { std::filesystem::create_directories(path); } catch (std::filesystem::filesystem_error & e) { - throw SysError("creating directory '%1%'", path.string()); + throw SystemError(e.code(), "creating directory '%1%'", path.string()); } } @@ -664,7 +668,7 @@ void replaceSymlink(const std::filesystem::path & target, const std::filesystem: } catch (std::filesystem::filesystem_error & e) { if (e.code() == std::errc::file_exists) continue; - throw SysError("creating symlink %1% -> %2%", PathFmt(tmp), PathFmt(target)); + throw SystemError(e.code(), "creating symlink %1% -> %2%", PathFmt(tmp), PathFmt(target)); } try { @@ -672,7 +676,7 @@ void replaceSymlink(const std::filesystem::path & target, const std::filesystem: } catch (std::filesystem::filesystem_error & e) { if (e.code() == std::errc::file_exists) continue; - throw SysError("renaming %1% to %2%", PathFmt(tmp), PathFmt(link)); + throw SystemError(e.code(), "renaming %1% to %2%", PathFmt(tmp), PathFmt(link)); } break; @@ -773,7 +777,7 @@ std::filesystem::path makeParentCanonical(const std::filesystem::path & rawPath) } return std::filesystem::canonical(parent) / path.filename(); } catch (std::filesystem::filesystem_error & e) { - throw SysError("canonicalising parent path of %1%", PathFmt(path)); + throw SystemError(e.code(), "canonicalising parent path of %1%", PathFmt(path)); } } diff --git a/src/libutil/include/nix/util/error.hh b/src/libutil/include/nix/util/error.hh index 4f6d2363d05..d9babf34d1c 100644 --- a/src/libutil/include/nix/util/error.hh +++ b/src/libutil/include/nix/util/error.hh @@ -127,20 +127,20 @@ public: BaseError & operator=(BaseError &&) = default; template - BaseError(unsigned int status, const Args &... args) - : err{.level = lvlError, .msg = HintFmt(args...), .pos = {}, .status = status} + BaseError(unsigned int status, Args &&... args) + : err{.level = lvlError, .msg = HintFmt(std::forward(args)...), .pos = {}, .status = status} { } template - explicit BaseError(const std::string & fs, const Args &... args) - : err{.level = lvlError, .msg = HintFmt(fs, args...), .pos = {}} + explicit BaseError(const std::string & fs, Args &&... args) + : err{.level = lvlError, .msg = HintFmt(fs, std::forward(args)...), .pos = {}} { } template - BaseError(const Suggestions & sug, const Args &... args) - : err{.level = lvlError, .msg = HintFmt(args...), .pos = {}, .suggestions = sug} + BaseError(const Suggestions & sug, Args &&... args) + : err{.level = lvlError, .msg = HintFmt(std::forward(args)...), .pos = {}, .suggestions = sug} { } @@ -204,9 +204,9 @@ public: * @param args... Format string arguments. */ template - void addTrace(std::shared_ptr && pos, std::string_view fs, const Args &... args) + void addTrace(std::shared_ptr && pos, std::string_view fs, Args &&... args) { - addTrace(std::move(pos), HintFmt(std::string(fs), args...)); + addTrace(std::move(pos), HintFmt(std::string(fs), std::forward(args)...)); } /** @@ -248,19 +248,39 @@ MakeError(UnimplementedError, Error); class SystemError : public Error { std::error_code errorCode; + std::string errorDetails; -public: +protected: + + /** + * Just here to allow derived classes to use the right constructor + * (the protected one). + */ + struct Disambig + {}; + + /** + * Protected constructor for subclasses that provide their own error message. + * The error message is appended to the formatted hint. + */ template - SystemError(std::errc posixErrNo, Args &&... args) - : Error(std::forward(args)...) - , errorCode(std::make_error_code(posixErrNo)) + SystemError(Disambig, std::error_code errorCode, std::string_view errorDetails, Args &&... args) + : Error("") + , errorCode(errorCode) + , errorDetails(errorDetails) { + auto hf = HintFmt(std::forward(args)...); + err.msg = HintFmt("%s: %s", Uncolored(hf.str()), errorDetails); } +public: + /** + * Construct with an error code. The error code's message is automatically + * appended to the error message. + */ template SystemError(std::error_code errorCode, Args &&... args) - : Error(std::forward(args)...) - , errorCode(errorCode) + : SystemError(Disambig{}, errorCode, errorCode.message(), std::forward(args)...) { } @@ -301,12 +321,14 @@ public: * will be used to try to add additional information to the message. */ template - SysError(int errNo, const Args &... args) - : SystemError(static_cast(errNo), "") + SysError(int errNo, Args &&... args) + : SystemError( + Disambig{}, + std::make_error_code(static_cast(errNo)), + strerror(errNo), + std::forward(args)...) , errNo(errNo) { - auto hf = HintFmt(args...); - err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), strerror(errNo)); } /** @@ -316,8 +338,8 @@ public: * calling this constructor! */ template - SysError(const Args &... args) - : SysError(errno, args...) + SysError(Args &&... args) + : SysError(errno, std::forward(args)...) { } }; @@ -381,12 +403,14 @@ public: * information to the message. */ template - WinError(DWORD lastError, const Args &... args) - : SystemError(std::error_code(lastError, std::system_category()), "") + WinError(DWORD lastError, Args &&... args) + : SystemError( + Disambig{}, + std::error_code(lastError, std::system_category()), + renderError(lastError), + std::forward(args)...) , lastError(lastError) { - auto hf = HintFmt(args...); - err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), renderError(lastError)); } /** @@ -396,14 +420,14 @@ public: * before calling this constructor! */ template - WinError(const Args &... args) - : WinError(GetLastError(), args...) + WinError(Args &&... args) + : WinError(GetLastError(), std::forward(args)...) { } private: - std::string renderError(DWORD lastError); + static std::string renderError(DWORD lastError); }; } // namespace windows diff --git a/src/libutil/include/nix/util/file-system-at.hh b/src/libutil/include/nix/util/file-system-at.hh index b1b636d83b8..4026e68e5d8 100644 --- a/src/libutil/include/nix/util/file-system-at.hh +++ b/src/libutil/include/nix/util/file-system-at.hh @@ -75,7 +75,7 @@ namespace linux { * * @see https://man7.org/linux/man-pages/man2/openat2.2.html * @see https://man7.org/linux/man-pages/man2/open_how.2type.html -v* + * * @param flags O_* flags * @param mode Mode for O_{CREAT,TMPFILE} * @param resolve RESOLVE_* flags diff --git a/src/libutil/include/nix/util/file-system.hh b/src/libutil/include/nix/util/file-system.hh index 6fd30196213..310daa01efe 100644 --- a/src/libutil/include/nix/util/file-system.hh +++ b/src/libutil/include/nix/util/file-system.hh @@ -189,21 +189,19 @@ Path readLink(const Path & path); */ std::filesystem::path readLink(const std::filesystem::path & path); -#ifdef _WIN32 -namespace windows { - /** - * Get the path associated with a file handle. + * Get the path associated with a file descriptor. * * @note One MUST only use this for error handling, because it creates * TOCTOU issues. We don't mind if error messages point to out of date * paths (that is a rather trivial TOCTOU --- the error message is best * effort) but for anything else we do. + * + * @note this function will clobber `errno` (Unix) / "last error" + * (Windows), so care must be used to get those error codes, then call + * this, then build a `SysError` / `WinError` with the saved error code. */ -std::filesystem::path handleToPath(Descriptor handle); - -} // namespace windows -#endif +std::filesystem::path descriptorToPath(Descriptor fd); /** * Open a `Descriptor` with read-only access to the given directory. diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 6b21696f024..bc3af9c0288 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -170,7 +170,7 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & if (e.code() == std::errc::permission_denied || e.code() == std::errc::operation_not_permitted) return std::nullopt; else - throw; + throw SystemError(e.code(), "getting status of '%s'", PathFmt(entry.path())); } }(); res.emplace(entry.path().filename().string(), type); diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index ec01f337de9..86177d01bef 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -49,7 +49,8 @@ void readFull(int fd, char * buf, size_t count) pollFD(fd, POLLIN); continue; } - throw SysError("reading from file"); + auto savedErrno = errno; + throw SysError(savedErrno, "reading from file %s", PathFmt(descriptorToPath(fd))); } if (res == 0) throw EndOfFile("unexpected end-of-file"); @@ -72,7 +73,8 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts) pollFD(fd, POLLOUT); continue; } - throw SysError("writing to file"); + auto savedErrno = errno; + throw SysError(savedErrno, "writing to file %s", PathFmt(descriptorToPath(fd))); } if (res > 0) s.remove_prefix(res); @@ -95,8 +97,10 @@ std::string readLine(int fd, bool eofOk, char terminator) pollFD(fd, POLLIN); continue; } - default: - throw SysError("reading a line"); + default: { + auto savedErrno = errno; + throw SysError(savedErrno, "reading a line from %s", PathFmt(descriptorToPath(fd))); + } } } else if (rd == 0) { if (eofOk) diff --git a/src/libutil/unix/file-system-at.cc b/src/libutil/unix/file-system-at.cc index 866cdd31ced..85c90f6972d 100644 --- a/src/libutil/unix/file-system-at.cc +++ b/src/libutil/unix/file-system-at.cc @@ -71,8 +71,10 @@ void unix::fchmodatTryNoFollow(Descriptor dirFd, const CanonPath & path, mode_t if (res < 0) { if (errno == ENOSYS) fchmodat2Unsupported.test_and_set(); - else - throw SysError("fchmodat2 '%s' relative to parent directory", path.rel()); + else { + auto savedErrno = errno; + throw SysError(savedErrno, "fchmodat2 %s", PathFmt(descriptorToPath(dirFd) / path.rel())); + } } else return; } @@ -80,10 +82,13 @@ void unix::fchmodatTryNoFollow(Descriptor dirFd, const CanonPath & path, mode_t #ifdef __linux__ AutoCloseFD pathFd = ::openat(dirFd, path.rel_c_str(), O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (!pathFd) + if (!pathFd) { + auto savedErrno = errno; throw SysError( - "opening '%s' relative to parent directory to get an O_PATH file descriptor (fchmodat2 is unsupported)", - path.rel()); + savedErrno, + "opening %s to get an O_PATH file descriptor (fchmodat2 is unsupported)", + PathFmt(descriptorToPath(dirFd) / path.rel())); + } struct ::stat st; /* Possible since https://github.com/torvalds/linux/commit/55815f70147dcfa3ead5738fd56d3574e2e3c1c2 (3.6) */ @@ -91,7 +96,7 @@ void unix::fchmodatTryNoFollow(Descriptor dirFd, const CanonPath & path, mode_t throw SysError("statting '%s' relative to parent directory via O_PATH file descriptor", path.rel()); if (S_ISLNK(st.st_mode)) - throw SysError(EOPNOTSUPP, "can't change mode of symlink '%s' relative to parent directory", path.rel()); + throw SysError(EOPNOTSUPP, "can't change mode of symlink %s", PathFmt(descriptorToPath(dirFd) / path.rel())); static std::atomic_flag dontHaveProc{}; if (!dontHaveProc.test()) { @@ -101,8 +106,11 @@ void unix::fchmodatTryNoFollow(Descriptor dirFd, const CanonPath & path, mode_t if (int res = ::chmod(selfProcFdPath.c_str(), mode); res == -1) { if (errno == ENOENT) dontHaveProc.test_and_set(); - else - throw SysError("chmod '%s' ('%s' relative to parent directory)", selfProcFdPath, path); + else { + auto savedErrno = errno; + throw SysError( + savedErrno, "chmod %s (%s)", selfProcFdPath, PathFmt(descriptorToPath(dirFd) / path.rel())); + } } else return; } @@ -122,8 +130,10 @@ void unix::fchmodatTryNoFollow(Descriptor dirFd, const CanonPath & path, mode_t #endif ); - if (res == -1) - throw SysError("fchmodat '%s' relative to parent directory", path.rel()); + if (res == -1) { + auto savedErrno = errno; + throw SysError(savedErrno, "fchmodat %s", PathFmt(descriptorToPath(dirFd) / path.rel())); + } } static Descriptor @@ -206,9 +216,10 @@ OsString readLinkAt(Descriptor dirFd, const CanonPath & path) checkInterrupt(); buf.resize(bufSize); ssize_t rlSize = ::readlinkat(dirFd, path.rel_c_str(), buf.data(), bufSize); - if (rlSize == -1) - throw SysError("reading symbolic link '%1%' relative to parent directory", path.rel()); - else if (rlSize < bufSize) + if (rlSize == -1) { + auto savedErrno = errno; + throw SysError(savedErrno, "reading symbolic link %1%", PathFmt(descriptorToPath(dirFd) / path.rel())); + } else if (rlSize < bufSize) return {buf.data(), static_cast(rlSize)}; } } diff --git a/src/libutil/unix/file-system.cc b/src/libutil/unix/file-system.cc index d3b6cbe28a3..3598bc8dee7 100644 --- a/src/libutil/unix/file-system.cc +++ b/src/libutil/unix/file-system.cc @@ -46,6 +46,31 @@ Descriptor openNewFileForWrite(const std::filesystem::path & path, mode_t mode, return open(path.c_str(), flags, mode); } +std::filesystem::path descriptorToPath(Descriptor fd) +{ + if (fd == STDIN_FILENO) + return ""; + if (fd == STDOUT_FILENO) + return ""; + if (fd == STDERR_FILENO) + return ""; + +#if defined(__linux__) + try { + return readLink("/proc/self/fd/" + std::to_string(fd)); + } catch (SystemError &) { + } +#elif HAVE_F_GETPATH + /* F_GETPATH requires PATH_MAX buffer per POSIX */ + char buf[PATH_MAX]; + if (fcntl(fd, F_GETPATH, buf) != -1) + return buf; +#endif + + /* Fallback for unknown fd or unsupported platform */ + return ""; +} + std::filesystem::path defaultTempDir() { return getEnvNonEmpty("TMPDIR").value_or("/tmp"); diff --git a/src/libutil/unix/meson.build b/src/libutil/unix/meson.build index e59b4b6386d..7859707fe88 100644 --- a/src/libutil/unix/meson.build +++ b/src/libutil/unix/meson.build @@ -8,6 +8,12 @@ configdata_unix.set( description : 'Optionally used for changing the files and symlinks.', ) +configdata_unix.set( + 'HAVE_F_GETPATH', + cxx.has_header_symbol('fcntl.h', 'F_GETPATH').to_int(), + description : 'Optionally used for getting the path of a file descriptor (macOS).', +) + # Check for each of these functions, and create a define like `#define # HAVE_CLOSE_RANGE 1`. check_funcs_unix = [ diff --git a/src/libutil/windows/file-descriptor.cc b/src/libutil/windows/file-descriptor.cc index bd50e40be79..44a13cc9154 100644 --- a/src/libutil/windows/file-descriptor.cc +++ b/src/libutil/windows/file-descriptor.cc @@ -45,9 +45,9 @@ void writeFull(HANDLE handle, std::string_view s, bool allowInterrupts) checkInterrupt(); DWORD res; if (!WriteFile(handle, s.data(), s.size(), &res, NULL)) { - // Do this because `handleToPath` will overwrite the last error. + // Do this because `descriptorToPath` will overwrite the last error. auto lastError = GetLastError(); - auto path = handleToPath(handle); + auto path = descriptorToPath(handle); throw WinError(lastError, "writing to file %d:%s", handle, PathFmt(path)); } if (res > 0) diff --git a/src/libutil/windows/file-system-at.cc b/src/libutil/windows/file-system-at.cc index 4e012bb0867..db4a3b0d663 100644 --- a/src/libutil/windows/file-system-at.cc +++ b/src/libutil/windows/file-system-at.cc @@ -156,13 +156,13 @@ OsString readSymlinkTarget(HANDLE linkHandle) size_t path_buf_offset = offsetof(ReparseDataBuffer, SymbolicLinkReparseBuffer.PathBuffer[0]); if (out < path_buf_offset) { - auto fullPath = handleToPath(linkHandle); + auto fullPath = descriptorToPath(linkHandle); throw WinError( DWORD{ERROR_REPARSE_TAG_INVALID}, "invalid reparse data for %d:%s", linkHandle, PathFmt(fullPath)); } if (reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) { - auto fullPath = handleToPath(linkHandle); + auto fullPath = descriptorToPath(linkHandle); throw WinError(DWORD{ERROR_REPARSE_TAG_INVALID}, "not a symlink: %d:%s", linkHandle, PathFmt(fullPath)); } @@ -179,7 +179,7 @@ OsString readSymlinkTarget(HANDLE linkHandle) } if (path_buf_offset + name_offset + name_length > out) { - auto fullPath = handleToPath(linkHandle); + auto fullPath = descriptorToPath(linkHandle); throw WinError( DWORD{ERROR_REPARSE_TAG_INVALID}, "invalid symlink data for %d:%s", linkHandle, PathFmt(fullPath)); } diff --git a/src/libutil/windows/file-system.cc b/src/libutil/windows/file-system.cc index e3b74fe392f..5b770e60a23 100644 --- a/src/libutil/windows/file-system.cc +++ b/src/libutil/windows/file-system.cc @@ -83,7 +83,7 @@ void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed) deletePath(path); } -std::filesystem::path windows::handleToPath(HANDLE handle) +std::filesystem::path descriptorToPath(Descriptor handle) { std::vector buf(0x100); DWORD dw = GetFinalPathNameByHandleW(handle, buf.data(), buf.size(), FILE_NAME_OPENED); diff --git a/src/nix/nix-collect-garbage/nix-collect-garbage.cc b/src/nix/nix-collect-garbage/nix-collect-garbage.cc index ec6ede80c2b..88fbc9db0e2 100644 --- a/src/nix/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix/nix-collect-garbage/nix-collect-garbage.cc @@ -43,8 +43,8 @@ void removeOldGenerations(std::filesystem::path dir) std::string link; try { link = readLink(path); - } catch (std::filesystem::filesystem_error & e) { - if (e.code() == std::errc::no_such_file_or_directory) + } catch (SystemError & e) { + if (e.is(std::errc::no_such_file_or_directory)) continue; throw; } diff --git a/src/nix/nix-env/nix-env.cc b/src/nix/nix-env/nix-env.cc index 4a46e7ca65b..18bb2c74a03 100644 --- a/src/nix/nix-env/nix-env.cc +++ b/src/nix/nix-env/nix-env.cc @@ -1419,7 +1419,6 @@ static int main_nix_env(int argc, char ** argv) replaceSymlink(defaultChannelsDir(profilesDirOpts), nixExprPath / "channels"); if (!isRootUser()) replaceSymlink(rootChannelsDir(profilesDirOpts), nixExprPath / "channels_root"); - } catch (std::filesystem::filesystem_error &) { } catch (Error &) { } }