aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/filesystem.cc
diff options
context:
space:
mode:
authorThéophane Hufschmitt <theophane@hufschmitt.net>2022-03-17 15:28:08 +0100
committerThéophane Hufschmitt <theophane.hufschmitt@tweag.io>2022-08-03 10:27:25 +0200
commit8119390abcbb25e849acc50d0af0b37d85adfb04 (patch)
treed159fb7eeba5cfd04b1cce3c235ccf4c1719d7fa /src/libutil/filesystem.cc
parent780a4793866b2cac1040d522df514645d01c492f (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.cc44
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;
+ }
+}
+
+}