• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #ifndef FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
17 #define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
18 
19 #include <cstdint>
20 #include <map>
21 #include <string>
22 #include <unistd.h>
23 
24 #include "ffrt.h"
25 #include "unzip.h"
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 struct CentralDirEntry;
30 struct ZipEntry;
31 using ZipPos = ZPOS64_T;
32 using ZipEntryMap = std::map<std::string, ZipEntry>;
33 using BytePtr = Byte *;
34 
35 // Local file header: descript in APPNOTE-6.3.4
36 //    local file header signature     4 bytes  (0x04034b50)
37 //    version needed to extract       2 bytes
38 //    general purpose bit flag        2 bytes
39 //    compression method              2 bytes  10
40 //    last mod file time              2 bytes
41 //    last mod file date              2 bytes
42 //    crc-32                          4 bytes
43 //    compressed size                 4 bytes  22
44 //    uncompressed size               4 bytes
45 //    file name length                2 bytes
46 //    extra field length              2 bytes  30
47 struct __attribute__((packed)) LocalHeader {
48     uint32_t signature = 0;
49     uint16_t versionNeeded = 0;
50     uint16_t flags = 0;
51     uint16_t compressionMethod = 0;
52     uint16_t modifiedTime = 0;
53     uint16_t modifiedDate = 0;
54     uint32_t crc = 0;
55     uint32_t compressedSize = 0;
56     uint32_t uncompressedSize = 0;
57     uint16_t nameSize = 0;
58     uint16_t extraSize = 0;
59 };
60 
61 // central file header
62 //    Central File header:
63 //    central file header signature   4 bytes  (0x02014b50)
64 //    version made by                 2 bytes
65 //    version needed to extract       2 bytes
66 //    general purpose bit flag        2 bytes  10
67 //    compression method              2 bytes
68 //    last mod file time              2 bytes
69 //    last mod file date              2 bytes
70 //    crc-32                          4 bytes  20
71 //    compressed size                 4 bytes
72 //    uncompressed size               4 bytes
73 //    file name length                2 bytes  30
74 //    extra field length              2 bytes
75 //    file comment length             2 bytes
76 //    disk number start               2 bytes
77 //    internal file attributes        2 bytes
78 //    external file attributes        4 bytes
79 //    relative offset of local header 4 bytes 46byte
80 struct __attribute__((packed)) CentralDirEntry {
81     uint32_t signature = 0;
82     uint16_t versionMade = 0;
83     uint16_t versionNeeded = 0;
84     uint16_t flags = 0;  // general purpose bit flag
85     uint16_t compressionMethod = 0;
86     uint16_t modifiedTime = 0;
87     uint16_t modifiedDate = 0;
88     uint32_t crc = 0;
89     uint32_t compressedSize = 0;
90     uint32_t uncompressedSize = 0;
91     uint16_t nameSize = 0;
92     uint16_t extraSize = 0;
93     uint16_t commentSize = 0;
94     uint16_t diskNumStart = 0;
95     uint16_t internalAttr = 0;
96     uint32_t externalAttr = 0;
97     uint32_t localHeaderOffset = 0;
98 };
99 
100 // end of central directory packed structure
101 //    end of central dir signature    4 bytes  (0x06054b50)
102 //    number of this disk             2 bytes
103 //    number of the disk with the
104 //    start of the central directory  2 bytes
105 //    total number of entries in the
106 //    central directory on this disk  2 bytes
107 //    total number of entries in
108 //    the central directory           2 bytes
109 //    size of the central directory   4 bytes
110 //    offset of start of central
111 //    directory with respect to
112 //    the starting disk number        4 bytes
113 //    .ZIP file comment length        2 bytes
114 struct __attribute__((packed)) EndDir {
115     uint32_t signature = 0;
116     uint16_t numDisk = 0;
117     uint16_t startDiskOfCentralDir = 0;
118     uint16_t totalEntriesInThisDisk = 0;
119     uint16_t totalEntries = 0;
120     uint32_t sizeOfCentralDir = 0;
121     uint32_t offset = 0;
122     uint16_t commentLen = 0;
123 };
124 
125 // Data descriptor:
126 //    data descriptor signature       4 bytes  (0x06054b50)
127 //    crc-32                          4 bytes
128 //    compressed size                 4 bytes
129 //    uncompressed size               4 bytes
130 // This descriptor MUST exist if bit 3 of the general purpose bit flag is set (see below).
131 // It is byte aligned and immediately follows the last byte of compressed data.
132 struct __attribute__((packed)) DataDesc {
133     uint32_t signature = 0;
134     uint32_t crc = 0;
135     uint32_t compressedSize = 0;
136     uint32_t uncompressedSize = 0;
137 };
138 
139 struct ZipEntry {
140     ZipEntry() = default;
141     explicit ZipEntry(const CentralDirEntry &centralEntry);
142     ~ZipEntry() = default;  // for CodeDEX warning
143 
144     uint16_t compressionMethod = 0;
145     uint16_t flags = 0;
146     uint32_t uncompressedSize = 0;
147     uint32_t compressedSize = 0;
148     uint32_t localHeaderOffset = 0;
149     uint32_t crc = 0;
150     std::string fileName;
151 };
152 
153 // zip file extract class for bundle format.
154 class ZipFile {
155 public:
156     explicit ZipFile(const std::string &pathName, bool parallel = false);
157     ~ZipFile();
158     /**
159      * @brief Open zip file.
160      * @return Returns true if the zip file is successfully opened; returns false otherwise.
161      */
162     bool Open();
163     /**
164      * @brief Close zip file.
165      */
166     void Close();
167     /**
168      * @brief Set this zip content start offset and length in the zip file form pathName.
169      * @param start Indicates the zip content location start position.
170      * @param length Indicates the zip content length.
171      */
172     void SetContentLocation(ZipPos start, size_t length);
173     /**
174      * @brief Get all entries in the zip file.
175      * @param start Indicates the zip content location start position.
176      * @param length Indicates the zip content length.
177      * @return Returns the ZipEntryMap object cotain all entries.
178      */
179     const ZipEntryMap &GetAllEntries() const;
180     /**
181      * @brief Has entry by name.
182      * @param entryName Indicates the entry name.
183      * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
184      */
185     bool HasEntry(const std::string &entryName) const;
186 
187     bool IsDirExist(const std::string &dir) const;
188 
189     /**
190      * @brief Get entry by name.
191      * @param entryName Indicates the entry name.
192      * @param resultEntry Indicates the obtained ZipEntry object.
193      * @return Returns true if the ZipEntry is successfully finded; returns false otherwise.
194      */
195     bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const;
196     /**
197      * @brief Get data relative offset for file.
198      * @param file Indicates the entry name.
199      * @param offset Indicates the obtained offset.
200      * @param length Indicates the length.
201      * @return Returns true if this function is successfully called; returns false otherwise.
202      */
203     bool GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const;
204     /**
205      * @brief Get data relative offset for file.
206      * @param file Indicates the entry name.
207      * @param dest Indicates the obtained ostream object.
208      * @return Returns true if file is successfully extracted; returns false otherwise.
209      */
210     bool ExtractFile(const std::string &file, std::ostream &dest) const;
211     /**
212      * @brief Extract data from file parallelly.
213      * @brief Get data relative offset for file.
214      * @param file Indicates the entry name.
215      * @param dest Indicates the obtained ostream object.
216      * @return Returns true if file is successfully extracted; returns false otherwise.
217      */
218     bool ExtractFileParallel(const std::string &file, std::ostream &dest) const;
219 
220 private:
221     /**
222      * @brief Check the EndDir object.
223      * @param endDir Indicates the EndDir object to check.
224      * @return Returns true if  successfully checked; returns false otherwise.
225      */
226     bool CheckEndDir(const EndDir &endDir) const;
227     /**
228      * @brief Parse the EndDir.
229      * @return Returns true if  successfully Parsed; returns false otherwise.
230      */
231     bool ParseEndDirectory();
232     /**
233      * @brief Parse all Entries.
234      * @return Returns true if successfully parsed; returns false otherwise.
235      */
236     bool ParseAllEntries();
237     /**
238      * @brief Get LocalHeader object size.
239      * @param nameSize Indicates the nameSize.
240      * @param extraSize Indicates the extraSize.
241      * @return Returns size of LocalHeader.
242      */
243     size_t GetLocalHeaderSize(const uint16_t nameSize = 0, const uint16_t extraSize = 0) const;
244     /**
245      * @brief Get entry data offset.
246      * @param zipEntry Indicates the ZipEntry object.
247      * @param extraSize Indicates the extraSize.
248      * @return Returns position.
249      */
250     ZipPos GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const;
251     /**
252      * @brief Check data description with specific file handler.
253      * @param zipEntry Indicates the ZipEntry object.
254      * @param localHeader Indicates the localHeader object.
255      * @param file Indicates the file handler used to read data.
256      * @return Returns true if successfully checked; returns false otherwise.
257      */
258     bool CheckDataDescInternal(const ZipEntry &zipEntry, const LocalHeader &localHeader, FILE *file) const;
259     /**
260      * @brief Check data description.
261      * @param zipEntry Indicates the ZipEntry object.
262      * @param localHeader Indicates the localHeader object.
263      * @return Returns true if successfully checked; returns false otherwise.
264      */
265     bool CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const;
266     /**
267      * @brief Check coherency LocalHeader object with specific file handler.
268      * @param zipEntry Indicates the ZipEntry object.
269      * @param extraSize Indicates the obtained size.
270      * @param file Indicates the file handler used to read data.
271      * @return Returns true if successfully checked; returns false otherwise.
272      */
273     bool CheckCoherencyLocalHeaderInternal(const ZipEntry &zipEntry, uint16_t &extraSize, FILE *file) const;
274     /**
275      * @brief Check coherency LocalHeader object.
276      * @param zipEntry Indicates the ZipEntry object.
277      * @param extraSize Indicates the obtained size.
278      * @return Returns true if successfully checked; returns false otherwise.
279      */
280     bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const;
281     /**
282      * @brief Unzip ZipEntry object to ostream.
283      * @param zipEntry Indicates the ZipEntry object.
284      * @param extraSize Indicates the size.
285      * @param dest Indicates the obtained ostream object.
286      * @param file Indicates the file handler used to read data.
287      * @return Returns true if successfully Unzip; returns false otherwise.
288      */
289     bool UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest, FILE *file) const;
290     /**
291      * @brief Unzip ZipEntry object to ostream.
292      * @param zipEntry Indicates the ZipEntry object.
293      * @param extraSize Indicates the size.
294      * @param dest Indicates the obtained ostream object.
295      * @param file Indicates the file handler used to read data.
296      * @return Returns true if successfully Unzip; returns false otherwise.
297      */
298     bool UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest, FILE *file) const;
299     /**
300      * @brief Seek to Entry start with specific file handler.
301      * @param zipEntry Indicates the ZipEntry object.
302      * @param extraSize Indicates the extra size.
303      * @param file Indicates the file handler used to read data.
304      * @return Returns true if successfully Seeked; returns false otherwise.
305      */
306     bool SeekToEntryStartInternal(const ZipEntry &zipEntry, const uint16_t extraSize, FILE *file) const;
307     /**
308      * @brief Seek to Entry start.
309      * @param zipEntry Indicates the ZipEntry object.
310      * @param extraSize Indicates the extra size.
311      * @return Returns true if successfully Seeked; returns false otherwise.
312      */
313     bool SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const;
314     /**
315      * @brief Init zlib stream.
316      * @param zstream Indicates the obtained z_stream object.
317      * @return Returns true if successfully init; returns false otherwise.
318      */
319     bool InitZStream(z_stream &zstream) const;
320     /**
321      * @brief Read zlib stream.
322      * @param buffer Indicates the buffer to read.
323      * @param zstream Indicates the obtained z_stream object.
324      * @param remainCompressedSize Indicates the obtained size.
325      * @param file Indicates the file handler used to read data.
326      * @return Returns true if successfully read; returns false otherwise.
327      */
328     bool ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize, FILE *file) const;
329     /**
330      * @brief Get file handler for parallel decompression.
331      * @param resourceId Indicates the initial resource id, returns actual resource id by input parameter.
332      */
333     void GetFileHandler(int32_t &resourceId) const;
334     /**
335      * @brief Release file handler for parallel compression
336      * @param resourceId Indicates the file handler id to release.
337      */
338     void ReleaseFileHandler(const int32_t resourceId) const;
339 
340 private:
341     bool isOpen_ = false;
342     std::string pathName_;
343     FILE *file_ = nullptr;
344     // offset of central directory relative to zip file.
345     ZipPos centralDirPos_ = 0;
346     // this zip content start offset relative to zip file.
347     ZipPos fileStartPos_ = 0;
348     // this zip content length in the zip file.
349     ZipPos fileLength_ = 0;
350     EndDir endDir_;
351     ZipEntryMap entriesMap_;
352 
353     bool parallel_ = false;
354     const int32_t concurrency_ = sysconf(_SC_NPROCESSORS_ONLN);
355     mutable std::vector<ffrt::mutex> mtxes_ = std::vector<ffrt::mutex> (concurrency_);
356     std::vector<FILE *> files_;
357 };
358 }  // namespace AppExecFwk
359 }  // namespace OHOS
360 #endif  // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_ZIP_FILE_H
361