diff options
author | Théophane Hufschmitt <theophane@hufschmitt.net> | 2022-03-17 15:28:08 +0100 |
---|---|---|
committer | Théophane Hufschmitt <theophane.hufschmitt@tweag.io> | 2022-08-03 10:27:25 +0200 |
commit | 8119390abcbb25e849acc50d0af0b37d85adfb04 (patch) | |
tree | d159fb7eeba5cfd04b1cce3c235ccf4c1719d7fa /src/libutil/filesystem.cc | |
parent | 780a4793866b2cac1040d522df514645d01c492f (diff) |
Move some fs-related functions to their own file
Unclutter `util.cc` a bit
Diffstat (limited to 'src/libutil/filesystem.cc')
-rw-r--r-- | src/libutil/filesystem.cc | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc new file mode 100644 index 000000000..e67383e6f --- /dev/null +++ b/src/libutil/filesystem.cc @@ -0,0 +1,44 @@ +#include <sys/time.h> + +#include "util.hh" +#include "types.hh" + +namespace nix { + +void createSymlink(const Path & target, const Path & link, + std::optional<time_t> mtime) +{ + if (symlink(target.c_str(), link.c_str())) + throw SysError("creating symlink from '%1%' to '%2%'", link, target); + if (mtime) { + struct timeval times[2]; + times[0].tv_sec = *mtime; + times[0].tv_usec = 0; + times[1].tv_sec = *mtime; + times[1].tv_usec = 0; + if (lutimes(link.c_str(), times)) + throw SysError("setting time of symlink '%s'", link); + } +} + +void replaceSymlink(const Path & target, const Path & link, + std::optional<time_t> mtime) +{ + for (unsigned int n = 0; true; n++) { + Path tmp = canonPath(fmt("%s/.%d_%s", dirOf(link), n, baseNameOf(link))); + + try { + createSymlink(target, tmp, mtime); + } catch (SysError & e) { + if (e.errNo == EEXIST) continue; + throw; + } + + if (rename(tmp.c_str(), link.c_str()) != 0) + throw SysError("renaming '%1%' to '%2%'", tmp, link); + + break; + } +} + +} |