1mod compression;
2
3use std::fs::File;
4use std::io::{Error, ErrorKind, Read, Seek};
5
6use crate::contents::enums;
7
8fn find_subsequence(source: &[u8], target: &[u8]) -> Option<usize> {
9 source
10 .windows(target.len())
11 .position(|window| window == target)
12}
13
14pub fn get_file_type(file_path: &std::path::PathBuf) -> Result<enums::FileType, std::io::Error> {
15 struct CompressMagic {
16 magic_number: &'static [u8],
17 length: usize,
18 file_type: enums::FileType,
19 }
20
21 let compress_magic_startswith_list = [
22 CompressMagic {
23 magic_number: b"BZh",
24 length: 3,
25 file_type: enums::FileType::Bz2,
26 },
27 CompressMagic {
28 magic_number: &[0x1f, 0x8b],
29 length: 2,
30 file_type: enums::FileType::Gz,
31 },
32 CompressMagic {
33 magic_number: &[0x50, 0x4b, 0x03, 0x04],
34 length: 4,
35 file_type: enums::FileType::Zip,
36 },
37 CompressMagic {
38 magic_number: &[0x37, 0x7a, 0xbc, 0xaf],
39 length: 4,
40 file_type: enums::FileType::SevenZ,
41 },
42 CompressMagic {
43 magic_number: &[0xfd, 0x37, 0x7a, 0x58],
44 length: 4,
45 file_type: enums::FileType::Xz,
46 },
47 CompressMagic {
48 magic_number: &[0x28, 0xb5, 0x2f, 0xfd],
49 length: 4,
50 file_type: enums::FileType::Zst,
51 },
52 CompressMagic {
53 magic_number: &[0x04, 0x22, 0x4d, 0x18],
54 length: 4,
55 file_type: enums::FileType::Lz4,
56 },
57 ];
58
59 let compress_magic_include_list = [CompressMagic {
60 magic_number: &[0x75, 0x73, 0x74, 0x61, 0x72],
61 length: 5,
62 file_type: enums::FileType::Tar,
63 }];
64
65 let mut startswith_buffer = [0u8; 4];
66 let mut file = File::open(file_path).expect("File open failed");
67 match file.read_exact(&mut startswith_buffer) {
68 Ok(_) => (),
69 Err(_) => return Err(Error::from(ErrorKind::Unsupported)),
70 };
71
72 for compress_magic in compress_magic_startswith_list.iter() {
73 if startswith_buffer.get(..compress_magic.length).unwrap() == compress_magic.magic_number {
74 return Ok(compress_magic.file_type);
75 }
76 }
77
78 file.rewind().expect("Seek 0 failed");
79 let mut include_vec = Vec::new();
80 file.read_to_end(&mut include_vec)
81 .expect("Read file failed");
82
83 for compress_magic in compress_magic_include_list.iter() {
84 if find_subsequence(&include_vec, compress_magic.magic_number).is_some() {
85 return Ok(compress_magic.file_type);
86 }
87 }
88
89 if compression::upx::detect(&include_vec) {
90 return Ok(enums::FileType::Upx);
91 }
92
93 Err(Error::from(ErrorKind::Unsupported))
94}
95
96pub fn compress(
99 file_type: enums::FileType,
100 src_path: &std::path::Path,
101 dst_path: &std::path::Path,
102) {
103 compress_with_password(file_type, src_path, dst_path, None);
104}
105
106pub fn compress_with_password(
107 file_type: enums::FileType,
108 src_path: &std::path::Path,
109 dst_path: &std::path::Path,
110 password: Option<&str>,
111) {
112 match file_type {
113 enums::FileType::Zip => {
114 compression::zip::compress(src_path, dst_path);
115 }
116 enums::FileType::Tar => {
117 compression::tar::compress(src_path, dst_path);
118 }
119 enums::FileType::Bz2 => {
120 compression::bz2::compress(src_path, dst_path);
121 }
122 enums::FileType::Gz => {
123 compression::gz::compress(src_path, dst_path);
124 }
125 enums::FileType::Tarbz2 => {
126 compression::tar_bz2::compress(src_path, dst_path);
127 }
128 enums::FileType::Targz => {
129 compression::tar_gz::compress(src_path, dst_path);
130 }
131 enums::FileType::SevenZ => {
132 compression::sevenz::compress(src_path, dst_path, password);
133 }
134 enums::FileType::Xz => {
135 compression::xz::compress(src_path, dst_path);
136 }
137 enums::FileType::Tarxz => {
138 compression::tar_xz::compress(src_path, dst_path);
139 }
140 enums::FileType::Zst => {
141 compression::zst::compress(src_path, dst_path);
142 }
143 enums::FileType::Tarzst => {
144 compression::tar_zst::compress(src_path, dst_path);
145 }
146 enums::FileType::Lz4 => {
147 compression::lz4::compress(src_path, dst_path);
148 }
149 enums::FileType::Tarlz4 => {
150 compression::tar_lz4::compress(src_path, dst_path);
151 }
152 enums::FileType::Upx => {
153 compression::upx::compress(src_path, dst_path);
154 }
155 }
156}
157
158pub fn decompress(
161 file_type: enums::FileType,
162 src_path: &std::path::Path,
163 dst_path: &std::path::Path,
164) {
165 decompress_with_password(file_type, src_path, dst_path, None);
166}
167
168pub fn decompress_with_password(
169 file_type: enums::FileType,
170 src_path: &std::path::Path,
171 dst_path: &std::path::Path,
172 password: Option<&str>,
173) {
174 match file_type {
175 enums::FileType::Zip => {
176 compression::zip::decompress(src_path, dst_path);
177 }
178 enums::FileType::Tar => {
179 compression::tar::decompress(src_path, dst_path);
180 }
181 enums::FileType::Tarbz2 => {
182 compression::tar_bz2::decompress(src_path, dst_path);
183 }
184 enums::FileType::Targz => {
185 compression::tar_gz::decompress(src_path, dst_path);
186 }
187 enums::FileType::Bz2 => {
188 compression::bz2::decompress(src_path, dst_path);
189 }
190 enums::FileType::Gz => {
191 compression::gz::decompress(src_path, dst_path);
192 }
193 enums::FileType::SevenZ => {
194 compression::sevenz::decompress(src_path, dst_path, password);
195 }
196 enums::FileType::Xz => {
197 compression::xz::decompress(src_path, dst_path);
198 }
199 enums::FileType::Tarxz => {
200 compression::tar_xz::decompress(src_path, dst_path);
201 }
202 enums::FileType::Zst => {
203 compression::zst::decompress(src_path, dst_path);
204 }
205 enums::FileType::Tarzst => {
206 compression::tar_zst::decompress(src_path, dst_path);
207 }
208 enums::FileType::Lz4 => {
209 compression::lz4::decompress(src_path, dst_path);
210 }
211 enums::FileType::Tarlz4 => {
212 compression::tar_lz4::decompress(src_path, dst_path);
213 }
214 enums::FileType::Upx => {
215 compression::upx::decompress(src_path, dst_path);
216 }
217 }
218}