easy_archive/archive/tar/
encode.rs1use crate::{
3 File,
4 error::{ArchiveError, Result},
5 traits::Encode,
6 utils::check_duplicate_files,
7};
8
9use super::Tar;
10
11pub(crate) fn encode_tar_archive(files: Vec<File>) -> Result<Vec<u8>> {
28 check_duplicate_files(&files)?;
30
31 let estimated_size: usize = files.iter().map(|f| f.buffer.len() + 512).sum();
33 let mut buffer: Vec<u8> = Vec::with_capacity(estimated_size);
34 {
35 let mut builder = tar::Builder::new(&mut buffer);
36
37 for file in files {
38 let mut header = tar::Header::new_gnu();
39 header.set_size(file.buffer.len() as u64);
40 header.set_mode(file.mode.unwrap_or(0o644));
41 header.set_uid(0);
42 header.set_gid(0);
43 header.set_mtime(file.last_modified.unwrap_or(0));
44 header.set_cksum();
45
46 builder
47 .append_data(&mut header, &file.path, &file.buffer[..])
48 .map_err(|e| ArchiveError::EncodeFailed {
49 format: "tar".to_string(),
50 reason: format!("Failed to append file '{}': {}", file.path, e),
51 })?;
52 }
53
54 builder.finish().map_err(|e| ArchiveError::EncodeFailed {
55 format: "tar".to_string(),
56 reason: format!("Failed to finalize tar archive: {}", e),
57 })?;
58 }
59
60 Ok(buffer)
61}
62
63impl Encode for Tar {
64 fn encode(files: Vec<File>) -> Result<Vec<u8>> {
65 encode_tar_archive(files)
66 }
67}