use core::time::Duration;
use std::time::SystemTime;
use time::OffsetDateTime;
use std::fs::File;
use std::io;
use std::path::Path;
use io::Seek;
use io::BufWriter;
use io::Write;
use io::BufRead;
use io::Read;
use zip::CompressionMethod;
use zip::ZipWriter;
use zip::write::SimpleFileOptions;
pub use tar;
pub use time;
pub use zip;
pub fn entry2zip<R, W>(entry: &mut tar::Entry<R>, zwtr: &mut ZipWriter<W>) -> Result<(), io::Error>
where
R: Read,
W: Write + Seek,
{
let cpat = entry.path()?;
let pat: &Path = &cpat;
let hdr: &tar::Header = entry.header();
let mtime_unixtime: u64 = hdr.mtime().ok().unwrap_or_default();
let mtime_duration: Duration = Duration::from_secs(mtime_unixtime);
let mtime_sys: SystemTime = SystemTime::UNIX_EPOCH
.checked_add(mtime_duration)
.unwrap_or(SystemTime::UNIX_EPOCH);
let mtime_o: OffsetDateTime = mtime_sys.into();
let opts: SimpleFileOptions = SimpleFileOptions::default()
.compression_method(CompressionMethod::Deflated)
.last_modified_time(mtime_o.try_into().map_err(io::Error::other)?);
let s: &str = pat
.as_os_str()
.to_str()
.ok_or(io::Error::other("invalid path"))?;
zwtr.start_file(s, opts)?;
io::copy(entry, zwtr)?;
Ok(())
}
pub fn tar2zip<R, W>(mut tarfile: tar::Archive<R>, mut zwtr: ZipWriter<W>) -> Result<(), io::Error>
where
R: Read,
W: Write + Seek,
{
let items = tarfile.entries()?;
for ritem in items {
let mut item: tar::Entry<_> = ritem?;
entry2zip(&mut item, &mut zwtr)?;
}
let mut w: W = zwtr.finish()?;
w.flush()
}
pub fn reader2writer<R, W>(tarfile: R, mut zwtr: W) -> Result<(), io::Error>
where
R: BufRead,
W: Write + Seek,
{
let ta = tar::Archive::new(tarfile);
let bw = BufWriter::new(&mut zwtr);
let zw = ZipWriter::new(bw);
tar2zip(ta, zw)?;
zwtr.flush()
}
pub fn stdin2file(filename: &str) -> Result<(), io::Error> {
let i = io::stdin();
let l = i.lock();
let f: File = File::create(filename)?;
reader2writer(l, f)
}