Add shallow_copy_file_from_path,deep_copy_file_from_path and raw_copy_file_to_path, and use PathBuf in fuzz_write
This commit is contained in:
parent
0087dab984
commit
cdc2e7aa23
3 changed files with 46 additions and 28 deletions
|
@ -275,7 +275,8 @@
|
||||||
|
|
||||||
- `index_for_name`, `index_for_path`, `name_for_index`: get the index of a file given its path or vice-versa, without
|
- `index_for_name`, `index_for_path`, `name_for_index`: get the index of a file given its path or vice-versa, without
|
||||||
initializing metadata from the local-file header or needing to mutably borrow the `ZipArchive`.
|
initializing metadata from the local-file header or needing to mutably borrow the `ZipArchive`.
|
||||||
- `add_symlink_from_path`: create a symlink using `AsRef<Path>` arguments
|
- `add_symlink_from_path`, `shallow_copy_file_from_path`, `deep_copy_file_from_path`, `raw_copy_file_to_path`: copy a
|
||||||
|
file or create a symlink using `AsRef<Path>` arguments
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub enum BasicFileOperation {
|
||||||
},
|
},
|
||||||
WriteDirectory(zip::write::FullFileOptions),
|
WriteDirectory(zip::write::FullFileOptions),
|
||||||
WriteSymlinkWithTarget {
|
WriteSymlinkWithTarget {
|
||||||
target: Box<PathBuf>,
|
target: PathBuf,
|
||||||
options: zip::write::FullFileOptions,
|
options: zip::write::FullFileOptions,
|
||||||
},
|
},
|
||||||
ShallowCopy(Box<FileOperation>),
|
ShallowCopy(Box<FileOperation>),
|
||||||
|
@ -24,7 +24,7 @@ pub enum BasicFileOperation {
|
||||||
#[derive(Arbitrary, Clone, Debug)]
|
#[derive(Arbitrary, Clone, Debug)]
|
||||||
pub struct FileOperation {
|
pub struct FileOperation {
|
||||||
basic: BasicFileOperation,
|
basic: BasicFileOperation,
|
||||||
name: String,
|
path: PathBuf,
|
||||||
reopen: bool,
|
reopen: bool,
|
||||||
// 'abort' flag is separate, to prevent trying to copy an aborted file
|
// 'abort' flag is separate, to prevent trying to copy an aborted file
|
||||||
}
|
}
|
||||||
|
@ -36,20 +36,9 @@ pub struct FuzzTestCase {
|
||||||
flush_on_finish_file: bool,
|
flush_on_finish_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileOperation {
|
|
||||||
fn referenceable_name(&self) -> String {
|
|
||||||
if let BasicFileOperation::WriteDirectory(_) = self.basic {
|
|
||||||
if !self.name.ends_with('\\') && !self.name.ends_with('/') {
|
|
||||||
return self.name.to_owned() + "/";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.name.to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_operation<T>(
|
fn do_operation<T>(
|
||||||
writer: &mut RefCell<zip::ZipWriter<T>>,
|
writer: &mut RefCell<zip::ZipWriter<T>>,
|
||||||
operation: FileOperation,
|
operation: &FileOperation,
|
||||||
abort: bool,
|
abort: bool,
|
||||||
flush_on_finish_file: bool,
|
flush_on_finish_file: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>>
|
) -> Result<(), Box<dyn std::error::Error>>
|
||||||
|
@ -59,39 +48,38 @@ where
|
||||||
writer
|
writer
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_flush_on_finish_file(flush_on_finish_file);
|
.set_flush_on_finish_file(flush_on_finish_file);
|
||||||
let name = operation.name;
|
let path = &operation.path;
|
||||||
match operation.basic {
|
match &operation.basic {
|
||||||
BasicFileOperation::WriteNormalFile {
|
BasicFileOperation::WriteNormalFile {
|
||||||
contents,
|
contents,
|
||||||
mut options,
|
options,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let uncompressed_size = contents.iter().map(Vec::len).sum::<usize>();
|
let uncompressed_size = contents.iter().map(Vec::len).sum::<usize>();
|
||||||
|
let mut options = (*options).to_owned();
|
||||||
if uncompressed_size >= u32::MAX as usize {
|
if uncompressed_size >= u32::MAX as usize {
|
||||||
options = options.large_file(true);
|
options = options.large_file(true);
|
||||||
}
|
}
|
||||||
writer.borrow_mut().start_file(name, options)?;
|
writer.borrow_mut().start_file_from_path(path, options)?;
|
||||||
for chunk in contents {
|
for chunk in contents {
|
||||||
writer.borrow_mut().write_all(chunk.as_slice())?;
|
writer.borrow_mut().write_all(chunk.as_slice())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BasicFileOperation::WriteDirectory(options) => {
|
BasicFileOperation::WriteDirectory(options) => {
|
||||||
writer.borrow_mut().add_directory(name, options)?;
|
writer.borrow_mut().add_directory_from_path(path, options.to_owned())?;
|
||||||
}
|
}
|
||||||
BasicFileOperation::WriteSymlinkWithTarget { target, options } => {
|
BasicFileOperation::WriteSymlinkWithTarget { target, options } => {
|
||||||
writer
|
writer
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.add_symlink(name, target.to_string_lossy(), options)?;
|
.add_symlink_from_path(&path, target, options.to_owned())?;
|
||||||
}
|
}
|
||||||
BasicFileOperation::ShallowCopy(base) => {
|
BasicFileOperation::ShallowCopy(base) => {
|
||||||
let base_name = base.referenceable_name();
|
do_operation(writer, &base, false, flush_on_finish_file)?;
|
||||||
do_operation(writer, *base, false, flush_on_finish_file)?;
|
writer.borrow_mut().shallow_copy_file_from_path(&base.path, &path)?;
|
||||||
writer.borrow_mut().shallow_copy_file(&base_name, &name)?;
|
|
||||||
}
|
}
|
||||||
BasicFileOperation::DeepCopy(base) => {
|
BasicFileOperation::DeepCopy(base) => {
|
||||||
let base_name = base.referenceable_name();
|
do_operation(writer, &base, false, flush_on_finish_file)?;
|
||||||
do_operation(writer, *base, false, flush_on_finish_file)?;
|
writer.borrow_mut().deep_copy_file_from_path(&base.path, &path)?;
|
||||||
writer.borrow_mut().deep_copy_file(&base_name, &name)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if abort {
|
if abort {
|
||||||
|
@ -113,7 +101,7 @@ fuzz_target!(|test_case: FuzzTestCase| {
|
||||||
for (operation, abort) in test_case.operations {
|
for (operation, abort) in test_case.operations {
|
||||||
let _ = do_operation(
|
let _ = do_operation(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
operation,
|
&operation,
|
||||||
abort,
|
abort,
|
||||||
test_case.flush_on_finish_file,
|
test_case.flush_on_finish_file,
|
||||||
);
|
);
|
||||||
|
|
29
src/write.rs
29
src/write.rs
|
@ -594,6 +594,16 @@ impl<A: Read + Write + Seek> ZipWriter<A> {
|
||||||
}
|
}
|
||||||
self.finish_file()
|
self.finish_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `deep_copy_file`, but uses Path arguments.
|
||||||
|
///
|
||||||
|
/// This function ensures that the '/' path separator is used and normalizes `.` and `..`. It
|
||||||
|
/// ignores any `..` or Windows drive letter that would produce a path outside the ZIP file's
|
||||||
|
/// root.
|
||||||
|
pub fn deep_copy_file_from_path<T: AsRef<Path>, U: AsRef<Path>>(&mut self, src_path: T, dest_path: U) -> ZipResult<()>
|
||||||
|
{
|
||||||
|
self.deep_copy_file(&*path_to_string(src_path), &*path_to_string(dest_path))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write + Seek> ZipWriter<W> {
|
impl<W: Write + Seek> ZipWriter<W> {
|
||||||
|
@ -997,6 +1007,15 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `raw_copy_file_to_path`, but uses Path arguments.
|
||||||
|
///
|
||||||
|
/// This function ensures that the '/' path separator is used and normalizes `.` and `..`. It
|
||||||
|
/// ignores any `..` or Windows drive letter that would produce a path outside the ZIP file's
|
||||||
|
/// root.
|
||||||
|
pub fn raw_copy_file_to_path<P: AsRef<Path>>(&mut self, file: ZipFile, path: P) -> ZipResult<()> {
|
||||||
|
self.raw_copy_file_rename(file, path_to_string(path))
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a new file using the already compressed data from a ZIP file being read, this allows faster
|
/// Add a new file using the already compressed data from a ZIP file being read, this allows faster
|
||||||
/// copies of the `ZipFile` since there is no need to decompress and compress it again. Any `ZipFile`
|
/// copies of the `ZipFile` since there is no need to decompress and compress it again. Any `ZipFile`
|
||||||
/// metadata is copied and not checked, for example the file CRC.
|
/// metadata is copied and not checked, for example the file CRC.
|
||||||
|
@ -1219,6 +1238,16 @@ impl<W: Write + Seek> ZipWriter<W> {
|
||||||
self.insert_file_data(dest_data)?;
|
self.insert_file_data(dest_data)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `shallow_copy_file`, but uses Path arguments.
|
||||||
|
///
|
||||||
|
/// This function ensures that the '/' path separator is used and normalizes `.` and `..`. It
|
||||||
|
/// ignores any `..` or Windows drive letter that would produce a path outside the ZIP file's
|
||||||
|
/// root.
|
||||||
|
pub fn shallow_copy_file_from_path<T: AsRef<Path>, U: AsRef<Path>>(&mut self, src_path: T, dest_path: U) -> ZipResult<()>
|
||||||
|
{
|
||||||
|
self.shallow_copy_file(&*path_to_string(src_path), &*path_to_string(dest_path))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write + Seek> Drop for ZipWriter<W> {
|
impl<W: Write + Seek> Drop for ZipWriter<W> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue