mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-06-15 15:16:37 +00:00

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>
67 lines
2 KiB
Rust
67 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() 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)?;
|
|
extracted_files.add_dir(parent);
|
|
|
|
match entry.kind() {
|
|
EntryKind::Symlink => {
|
|
extracted_files.add_file(&path);
|
|
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(&path);
|
|
do_extract_file()?;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(extracted_files)
|
|
}
|