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