magic_pack/modules/
mod.rs1mod 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 ];
38
39 let compress_magic_include_list = [CompressMagic {
40 magic_number: &[0x75, 0x73, 0x74, 0x61, 0x72],
41 length: 5,
42 file_type: enums::FileType::Tar,
43 }];
44
45 let mut startswith_buffer = [0u8; 4];
46 let mut file = File::open(file_path).expect("File open failed");
47 match file.read_exact(&mut startswith_buffer) {
48 Ok(_) => (),
49 Err(_) => return Err(Error::from(ErrorKind::Unsupported)),
50 };
51
52 for compress_magic in compress_magic_startswith_list.iter() {
53 if startswith_buffer.get(..compress_magic.length).unwrap() == compress_magic.magic_number {
54 return Ok(compress_magic.file_type);
55 }
56 }
57
58 file.rewind().expect("Seek 0 failed");
59 let mut include_vec = Vec::new();
60 file.read_to_end(&mut include_vec)
61 .expect("Read file failed");
62
63 for compress_magic in compress_magic_include_list.iter() {
64 if find_subsequence(&include_vec, compress_magic.magic_number).is_some() {
65 return Ok(compress_magic.file_type);
66 }
67 }
68
69 Err(Error::from(ErrorKind::Unsupported))
70}
71
72pub fn compress(
73 file_type: enums::FileType,
74 src_path: &std::path::PathBuf,
75 dst_path: &std::path::PathBuf,
76) {
77 let src_path_str = src_path.to_owned().into_os_string().into_string().unwrap();
78 let dst_path_str = dst_path.to_owned().into_os_string().into_string().unwrap();
79 match file_type {
80 enums::FileType::Zip => {
81 compression::zip::compress(&src_path_str, &dst_path_str);
82 }
83 enums::FileType::Tar => {
84 compression::tar::compress(&src_path_str, &dst_path_str);
85 }
86 enums::FileType::Bz2 => {
87 compression::bz2::compress(&src_path_str, &dst_path_str);
88 }
89 enums::FileType::Gz => {
90 compression::gz::compress(&src_path_str, &dst_path_str);
91 }
92 enums::FileType::Tarbz2 => {
93 compression::tar_bz2::compress(&src_path_str, &dst_path_str);
94 }
95 enums::FileType::Targz => {
96 compression::tar_gz::compress(&src_path_str, &dst_path_str);
97 }
98 }
99}
100
101pub fn decompress(
102 file_type: enums::FileType,
103 src_path: &std::path::PathBuf,
104 dst_path: &std::path::PathBuf,
105) {
106 let src_path_str = src_path.to_owned().into_os_string().into_string().unwrap();
107 let dst_path_str = dst_path.to_owned().into_os_string().into_string().unwrap();
108 match file_type {
109 enums::FileType::Zip => {
110 println!("zip");
111 compression::zip::decompress(&src_path_str, &dst_path_str);
112 }
113 enums::FileType::Tar => {
114 println!("tar");
115 compression::tar::decompress(&src_path_str, &dst_path_str);
116 }
117 enums::FileType::Tarbz2 => {
118 println!("tar.bz2");
119 compression::tar_bz2::decompress(&src_path_str, &dst_path_str);
120 }
121 enums::FileType::Targz => {
122 println!("tar.gz");
123 compression::tar_gz::decompress(&src_path_str, &dst_path_str);
124 }
125 enums::FileType::Bz2 => {
126 println!("bz2");
127 compression::bz2::decompress(&src_path_str, &dst_path_str);
128 }
129 enums::FileType::Gz => {
130 println!("gz");
131 compression::gz::decompress(&src_path_str, &dst_path_str);
132 }
133 }
134}