easy_archive/archive/
tar.rs1use crate::{Decode, Encode, File, tool::clean};
2use flate2::read::GzDecoder;
3use std::io::{BufReader, Cursor, Read};
4use tar::Archive;
5
6pub struct Tar;
7
8impl Decode for Tar {
9 fn decode(buffer: Vec<u8>) -> Option<Vec<File>> {
10 let mut files = Vec::new();
11 let cur = Cursor::new(buffer);
12 let mut a = Archive::new(cur);
13 for file in a.entries().unwrap() {
14 let mut file = file.unwrap();
15 let path = file.header().path().unwrap().to_string_lossy().to_string();
16 if path == "pax_global_header" {
18 continue;
19 }
20 let mut buffer = vec![];
21 file.read_to_end(&mut buffer).expect("failed to read file");
22 let mode = file.header().mode().ok();
23 let is_dir = path.ends_with("/");
24 let path = clean(&path);
25 let mtime = file.header().mtime().ok();
26 files.push(File::new(path, buffer, mode, is_dir, mtime));
27 }
28 Some(files)
29 }
30}
31
32pub struct TarGz;
33impl Decode for TarGz {
34 fn decode(buffer: Vec<u8>) -> Option<Vec<File>> {
35 let mut decoder = GzDecoder::new(&buffer[..]);
36 let mut decompressed = Vec::new();
37 decoder.read_to_end(&mut decompressed).ok()?;
38 Tar::decode(decompressed)
39 }
40}
41
42#[cfg(feature = "xz2")]
43fn decode_xz2(buffer: &[u8]) -> Option<Vec<File>> {
44 use xz2::bufread::XzDecoder;
45 let mut dec = XzDecoder::new(buffer);
46 let mut decompressed = vec![];
47 dec.read_to_end(&mut decompressed).ok()?;
48 Tar::decode(decompressed)
49}
50
51#[cfg(feature = "lzma-rs")]
52fn decode_lzma_rs(buffer: &[u8]) -> Option<Vec<File>> {
53 let mut cur = Cursor::new(buffer);
54 let mut decomp: Vec<u8> = Vec::new();
55 lzma_rs::xz_decompress(&mut cur, &mut decomp).ok()?;
56 Tar::decode(decomp)
57}
58
59pub struct TarXz;
60impl Decode for TarXz {
61 fn decode(buffer: Vec<u8>) -> Option<Vec<File>> {
62 #[cfg(feature = "xz2")]
63 return decode_xz2(&buffer);
64 #[allow(unreachable_code)]
65 #[cfg(feature = "lzma-rs")]
66 return decode_lzma_rs(&buffer);
67 }
68}
69
70pub struct TarBz;
71impl Decode for TarBz {
72 fn decode(buffer: Vec<u8>) -> Option<Vec<File>> {
73 use bzip2_rs::DecoderReader;
74 let cur = Cursor::new(buffer);
75 let reader = BufReader::new(DecoderReader::new(cur));
76 let v = reader.bytes().map(|i| i.unwrap()).collect();
77 Tar::decode(v)
78 }
79}
80use ruzstd::decoding::StreamingDecoder;
81
82pub struct TarZstd;
83impl Decode for TarZstd {
84 fn decode(buffer: Vec<u8>) -> Option<Vec<File>> {
85 let cur = Cursor::new(buffer);
86 let mut decoder = StreamingDecoder::new(cur).unwrap();
87 let mut result = Vec::new();
88 decoder.read_to_end(&mut result).unwrap();
89 Tar::decode(result)
90 }
91}
92
93impl Encode for Tar {}
94impl Encode for TarGz {}
95impl Encode for TarXz {}
96impl Encode for TarBz {}
97impl Encode for TarZstd {}