.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,
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
}
_ => {
pub match_list: &'a [MatchEntry],
pub extract_match_default: bool,
pub allow_existing_dirs: bool,
+ pub overwrite: bool,
pub on_error: Option<ErrorHandler>,
}
dir,
root.metadata().clone(),
options.allow_existing_dirs,
+ options.overwrite,
feature_flags,
);
&mut decoder.contents().ok_or_else(|| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite,
),
(false, _) => Ok(()), // skip this
}
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.
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),
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))?,
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))?,
)
})?;
- 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>(
&mut file.contents().await.map_err(|_| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite,
)
.await?
}
&mut decoder.contents().ok_or_else(|| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite,
)
.await?
}