aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/filesystem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/filesystem.cc')
-rw-r--r--src/libutil/filesystem.cc175
1 files changed, 0 insertions, 175 deletions
diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc
deleted file mode 100644
index b637281d0..000000000
--- a/src/libutil/filesystem.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-#include <sys/time.h>
-#include <filesystem>
-#include <atomic>
-
-#include "finally.hh"
-#include "util.hh"
-#include "signals.hh"
-#include "types.hh"
-
-namespace fs = std::filesystem;
-
-namespace nix {
-
-static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
- std::atomic<unsigned int> & counter)
-{
- tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
- if (includePid)
- return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
- else
- return fmt("%1%/%2%-%3%", tmpRoot, prefix, counter++);
-}
-
-Path createTempDir(const Path & tmpRoot, const Path & prefix,
- bool includePid, bool useGlobalCounter, mode_t mode)
-{
- static std::atomic<unsigned int> globalCounter = 0;
- std::atomic<unsigned int> localCounter = 0;
- auto & counter(useGlobalCounter ? globalCounter : localCounter);
-
- while (1) {
- checkInterrupt();
- Path tmpDir = tempName(tmpRoot, prefix, includePid, counter);
- if (mkdir(tmpDir.c_str(), mode) == 0) {
-#if __FreeBSD__
- /* Explicitly set the group of the directory. This is to
- work around around problems caused by BSD's group
- ownership semantics (directories inherit the group of
- the parent). For instance, the group of /tmp on
- FreeBSD is "wheel", so all directories created in /tmp
- will be owned by "wheel"; but if the user is not in
- "wheel", then "tar" will fail to unpack archives that
- have the setgid bit set on directories. */
- if (chown(tmpDir.c_str(), (uid_t) -1, getegid()) != 0)
- throw SysError("setting group of directory '%1%'", tmpDir);
-#endif
- return tmpDir;
- }
- if (errno != EEXIST)
- throw SysError("creating directory '%1%'", tmpDir);
- }
-}
-
-
-std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
-{
- Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
- // Strictly speaking, this is UB, but who cares...
- // FIXME: use O_TMPFILE.
- AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
- if (!fd)
- throw SysError("creating temporary file '%s'", tmpl);
- closeOnExec(fd.get());
- return {std::move(fd), tmpl};
-}
-
-void createSymlink(const Path & target, const Path & link)
-{
- if (symlink(target.c_str(), link.c_str()))
- throw SysError("creating symlink from '%1%' to '%2%'", link, target);
-}
-
-void replaceSymlink(const Path & target, const Path & link)
-{
- for (unsigned int n = 0; true; n++) {
- Path tmp = canonPath(fmt("%s/.%d_%s", dirOf(link), n, baseNameOf(link)));
-
- try {
- createSymlink(target, tmp);
- } catch (SysError & e) {
- if (e.errNo == EEXIST) continue;
- throw;
- }
-
- renameFile(tmp, link);
-
- break;
- }
-}
-
-void setWriteTime(const fs::path & p, const struct stat & st)
-{
- struct timeval times[2];
- times[0] = {
- .tv_sec = st.st_atime,
- .tv_usec = 0,
- };
- times[1] = {
- .tv_sec = st.st_mtime,
- .tv_usec = 0,
- };
- if (lutimes(p.c_str(), times) != 0)
- throw SysError("changing modification time of '%s'", p);
-}
-
-void copy(const fs::directory_entry & from, const fs::path & to, CopyFileFlags flags)
-{
- // TODO: Rewrite the `is_*` to use `symlink_status()`
- auto statOfFrom = lstat(from.path().c_str());
- auto fromStatus = from.symlink_status();
-
- // Mark the directory as writable so that we can delete its children
- if (flags.deleteAfter && fs::is_directory(fromStatus)) {
- fs::permissions(from.path(), fs::perms::owner_write, fs::perm_options::add | fs::perm_options::nofollow);
- }
-
-
- if (fs::is_symlink(fromStatus) || fs::is_regular_file(fromStatus)) {
- auto opts = fs::copy_options::overwrite_existing;
-
- if (!flags.followSymlinks) {
- opts |= fs::copy_options::copy_symlinks;
- }
-
- fs::copy(from.path(), to, opts);
- } else if (fs::is_directory(fromStatus)) {
- fs::create_directory(to);
- for (auto & entry : fs::directory_iterator(from.path())) {
- copy(entry, to / entry.path().filename(), flags);
- }
- } else {
- throw Error("file '%s' has an unsupported type", from.path());
- }
-
- setWriteTime(to, statOfFrom);
- if (flags.deleteAfter) {
- if (!fs::is_symlink(fromStatus))
- fs::permissions(from.path(), fs::perms::owner_write, fs::perm_options::add | fs::perm_options::nofollow);
- fs::remove(from.path());
- }
-}
-
-
-void copyFile(const Path & oldPath, const Path & newPath, CopyFileFlags flags)
-{
- return copy(fs::directory_entry(fs::path(oldPath)), fs::path(newPath), flags);
-}
-
-void renameFile(const Path & oldName, const Path & newName)
-{
- fs::rename(oldName, newName);
-}
-
-void moveFile(const Path & oldName, const Path & newName)
-{
- try {
- renameFile(oldName, newName);
- } catch (fs::filesystem_error & e) {
- auto oldPath = fs::path(oldName);
- auto newPath = fs::path(newName);
- // For the move to be as atomic as possible, copy to a temporary
- // directory
- fs::path temp = createTempDir(newPath.parent_path(), "rename-tmp");
- Finally removeTemp = [&]() { fs::remove(temp); };
- auto tempCopyTarget = temp / "copy-target";
- if (e.code().value() == EXDEV) {
- fs::remove(newPath);
- warn("Can’t rename %s as %s, copying instead", oldName, newName);
- copy(fs::directory_entry(oldPath), tempCopyTarget, { .deleteAfter = true });
- renameFile(tempCopyTarget, newPath);
- }
- }
-}
-
-}