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