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 ¢ralEntry); 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