Skip to main content

i6_pack/
compression.rs

1use std::fs::{self, File};
2use std::io::{self, Write};
3use std::path::Path;
4use tar::Builder;
5use walkdir::WalkDir;
6use zstd::stream::{decode_all, encode_all};
7use zstd::Encoder;
8
9pub fn create_tar_archive<P: AsRef<Path>>(
10  folder: P,
11  tar_file: &str,
12) -> io::Result<()> {
13  let tar_gz = File::create(tar_file)?;
14  let mut archive = Builder::new(tar_gz);
15
16  for entry in WalkDir::new(folder) {
17    let entry = match entry {
18      Ok(e) => e,
19      Err(e) => {
20        eprintln!("Warning: failed to read directory entry: {}", e);
21        continue;
22      }
23    };
24    let path = entry.path();
25    if path.is_symlink() {
26      match std::fs::read_link(path) {
27        Ok(target) => {
28          if target.exists() {
29            if let Err(e) = archive.append_path_with_name(&target, path) {
30              eprintln!("Warning: failed to append symlink {:?}: {}", path, e);
31            }
32          } else {
33            eprintln!(
34              "Warning: symlink target {:?} does not exist, skipping",
35              target
36            );
37          }
38        }
39        Err(e) => {
40          eprintln!(
41            "Warning: failed to read symlink {:?}, skipping: {}",
42            path, e
43          );
44        }
45      }
46    } else if path.exists() {
47      if let Err(e) = archive.append_path(path) {
48        eprintln!("Warning: failed to append path {:?}: {}", path, e);
49      }
50    } else {
51      eprintln!("Warning: file {:?} does not exist, skipping", path);
52    }
53  }
54
55  Ok(())
56}
57
58pub fn extract_tar_archive(tar_file: &str, output_dir: &str) -> io::Result<()> {
59  let tar_gz = File::open(tar_file)?;
60  let mut archive = tar::Archive::new(tar_gz);
61
62  let mut final_output_dir = output_dir.to_string();
63  if Path::new(output_dir).exists() {
64    final_output_dir = format!("{}-{}", output_dir, uuid::Uuid::new_v4());
65  }
66
67  std::fs::create_dir_all(&final_output_dir)?;
68  archive.unpack(&final_output_dir)?;
69  Ok(())
70}
71
72pub fn compress_tar_file(
73  tar_file: &str,
74  compressed_file: &str,
75) -> io::Result<()> {
76  let tar = File::open(tar_file)?;
77  let compressed = File::create(compressed_file)?;
78  let mut tar_reader = tar;
79  let mut compressed_writer = compressed;
80  let compression_level = 18;
81
82  let mut zstd = zstd::stream::write::Encoder::new(
83    &mut compressed_writer,
84    compression_level,
85  )?;
86  zstd.multithread(num_cpus::get() as u32)?;
87
88  zstd.long_distance_matching(true)?;
89  zstd.window_log(31)?;
90
91  io::copy(&mut tar_reader, &mut zstd)?;
92  zstd.finish()?;
93
94  Ok(())
95}
96
97pub fn decompress_file_v1(
98  compressed_file: &str,
99  output_file: &str,
100) -> io::Result<()> {
101  let compressed = File::open(compressed_file)?;
102  let decompressed_data = decode_all(compressed)?;
103  let mut decompressed = File::create(output_file)?;
104  decompressed.write_all(&decompressed_data)?;
105  Ok(())
106}
107
108pub fn decompress_file(
109  compressed_file: &str,
110  output_file: &str,
111) -> io::Result<()> {
112  let compressed = File::open(compressed_file)?;
113  let mut compressed_reader = compressed;
114  let mut decompressed_writer = File::create(output_file)?;
115
116  let mut zstd = zstd::stream::read::Decoder::new(&mut compressed_reader)?;
117  zstd.window_log_max(31)?;
118
119  io::copy(&mut zstd, &mut decompressed_writer)?;
120
121  Ok(())
122}