xref: /developtools/hdc/hdc_rust/src/tar/compress.rs (revision cc290419)
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