rename: Fallback to a copy if the filesystems mismatch
In `nix::rename`, if the call to `rename` fails with `EXDEV` (failure because the source and the destination are in a different filesystems) switch to copying and removing the source. To avoid having to re-implement the copy manually, I switched the function to use the c++17 `filesystem` library (which has a `copy` function that should do what we want). Fix #6262
This commit is contained in:
parent
c2de0a232c
commit
6f89fb6008
1 changed files with 13 additions and 2 deletions
|
@ -1,8 +1,11 @@
|
|||
#include <sys/time.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "util.hh"
|
||||
#include "types.hh"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace nix {
|
||||
|
||||
void createSymlink(const Path & target, const Path & link,
|
||||
|
@ -42,8 +45,16 @@ void replaceSymlink(const Path & target, const Path & link,
|
|||
|
||||
void moveFile(const Path & oldName, const Path & newName)
|
||||
{
|
||||
if (::rename(oldName.c_str(), newName.c_str()))
|
||||
throw SysError("renaming '%1%' to '%2%'", oldName, newName);
|
||||
auto oldPath = fs::path(oldName);
|
||||
auto newPath = fs::path(newName);
|
||||
try {
|
||||
fs::rename(oldPath, newPath);
|
||||
} catch (fs::filesystem_error & e) {
|
||||
if (e.code().value() == EXDEV) {
|
||||
fs::copy(oldName, newName, fs::copy_options::copy_symlinks);
|
||||
fs::remove_all(oldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue