From d9c51ec4e5919245dcc5e9f2f5532f4d85be5218 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Fri, 12 Jul 2024 16:15:33 -0600 Subject: [PATCH] libutil: implement a realPath() utility Just a wrapper around POSIX realpath(). Change-Id: I2593770285dbae573eace490efce5b272b00b001 --- src/libutil/file-system.cc | 19 +++++++++++++++++++ src/libutil/file-system.hh | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 278e5187c..f0199d36f 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -1,4 +1,5 @@ #include +#include #include #include @@ -106,6 +107,24 @@ Path canonPath(PathView path, bool resolveSymlinks) return s.empty() ? "/" : std::move(s); } +Path realPath(Path const & path) +{ + // With nullptr, realpath() malloc's and returns a new c-string. + char * resolved = realpath(path.c_str(), nullptr); + int saved = errno; + if (resolved == nullptr) { + throw SysError(saved, "cannot get realpath for '%s'", path); + } + + Finally const _free([&] { free(resolved); }); + + // There's not really a from_raw_parts() for std::string. + // The copy is not a big deal. + Path ret(resolved); + + return ret; +} + void chmodPath(const Path & path, mode_t mode) { if (chmod(path.c_str(), mode) == -1) diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 636c13f13..e49323e84 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -46,6 +46,22 @@ Path absPath(Path path, */ Path canonPath(PathView path, bool resolveSymlinks = false); +/** + * Resolves a file path to a fully absolute path with no symbolic links. + * + * @param path The path to resolve. If it is relative, it will be resolved relative + * to the process's current directory. + * + * @note This is not a pure function; it performs this resolution by querying + * the filesystem. + * + * @note @ref path sadly must be (a reference to) an owned string, as std::string_view + * are not valid C strings... + * + * @return The fully resolved path. + */ +Path realPath(Path const & path); + /** * Change the permissions of a path * Not called `chmod` as it shadows and could be confused with