1use std::io::Write;
2use std::path::PathBuf;
3
4use crate::compression;
5use crate::encryptions;
6use crate::utils;
7
8use crate::encryptions::encryption::Encryption;
9
10pub fn run(action: &str, target: &str, encrypt: bool) -> std::io::Result<()> {
11 let password = &if encrypt {
12 print!("Enter password: ");
13 std::io::stdout().flush().expect("Failed to flush stdout");
14 let password1 =
15 rpassword::read_password().expect("Failed to read password");
16
17 if (action == "pack") {
18 print!("Confirm password: ");
19 std::io::stdout().flush().expect("Failed to flush stdout");
20 let password2 =
21 rpassword::read_password().expect("Failed to read password");
22
23 if password1 != password2 {
24 eprintln!("Passwords do not match.");
25 std::process::exit(1);
26 }
27 }
28
29 password1
30 } else {
31 "".to_owned()
32 };
33
34 let target_path = utils::validate_path(target)
36 .or_else(|_| utils::sanitize_output_path(target))
37 .expect("Invalid target path");
38
39 return run_non_interactive(
40 action,
41 target_path.to_str().unwrap_or_default(),
42 password,
43 );
44}
45
46pub fn run_non_interactive(
47 action: &str,
48 target: &str,
49 password: &str,
50) -> std::io::Result<()> {
51 let encrypt = !password.is_empty();
52 let extension = if encrypt { "i6pe" } else { "i6p" };
53
54 let target_path = PathBuf::from(target);
55
56 let tar_file =
57 &format!("{}-{}.tar", target_path.display(), uuid::Uuid::new_v4());
58 let compressed_file =
59 &format!("{}-{}.tar.zst", target_path.display(), uuid::Uuid::new_v4());
60
61 let file_out = &format!("{}.{}", target_path.display(), extension);
62
63 match action {
64 "pack" => {
65 compression::create_tar_archive(target_path.to_str().unwrap(), tar_file)?;
66
67 if (encrypt) {
68 compression::compress_tar_file(tar_file, compressed_file)?;
69 encryptions::cha_cha20_poly1305::ChaCha20Poly1305::encrypt_file(
70 compressed_file,
71 file_out,
72 password,
73 )?;
74 } else {
75 compression::compress_tar_file(tar_file, file_out)?;
76 }
77 }
78 "unpack" => {
79 if (encrypt) {
80 encryptions::cha_cha20_poly1305::ChaCha20Poly1305::decrypt_file(
81 target_path.to_str().unwrap(),
82 compressed_file,
83 password,
84 )?;
85 compression::decompress_file(compressed_file, tar_file)?;
86 } else {
87 compression::decompress_file(target_path.to_str().unwrap(), tar_file)?;
88 }
89
90 compression::extract_tar_archive(
91 tar_file,
92 &utils::remove_extension(
93 target_path.to_str().unwrap(),
94 &format!(".{extension}"),
95 ),
96 )?;
97 }
98 _ => {
99 eprintln!("Invalid action. Use 'pack' or 'unpack'.");
100 std::process::exit(1);
101 }
102 }
103
104 std::fs::remove_file(tar_file)?;
106
107 if (encrypt) {
108 std::fs::remove_file(compressed_file)?;
109 }
110
111 Ok(())
112}