1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use std::fs::{self, File};
use std::io;
use std::path::Path;
use walkdir::WalkDir;
use self::zip_rs::result::{ZipError, ZipResult};
use self::zip_rs::write::FileOptions;
use zip as zip_rs;
pub fn compress(src_dir: &Path, dst_file: &File) -> ZipResult<()> {
if !Path::new(src_dir).is_dir() {
return Err(ZipError::Io(io::Error::new(
io::ErrorKind::Other,
"Source must be a directory.",
)));
}
let options = FileOptions::default()
.compression_method(zip_rs::CompressionMethod::Stored)
.unix_permissions(0o644);
let mut zip = zip_rs::ZipWriter::new(dst_file);
let walkdir = WalkDir::new(src_dir.to_str().unwrap());
let it = walkdir.into_iter();
for dent in it.filter_map(|e| e.ok()) {
let path = dent.path();
let name = path
.strip_prefix(Path::new(src_dir))
.unwrap()
.to_str()
.unwrap();
if path.is_file() {
zip.start_file(name, options)?;
let mut f = File::open(path)?;
io::copy(&mut f, &mut zip)?;
}
}
zip.finish()?;
dst_file.sync_all()?;
Ok(())
}
pub fn decompress<R>(src_file: R, dest: &Path) -> ZipResult<()>
where
R: io::Read + io::Seek,
{
let mut archive = zip_rs::ZipArchive::new(src_file)?;
for i in 0..archive.len() {
let mut file = archive.by_index(i)?;
let file_path = dest.join(file.name());
if (&*file.name()).ends_with('/') {
fs::create_dir_all(&file_path)?;
} else {
if let Some(p) = file_path.parent() {
if !p.exists() {
fs::create_dir_all(&p)?;
}
}
let mut outfile = fs::File::create(&file_path)?;
io::copy(&mut file, &mut outfile)?;
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Some(mode) = file.unix_mode() {
fs::set_permissions(
&file_path.to_str().unwrap(),
PermissionsExt::from_mode(mode),
)?;
}
}
}
Ok(())
}