Skip to main content

rs_tar2zip/
lib.rs

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
28/// Adds a tar entry to the zip.
29pub 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
60/// Adds all items in the tar archive to the zip.
61pub 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
75/// Adds all items in the tar archive(Read) to the zip(Write).
76pub 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
88/// Adds all items in the tar archive(stdin) to the zip(file).
89pub 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}