mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-06-06 18:56:36 +00:00

* Use rc-zip-sync for zip extraction Fixed #1080 In this commit, binstalk-downloader is updated to - first download the zip into a temporary file, since there is no correct way to extract zip from a stream. - then use rc-zip-sync to read from the zip and extract it to filesystem. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Fix returned `ExtractedFiles` in `do_extract_zip` Signed-off-by: Jiahao XU <30436523+NobodyXu@users.noreply.github.com> * Fix clippy in zip_extraction.rs Signed-off-by: Jiahao XU <30436523+NobodyXu@users.noreply.github.com> --------- Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> Signed-off-by: Jiahao XU <30436523+NobodyXu@users.noreply.github.com>
66 lines
2 KiB
Rust
66 lines
2 KiB
Rust
use std::{
|
|
fs::{self, create_dir_all, File},
|
|
io::{self, Read},
|
|
path::Path,
|
|
};
|
|
|
|
use cfg_if::cfg_if;
|
|
use rc_zip_sync::{rc_zip::parse::EntryKind, ReadZip};
|
|
|
|
use super::{DownloadError, ExtractedFiles};
|
|
|
|
pub(super) fn do_extract_zip(f: File, dir: &Path) -> Result<ExtractedFiles, DownloadError> {
|
|
let mut extracted_files = ExtractedFiles::new();
|
|
|
|
for entry in f.read_zip()?.entries() {
|
|
let Some(name) = entry.sanitized_name().map(Path::new) else {
|
|
continue;
|
|
};
|
|
let path = dir.join(name);
|
|
|
|
let do_extract_file = || {
|
|
let mut entry_writer = File::create(&path)?;
|
|
let mut entry_reader = entry.reader();
|
|
io::copy(&mut entry_reader, &mut entry_writer)?;
|
|
|
|
Ok::<_, io::Error>(())
|
|
};
|
|
|
|
let parent = path
|
|
.parent()
|
|
.expect("all full entry paths should have parent paths");
|
|
create_dir_all(parent)?;
|
|
|
|
match entry.kind() {
|
|
EntryKind::Symlink => {
|
|
extracted_files.add_file(name);
|
|
cfg_if! {
|
|
if #[cfg(windows)] {
|
|
do_extract_file()?;
|
|
} else {
|
|
match fs::symlink_metadata(&path) {
|
|
Ok(metadata) if metadata.is_file() => fs::remove_file(&path)?,
|
|
_ => (),
|
|
}
|
|
|
|
let mut src = String::new();
|
|
entry.reader().read_to_string(&mut src)?;
|
|
|
|
// validate pointing path before creating a symbolic link
|
|
if src.contains("..") {
|
|
continue;
|
|
}
|
|
std::os::unix::fs::symlink(src, &path)?;
|
|
}
|
|
}
|
|
}
|
|
EntryKind::Directory => (),
|
|
EntryKind::File => {
|
|
extracted_files.add_file(name);
|
|
do_extract_file()?;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(extracted_files)
|
|
}
|