1use std::borrow::Cow;
2use std::io;
3use std::path::Path;
4
5use io::Read;
6
7use tar::Archive;
8use tar::Entry;
9use tar::Header;
10
11use crate::core::TarEntry;
12
13pub fn header2size(hdr: &Header) -> Result<u64, io::Error> {
14 hdr.size()
15}
16
17pub fn header2mode(hdr: &Header) -> Result<u32, io::Error> {
18 hdr.mode()
19}
20
21pub fn header2mtime(hdr: &Header) -> Result<u64, io::Error> {
22 hdr.mtime()
23}
24
25pub fn ent2path<'a, R>(ent: &'a Entry<R>) -> Result<Cow<'a, Path>, io::Error>
26where
27 R: Read,
28{
29 ent.path()
30}
31
32pub fn ent2hdr<'a, R>(ent: &'a Entry<R>) -> &'a Header
33where
34 R: Read,
35{
36 ent.header()
37}
38
39pub fn ent2data<R>(ent: &mut Entry<R>, buf: &mut Vec<u8>, limit: u64) -> Result<usize, io::Error>
40where
41 R: Read,
42{
43 buf.clear();
44 let mut taken = ent.take(limit);
45 taken.read_to_end(buf)
46}
47
48pub fn copy<R>(src: &mut Entry<R>, dst: &mut TarEntry, limit: u64) -> Result<usize, io::Error>
49where
50 R: Read,
51{
52 let hdr: &Header = ent2hdr(src);
53
54 let mode: u32 = header2mode(hdr)?;
55 let unixtime: u64 = header2mtime(hdr)?;
56
57 let pat: &Path = &ent2path(src)?;
58 let ostr: Option<&str> = pat.to_str();
59 let upat: &str = ostr.ok_or(io::Error::other("invalid path"))?;
60 dst.name.clear();
61 dst.name.push_str(upat);
62
63 let usz: usize = ent2data(src, &mut dst.data, limit)?;
64
65 dst.mode = mode;
66 dst.modified_unixtime = unixtime;
67 dst.size = usz as u64;
68
69 Ok(usz)
70}
71
72pub fn reader2tar2entries2wtr<R, W>(rdr: R, wtr: &mut W, limit: u64) -> Result<(), io::Error>
73where
74 R: Read,
75 W: FnMut(&TarEntry) -> Result<(), io::Error>,
76{
77 let mut ta = Archive::new(rdr);
78 let entries = ta.entries()?;
79 let mut buf = TarEntry::default();
80 for rent in entries {
81 let mut ent = rent?;
82 copy(&mut ent, &mut buf, limit)?;
83 wtr(&buf)?;
84 }
85 Ok(())
86}