1use core::time::Duration;
2
3use std::time::SystemTime;
4
5use time::OffsetDateTime;
6
7use std::fs::File;
8use std::io;
9
10use std::path::Path;
11
12use io::Seek;
13
14use io::BufWriter;
15use io::Write;
16
17use io::BufRead;
18use io::Read;
19
20use zip::CompressionMethod;
21use zip::ZipWriter;
22use zip::write::SimpleFileOptions;
23
24pub use tar;
25pub use time;
26pub use zip;
27
28pub fn entry2zip<R, W>(entry: &mut tar::Entry<R>, zwtr: &mut ZipWriter<W>) -> Result<(), io::Error>
30where
31 R: Read,
32 W: Write + Seek,
33{
34 let cpat = entry.path()?;
35 let pat: &Path = &cpat;
36
37 let hdr: &tar::Header = entry.header();
38 let mtime_unixtime: u64 = hdr.mtime().ok().unwrap_or_default();
39 let mtime_duration: Duration = Duration::from_secs(mtime_unixtime);
40
41 let mtime_sys: SystemTime = SystemTime::UNIX_EPOCH
42 .checked_add(mtime_duration)
43 .unwrap_or(SystemTime::UNIX_EPOCH);
44 let mtime_o: OffsetDateTime = mtime_sys.into();
45
46 let opts: SimpleFileOptions = SimpleFileOptions::default()
47 .compression_method(CompressionMethod::Deflated)
48 .last_modified_time(mtime_o.try_into().map_err(io::Error::other)?);
49
50 let s: &str = pat
51 .as_os_str()
52 .to_str()
53 .ok_or(io::Error::other("invalid path"))?;
54 zwtr.start_file(s, opts)?;
55
56 io::copy(entry, zwtr)?;
57 Ok(())
58}
59
60pub fn tar2zip<R, W>(mut tarfile: tar::Archive<R>, mut zwtr: ZipWriter<W>) -> Result<(), io::Error>
62where
63 R: Read,
64 W: Write + Seek,
65{
66 let items = tarfile.entries()?;
67 for ritem in items {
68 let mut item: tar::Entry<_> = ritem?;
69 entry2zip(&mut item, &mut zwtr)?;
70 }
71 let mut w: W = zwtr.finish()?;
72 w.flush()
73}
74
75pub fn reader2writer<R, W>(tarfile: R, mut zwtr: W) -> Result<(), io::Error>
77where
78 R: BufRead,
79 W: Write + Seek,
80{
81 let ta = tar::Archive::new(tarfile);
82 let bw = BufWriter::new(&mut zwtr);
83 let zw = ZipWriter::new(bw);
84 tar2zip(ta, zw)?;
85 zwtr.flush()
86}
87
88pub fn stdin2file(filename: &str) -> Result<(), io::Error> {
90 let i = io::stdin();
91 let l = i.lock();
92 let f: File = File::create(filename)?;
93
94 reader2writer(l, f)
95}