magic_pack/modules/
mod.rs

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    ];
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}