• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! decompress
16 
17 use std::{
18     fs,
19     io::{self, Read},
20     path::Path,
21 };
22 
23 use crate::tar::{entry::Entry, header};
24 #[allow(unused)]
25 use crate::utils::hdc_log::*;
26 
27 /// Decomposes the tar package
28 pub struct Decompress {
29     entrys: Vec<Entry>,
30 }
31 
32 impl Decompress {
33     /// Decomposes tar
34     /// path: tar path
file(path: &str) -> Result<Decompress, io::Error>35     pub fn file(path: &str) -> Result<Decompress, io::Error> {
36         match fs::metadata(path) {
37             Ok(metadata) => {
38                 let file_size = metadata.len();
39                 if file_size == 0 || file_size % header::HEADER_LEN as u64 != 0 {
40                     return Err(io::Error::new(
41                         io::ErrorKind::InvalidInput,
42                         format!("{path} is not tar file"),
43                     ));
44                 }
45             }
46             Err(e) => return Err(e),
47         };
48         let mut f = fs::File::open(path)?;
49         let mut buff = [0u8; header::HEADER_LEN as usize];
50 
51         let mut decompress = Self { entrys: Vec::new() };
52 
53         let mut entry = None;
54         loop {
55             match f.read(&mut buff)? {
56                 512 => match entry {
57                     None => {
58                         if let Ok(p_entry) = Entry::create_from_raw_data(&buff) {
59                             if p_entry.is_finish() {
60                                 decompress.entrys.push(p_entry);
61                             } else {
62                                 entry = Some(p_entry);
63                             }
64                         }
65                         continue;
66                     }
67                     Some(ref mut p_entry) => {
68                         p_entry.add_data(&buff);
69                         if p_entry.is_finish() {
70                             decompress.entrys.push(entry.unwrap());
71                             entry = None;
72                         }
73                     }
74                 },
75                 0 => break,
76                 n => {
77                     crate::error!("read error n {n}");
78                     break;
79                 }
80             }
81         }
82 
83         Ok(decompress)
84     }
85 
86     /// 将文件解压到文件夹,传入路径为空则是当前文件夹
decompress(&self, prefix: &str) -> io::Result<()>87     pub fn decompress(&self, prefix: &str) -> io::Result<()> {
88         let prefix = if !prefix.is_empty() { prefix } else { "./" };
89 
90         let prefix_path = Path::new(prefix);
91 
92         if prefix_path.exists() {
93             if prefix_path.is_file() {
94                 return Err(io::Error::new(
95                     io::ErrorKind::InvalidInput,
96                     format!("{} is not a dir", prefix),
97                 ));
98             }
99         } else {
100             crate::debug!("need create dir {}", prefix);
101             fs::create_dir_all(prefix)?;
102         }
103 
104         for entry in &self.entrys {
105             if !entry.is_finish() {
106                 crate::error!("file data is not load");
107                 continue;
108             }
109             if let Err(e) = entry.write_to_file(prefix_path) {
110                 crate::error!("entry.write_to_file failed: {}", e);
111             }
112         }
113 
114         Ok(())
115     }
116 }
117