]> git.proxmox.com Git - proxmox-backup.git/commitdiff
pbs-client: added overwrite parameter to PxarExtractOptions.
authorMarkus Frank <m.frank@proxmox.com>
Fri, 19 Aug 2022 10:48:46 +0000 (12:48 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Fri, 19 Aug 2022 11:36:37 +0000 (13:36 +0200)
If overwrite is true, O_TRUNC is set (to clean the leftovers)
instead of O_EXCL and therefore overwrites the files and
does not error out.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
pbs-client/src/catalog_shell.rs
pbs-client/src/pxar/extract.rs
pxar-bin/src/main.rs

index b11901ed9e0d367d16f75babc1db6ab4d05d19b2..25e27b3783652fe2eaacbaf0b0bf5b55cb26b111 100644 (file)
@@ -984,7 +984,7 @@ impl Shell {
             .clone();
 
         let extractor =
-            crate::pxar::extract::Extractor::new(rootdir, root_meta, true, Flags::DEFAULT);
+            crate::pxar::extract::Extractor::new(rootdir, root_meta, true, false, Flags::DEFAULT);
 
         let mut extractor = ExtractorState::new(
             &mut self.catalog,
@@ -1172,7 +1172,7 @@ impl<'a> ExtractorState<'a> {
                 let file_name = CString::new(entry.file_name().as_bytes())?;
                 let mut contents = entry.contents().await?;
                 self.extractor
-                    .async_extract_file(&file_name, entry.metadata(), *size, &mut contents)
+                    .async_extract_file(&file_name, entry.metadata(), *size, &mut contents, false)
                     .await
             }
             _ => {
index 161d2cef19547723245b3a02be6d87d1f3f1cd12..206e105ea907bb2fcca56b070648faed6ab74c46 100644 (file)
@@ -34,6 +34,7 @@ pub struct PxarExtractOptions<'a> {
     pub match_list: &'a [MatchEntry],
     pub extract_match_default: bool,
     pub allow_existing_dirs: bool,
+    pub overwrite: bool,
     pub on_error: Option<ErrorHandler>,
 }
 
@@ -80,6 +81,7 @@ where
         dir,
         root.metadata().clone(),
         options.allow_existing_dirs,
+        options.overwrite,
         feature_flags,
     );
 
@@ -198,6 +200,7 @@ where
                 &mut decoder.contents().ok_or_else(|| {
                     format_err!("found regular file entry without contents in archive")
                 })?,
+                extractor.overwrite,
             ),
             (false, _) => Ok(()), // skip this
         }
@@ -215,6 +218,7 @@ where
 pub struct Extractor {
     feature_flags: Flags,
     allow_existing_dirs: bool,
+    overwrite: bool,
     dir_stack: PxarDirStack,
 
     /// For better error output we need to track the current path in the Extractor state.
@@ -231,11 +235,13 @@ impl Extractor {
         root_dir: Dir,
         metadata: Metadata,
         allow_existing_dirs: bool,
+        overwrite: bool,
         feature_flags: Flags,
     ) -> Self {
         Self {
             dir_stack: PxarDirStack::new(root_dir, metadata),
             allow_existing_dirs,
+            overwrite,
             feature_flags,
             current_path: Arc::new(Mutex::new(OsString::new())),
             on_error: Box::new(Err),
@@ -392,14 +398,21 @@ impl Extractor {
         metadata: &Metadata,
         size: u64,
         contents: &mut dyn io::Read,
+        overwrite: bool,
     ) -> Result<(), Error> {
         let parent = self.parent_fd()?;
+        let mut oflags = OFlag::O_CREAT | OFlag::O_WRONLY | OFlag::O_CLOEXEC;
+        if overwrite {
+            oflags = oflags | OFlag::O_TRUNC;
+        } else {
+            oflags = oflags | OFlag::O_EXCL;
+        }
         let mut file = unsafe {
             std::fs::File::from_raw_fd(
                 nix::fcntl::openat(
                     parent,
                     file_name,
-                    OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_WRONLY | OFlag::O_CLOEXEC,
+                    oflags,
                     Mode::from_bits(0o600).unwrap(),
                 )
                 .map_err(|err| format_err!("failed to create file {:?}: {}", file_name, err))?,
@@ -448,14 +461,21 @@ impl Extractor {
         metadata: &Metadata,
         size: u64,
         contents: &mut T,
+        overwrite: bool,
     ) -> Result<(), Error> {
         let parent = self.parent_fd()?;
+        let mut oflags = OFlag::O_CREAT | OFlag::O_WRONLY | OFlag::O_CLOEXEC;
+        if overwrite {
+            oflags = oflags | OFlag::O_TRUNC;
+        } else {
+            oflags = oflags | OFlag::O_EXCL;
+        }
         let mut file = tokio::fs::File::from_std(unsafe {
             std::fs::File::from_raw_fd(
                 nix::fcntl::openat(
                     parent,
                     file_name,
-                    OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_WRONLY | OFlag::O_CLOEXEC,
+                    oflags,
                     Mode::from_bits(0o600).unwrap(),
                 )
                 .map_err(|err| format_err!("failed to create file {:?}: {}", file_name, err))?,
@@ -818,7 +838,7 @@ where
         )
     })?;
 
-    Ok(Extractor::new(dir, metadata, false, Flags::DEFAULT))
+    Ok(Extractor::new(dir, metadata, false, false, Flags::DEFAULT))
 }
 
 pub async fn extract_sub_dir<T, DEST, PATH>(
@@ -951,6 +971,7 @@ where
                     &mut file.contents().await.map_err(|_| {
                         format_err!("found regular file entry without contents in archive")
                     })?,
+                    extractor.overwrite,
                 )
                 .await?
         }
@@ -998,6 +1019,7 @@ where
                             &mut decoder.contents().ok_or_else(|| {
                                 format_err!("found regular file entry without contents in archive")
                             })?,
+                            extractor.overwrite,
                         )
                         .await?
                 }
index 3714eb032340bfe9e5bd434beb92e4db4f33f362..9d7cf9def5113376b505a641667a8e4a9c232fbf 100644 (file)
@@ -75,6 +75,11 @@ fn extract_archive_from_reader<R: std::io::Read>(
                 optional: true,
                 default: false,
             },
+            "overwrite": {
+                description: "overwrite already existing files",
+                optional: true,
+                default: false,
+            },
             "files-from": {
                 description: "File containing match pattern for files to restore.",
                 optional: true,
@@ -112,6 +117,7 @@ fn extract_archive(
     no_fcaps: bool,
     no_acls: bool,
     allow_existing_dirs: bool,
+    overwrite: bool,
     files_from: Option<String>,
     no_device_nodes: bool,
     no_fifos: bool,
@@ -179,6 +185,7 @@ fn extract_archive(
     let options = PxarExtractOptions {
         match_list: &match_list,
         allow_existing_dirs,
+        overwrite,
         extract_match_default,
         on_error,
     };