diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-06-19 06:36:45 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-06-19 06:36:45 +0000 |
commit | 0536ceaf7ae28d9b0db36b58719d74c58518f949 (patch) | |
tree | 692540106c42632b16a42349650fac060ea44062 | |
parent | ace5bd80bbac17c6a913dbe58dd80505afee678c (diff) | |
parent | 8641c594b0d065f5000efd84d30333c2762ef74c (diff) | |
download | obnam2-0536ceaf7ae28d9b0db36b58719d74c58518f949.tar.gz |
Merge branch 'feature/restore-symlink-metadata' into 'main'
feat: restore symlink metadata
See merge request obnam/obnam!154
-rw-r--r-- | src/cmd/restore.rs | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs index 01e96bf..3c5b896 100644 --- a/src/cmd/restore.rs +++ b/src/cmd/restore.rs @@ -5,7 +5,7 @@ use crate::error::ObnamError; use crate::fsentry::{FilesystemEntry, FilesystemKind}; use crate::generation::{LocalGeneration, LocalGenerationError}; use indicatif::{ProgressBar, ProgressStyle}; -use libc::{chmod, mkfifo, timespec, utimensat, AT_FDCWD}; +use libc::{chmod, mkfifo, timespec, utimensat, AT_FDCWD, AT_SYMLINK_NOFOLLOW}; use log::{debug, error, info}; use std::ffi::CString; use std::io::prelude::*; @@ -209,6 +209,7 @@ fn restore_symlink(path: &Path, entry: &FilesystemEntry) -> RestoreResult<()> { } symlink(entry.symlink_target().unwrap(), path) .map_err(|err| RestoreError::Symlink(path.to_path_buf(), err))?; + restore_metadata(path, entry)?; debug!("restored symlink {}", path.display()); Ok(()) } @@ -254,15 +255,21 @@ fn restore_metadata(path: &Path, entry: &FilesystemEntry) -> RestoreResult<()> { // We have to use unsafe here to be able call the libc functions // below. unsafe { - debug!("chmod {:?}", path); - if chmod(path.as_ptr(), entry.mode()) == -1 { - let error = Error::last_os_error(); - error!("chmod failed on {:?}", path); - return Err(RestoreError::Chmod(pathbuf, error)); + if entry.kind() != FilesystemKind::Symlink { + debug!("chmod {:?}", path); + if chmod(path.as_ptr(), entry.mode()) == -1 { + let error = Error::last_os_error(); + error!("chmod failed on {:?}", path); + return Err(RestoreError::Chmod(pathbuf, error)); + } + } else { + debug!( + "skipping chmod of a symlink because it'll attempt to change the pointed-at file" + ); } debug!("utimens {:?}", path); - if utimensat(AT_FDCWD, path.as_ptr(), times, 0) == -1 { + if utimensat(AT_FDCWD, path.as_ptr(), times, AT_SYMLINK_NOFOLLOW) == -1 { let error = Error::last_os_error(); error!("utimensat failed on {:?}", path); return Err(RestoreError::SetTimestamp(pathbuf, error)); |