mirror of
git://git.proxmox.com/git/proxmox-backup.git
synced 2025-01-08 21:18:07 +03:00
fix: #4761: unlink existing entries for hard/symlinks when overwrite
Creating symlinks or hardlinks might fail if a directory entry with the same name is already present on the filesystem during restore. When the overwrite flag is given, on failure unlink the existing entry (except directories) and retry hard/symlink creation. Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
parent
03a9f822b3
commit
e22da2f40a
@ -547,7 +547,21 @@ impl Extractor {
|
||||
link: &OsStr,
|
||||
) -> Result<(), Error> {
|
||||
let parent = self.parent_fd()?;
|
||||
nix::unistd::symlinkat(link, Some(parent), file_name)?;
|
||||
|
||||
match nix::unistd::symlinkat(link, Some(parent), file_name) {
|
||||
Ok(()) => {}
|
||||
Err(err @ nix::errno::Errno::EEXIST) => {
|
||||
if !self.overwrite {
|
||||
return Err(err.into());
|
||||
}
|
||||
// Never unlink directories
|
||||
let flag = nix::unistd::UnlinkatFlags::NoRemoveDir;
|
||||
nix::unistd::unlinkat(Some(parent), file_name, flag)?;
|
||||
nix::unistd::symlinkat(link, Some(parent), file_name)?;
|
||||
}
|
||||
Err(err) => return Err(err.into())
|
||||
}
|
||||
|
||||
metadata::apply_at(
|
||||
self.feature_flags,
|
||||
metadata,
|
||||
@ -564,13 +578,29 @@ impl Extractor {
|
||||
let parent = self.parent_fd()?;
|
||||
let root = self.dir_stack.root_dir_fd()?;
|
||||
let target = CString::new(link.as_bytes())?;
|
||||
nix::unistd::linkat(
|
||||
Some(root.as_raw_fd()),
|
||||
target.as_c_str(),
|
||||
Some(parent),
|
||||
file_name,
|
||||
nix::unistd::LinkatFlags::NoSymlinkFollow,
|
||||
)?;
|
||||
let dolink = || {
|
||||
nix::unistd::linkat(
|
||||
Some(root.as_raw_fd()),
|
||||
target.as_c_str(),
|
||||
Some(parent),
|
||||
file_name,
|
||||
nix::unistd::LinkatFlags::NoSymlinkFollow,
|
||||
)
|
||||
};
|
||||
|
||||
match dolink() {
|
||||
Ok(()) => {}
|
||||
Err(err @ nix::errno::Errno::EEXIST) => {
|
||||
if !self.overwrite {
|
||||
return Err(err.into());
|
||||
}
|
||||
// Never unlink directories
|
||||
let flag = nix::unistd::UnlinkatFlags::NoRemoveDir;
|
||||
nix::unistd::unlinkat(Some(parent), file_name, flag)?;
|
||||
dolink()?;
|
||||
}
|
||||
Err(err) => return Err(err.into())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user