1 /* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 //! compress 16 17 use std::{ 18 fs, 19 io::{self, Error}, 20 path::{Path, PathBuf}, 21 }; 22 23 use crate::tar::entry::Entry; 24 #[allow(unused)] 25 use crate::utils::hdc_log::*; 26 27 /// Compress tar 28 #[derive(Default)] 29 pub struct Compress { 30 entrys: Vec<Entry>, 31 prefix: PathBuf, 32 max_count: usize, 33 } 34 35 impl Compress { 36 /// new Compress newnull37 pub fn new() -> Self { 38 Self { 39 entrys: Vec::new(), 40 prefix: PathBuf::new(), 41 max_count: 0, 42 } 43 } 44 45 /// updata prefix updata_prefixnull46 pub fn updata_prefix(&mut self, prefix: PathBuf) { 47 self.prefix = prefix; 48 } 49 50 /// updata max conunt 51 /// default: 0, no limit 52 /// other: Maximum number of entries allowed to be saved updata_max_countnull53 pub fn updata_max_count(&mut self, count: usize) { 54 self.max_count = count; 55 } 56 add_path_recursionnull57 fn add_path_recursion(&mut self, path: &Path) -> io::Result<()> { 58 if !path.is_dir() { 59 self.add_entry(&path.display().to_string())?; 60 return Ok(()); 61 } 62 63 self.add_entry(&path.display().to_string())?; 64 65 for entry in fs::read_dir(path)? { 66 let entry = entry?; 67 let entry_path = entry.path(); 68 self.add_path_recursion(&entry_path)?; 69 } 70 71 Ok(()) 72 } 73 74 /// Add a path that needs to be packaged add_pathnull75 pub fn add_path(&mut self, path: &Path) -> io::Result<()> { 76 self.add_path_recursion(path) 77 } 78 add_entrynull79 fn add_entry(&mut self, file: &str) -> io::Result<()> { 80 if self.max_count > 0 && self.entrys.len() > self.max_count { 81 return Err(Error::new( 82 io::ErrorKind::Other, 83 format!( 84 "Exceeded the set maximum value, the maximum value is set to {}", 85 self.max_count 86 ), 87 )); 88 } 89 90 if let Some(prefix) = self.prefix.to_str() { 91 if prefix == file { 92 crate::debug!("Ignoring compressed root directory"); 93 return Ok(()); 94 } 95 } 96 97 let entry = Entry::new(self.prefix.clone(), file); 98 self.entrys.push(entry); 99 100 Ok(()) 101 } 102 103 /// 开始将数据写入压缩包 compressnull104 pub fn compress(&mut self, file_path: PathBuf) -> io::Result<()> { 105 if file_path.exists() && file_path.is_dir() { 106 return Err(io::Error::new( 107 io::ErrorKind::InvalidInput, 108 format!("{} is not a file", file_path.display()), 109 )); 110 } 111 112 let mut f = fs::OpenOptions::new() 113 .read(true) 114 .write(true) 115 .create(true) 116 .truncate(true) 117 .open(file_path)?; 118 for entry in &mut self.entrys { 119 entry.read_data_to_file(&mut f)?; 120 } 121 122 Ok(()) 123 } 124 } 125