• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "zip_file.h"
17 
18 #include <cassert>
19 #include <cstring>
20 #include <ostream>
21 
22 #include "app_log_wrapper.h"
23 #include "bundle_constants.h"
24 #include "securec.h"
25 #include "zlib.h"
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 constexpr uint32_t MAX_FILE_PATH = 4096;
31 constexpr uint32_t UNZIP_BUFFER_SIZE = 1024;
32 constexpr uint32_t UNZIP_BUF_IN_LEN = 160 * UNZIP_BUFFER_SIZE;   // in  buffer length: 160KB
33 constexpr uint32_t UNZIP_BUF_OUT_LEN = 320 * UNZIP_BUFFER_SIZE;  // out buffer length: 320KB
34 constexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50;
35 constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50;
36 constexpr uint32_t EOCD_SIGNATURE = 0x06054b50;
37 constexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50;
38 constexpr uint32_t FLAG_DATA_DESC = 0x8;
39 constexpr size_t FILE_READ_COUNT = 1;
40 constexpr uint8_t INFLATE_ERROR_TIMES = 5;
41 }  // namespace
42 
ZipEntry(const CentralDirEntry & centralEntry)43 ZipEntry::ZipEntry(const CentralDirEntry &centralEntry)
44 {
45     compressionMethod = centralEntry.compressionMethod;
46     uncompressedSize = centralEntry.uncompressedSize;
47     compressedSize = centralEntry.compressedSize;
48     localHeaderOffset = centralEntry.localHeaderOffset;
49     crc = centralEntry.crc;
50     flags = centralEntry.flags;
51 }
52 
ZipFile(const std::string & pathName)53 ZipFile::ZipFile(const std::string &pathName) : pathName_(pathName)
54 {
55     APP_LOGI("create instance from %{private}s", pathName_.c_str());
56 }
57 
~ZipFile()58 ZipFile::~ZipFile()
59 {
60     Close();
61 }
62 
SetContentLocation(const ZipPos start,const size_t length)63 void ZipFile::SetContentLocation(const ZipPos start, const size_t length)
64 {
65     APP_LOGD("set content location start position(%{public}llu), length(%{public}zu)", start, length);
66     fileStartPos_ = start;
67     fileLength_ = length;
68 }
69 
CheckEndDir(const EndDir & endDir) const70 bool ZipFile::CheckEndDir(const EndDir &endDir) const
71 {
72     size_t lenEndDir = sizeof(EndDir);
73     if ((endDir.numDisk != 0) || (endDir.signature != EOCD_SIGNATURE) || (endDir.startDiskOfCentralDir != 0) ||
74         (endDir.offset >= fileLength_) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) ||
75         (endDir.commentLen != 0) ||
76         // central dir can't overlap end of central dir
77         ((endDir.offset + endDir.sizeOfCentralDir + lenEndDir) > fileLength_)) {
78         APP_LOGE("end dir format error");
79         return false;
80     }
81     return true;
82 }
83 
ParseEndDirectory()84 bool ZipFile::ParseEndDirectory()
85 {
86     size_t endDirLen = sizeof(EndDir);
87     size_t endFilePos = fileStartPos_ + fileLength_;
88 
89     if (fileLength_ <= endDirLen) {
90         APP_LOGE("parse EOCD file length(%{public}llu) <= end dir length(%{public}llu)", fileStartPos_, fileLength_);
91         return false;
92     }
93 
94     size_t eocdPos = endFilePos - endDirLen;
95     if (fseek(file_, eocdPos, SEEK_SET) != 0) {
96         APP_LOGE("locate EOCD seek failed, error: %{public}d", errno);
97         return false;
98     }
99 
100     if (fread(&endDir_, sizeof(EndDir), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
101         APP_LOGE("read EOCD struct failed, error: %{public}d", errno);
102         return false;
103     }
104 
105     centralDirPos_ = endDir_.offset + fileStartPos_;
106     APP_LOGD("parse EOCD offset(0x%{public}08x) file start position(0x%{public}08llx)", endDir_.offset, fileStartPos_);
107 
108     return CheckEndDir(endDir_);
109 }
110 
ParseAllEntries()111 bool ZipFile::ParseAllEntries()
112 {
113     bool ret = true;
114     ZipPos currentPos = centralDirPos_;
115     CentralDirEntry directoryEntry = {0};
116 
117     for (uint16_t i = 0; i < endDir_.totalEntries; i++) {
118         std::string fileName;
119         fileName.reserve(MAX_FILE_PATH);
120         fileName.resize(MAX_FILE_PATH - 1);
121 
122         if (fseek(file_, currentPos, SEEK_SET) != 0) {
123             APP_LOGE("parse entry(%{public}d) seek zipEntry failed, error: %{public}d", i, errno);
124             ret = false;
125             break;
126         }
127 
128         if (fread(&directoryEntry, sizeof(CentralDirEntry), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
129             APP_LOGE("parse entry(%{public}d) read ZipEntry failed, error: %{public}d", i, errno);
130             ret = false;
131             break;
132         }
133 
134         if (directoryEntry.signature != CENTRAL_SIGNATURE) {
135             APP_LOGE("parse entry(%{public}d) check signature(0x%08x) at pos(0x%08llx) failed",
136                 i,
137                 directoryEntry.signature,
138                 currentPos);
139             ret = false;
140             break;
141         }
142 
143         size_t fileLength = (directoryEntry.nameSize >= MAX_FILE_PATH) ? (MAX_FILE_PATH - 1) : directoryEntry.nameSize;
144         if (fread(&(fileName[0]), fileLength, FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
145             APP_LOGE("parse entry(%{public}d) read file name failed, error: %{public}d", i, errno);
146             ret = false;
147             break;
148         }
149         fileName.resize(fileLength);
150 
151         ZipEntry currentEntry(directoryEntry);
152         currentEntry.fileName = fileName;
153         entriesMap_[fileName] = currentEntry;
154 
155         currentPos += sizeof(directoryEntry);
156         currentPos += directoryEntry.nameSize + directoryEntry.extraSize + directoryEntry.commentSize;
157     }
158 
159     APP_LOGD("parse %{public}d central entries from %{private}s", endDir_.totalEntries, pathName_.c_str());
160     return ret;
161 }
162 
Open()163 bool ZipFile::Open()
164 {
165     APP_LOGD("open: %{private}s", pathName_.c_str());
166 
167     if (isOpen_) {
168         APP_LOGE("has already opened");
169         return true;
170     }
171 
172     if (pathName_.length() > PATH_MAX) {
173         APP_LOGE("path length(%{public}u) longer than max path length(%{public}d)",
174             static_cast<unsigned int>(pathName_.length()),
175             PATH_MAX);
176         return false;
177     }
178     std::string realPath;
179     realPath.reserve(PATH_MAX);
180     realPath.resize(PATH_MAX - 1);
181     if (realpath(pathName_.c_str(), &(realPath[0])) == nullptr) {
182         APP_LOGE("transform real path error: %{public}d", errno);
183         return false;
184     }
185 
186     FILE *tmpFile = fopen(realPath.c_str(), "rb");
187     if (tmpFile == nullptr) {
188         APP_LOGE("open file(%{private}s) failed, error: %{public}d", pathName_.c_str(), errno);
189         return false;
190     }
191 
192     if (fileLength_ == 0) {
193         if (fseek(tmpFile, 0, SEEK_END) != 0) {
194             APP_LOGE("file seek failed, error: %{public}d", errno);
195             fclose(tmpFile);
196             return false;
197         }
198         int64_t fileLength = ftell(tmpFile);
199         if (fileLength == -1) {
200             APP_LOGE("open file %{private}s failed", pathName_.c_str());
201             fclose(tmpFile);
202             return false;
203         }
204         fileLength_ = static_cast<ZipPos>(fileLength);
205         if (fileStartPos_ >= fileLength_) {
206             APP_LOGE("open start pos > length failed");
207             fclose(tmpFile);
208             return false;
209         }
210 
211         fileLength_ -= fileStartPos_;
212     }
213 
214     file_ = tmpFile;
215     bool result = ParseEndDirectory();
216     if (result) {
217         result = ParseAllEntries();
218     }
219     // it means open file success.
220     isOpen_ = true;
221     return result;
222 }
223 
Close()224 void ZipFile::Close()
225 {
226     APP_LOGD("close: %{private}s", pathName_.c_str());
227 
228     if (!isOpen_ || file_ == nullptr) {
229         APP_LOGW("file is not opened");
230         return;
231     }
232 
233     entriesMap_.clear();
234     pathName_ = "";
235     isOpen_ = false;
236 
237     if (fclose(file_) != 0) {
238         APP_LOGW("close failed, error: %{public}d", errno);
239     }
240     file_ = nullptr;
241 }
242 
243 // Get all file zipEntry in this file
GetAllEntries() const244 const ZipEntryMap &ZipFile::GetAllEntries() const
245 {
246     return entriesMap_;
247 }
248 
HasEntry(const std::string & entryName) const249 bool ZipFile::HasEntry(const std::string &entryName) const
250 {
251     return entriesMap_.find(entryName) != entriesMap_.end();
252 }
253 
IsDirExist(const std::string & dir) const254 bool ZipFile::IsDirExist(const std::string &dir) const
255 {
256     APP_LOGD("target dir: %{public}s", dir.c_str());
257     if (dir.empty()) {
258         APP_LOGE("target dir is empty");
259         return false;
260     }
261 
262     auto tempDir = dir;
263     if (tempDir.back() != Constants::FILE_SEPARATOR_CHAR) {
264         tempDir.push_back(Constants::FILE_SEPARATOR_CHAR);
265     }
266 
267     for (const auto &item : entriesMap_) {
268         if (item.first.find(tempDir) == 0) {
269             APP_LOGD("find target dir, fileName : %{public}s", item.first.c_str());
270             return true;
271         }
272     }
273     APP_LOGD("target dir not found, dir : %{public}s", dir.c_str());
274     return false;
275 }
276 
GetEntry(const std::string & entryName,ZipEntry & resultEntry) const277 bool ZipFile::GetEntry(const std::string &entryName, ZipEntry &resultEntry) const
278 {
279     APP_LOGD("get entry by name: %{public}s", entryName.c_str());
280     auto iter = entriesMap_.find(entryName);
281     if (iter != entriesMap_.end()) {
282         resultEntry = iter->second;
283         APP_LOGD("get entry succeed");
284         return true;
285     }
286     APP_LOGE("get entry failed");
287     return false;
288 }
289 
GetLocalHeaderSize(const uint16_t nameSize,const uint16_t extraSize) const290 size_t ZipFile::GetLocalHeaderSize(const uint16_t nameSize, const uint16_t extraSize) const
291 {
292     return sizeof(LocalHeader) + nameSize + extraSize;
293 }
294 
CheckDataDesc(const ZipEntry & zipEntry,const LocalHeader & localHeader) const295 bool ZipFile::CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const
296 {
297     uint32_t crcLocal = 0;
298     uint32_t compressedLocal = 0;
299     uint32_t uncompressedLocal = 0;
300 
301     if (localHeader.flags & FLAG_DATA_DESC) {  // use data desc
302         DataDesc dataDesc;
303         auto descPos = zipEntry.localHeaderOffset + GetLocalHeaderSize(localHeader.nameSize, localHeader.extraSize);
304         descPos += fileStartPos_ + zipEntry.compressedSize;
305 
306         if (fseek(file_, descPos, SEEK_SET) != 0) {
307             APP_LOGE("check local header seek datadesc failed, error: %{public}d", errno);
308             return false;
309         }
310 
311         if (fread(&dataDesc, sizeof(DataDesc), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
312             APP_LOGE("check local header read datadesc failed, error: %{public}d", errno);
313             return false;
314         }
315 
316         if (dataDesc.signature != DATA_DESC_SIGNATURE) {
317             APP_LOGE("check local header check datadesc signature failed");
318             return false;
319         }
320 
321         crcLocal = dataDesc.crc;
322         compressedLocal = dataDesc.compressedSize;
323         uncompressedLocal = dataDesc.uncompressedSize;
324     } else {
325         crcLocal = localHeader.crc;
326         compressedLocal = localHeader.compressedSize;
327         uncompressedLocal = localHeader.uncompressedSize;
328     }
329 
330     if ((zipEntry.crc != crcLocal) || (zipEntry.compressedSize != compressedLocal) ||
331         (zipEntry.uncompressedSize != uncompressedLocal)) {
332         APP_LOGE("check local header compressed size corrupted");
333         return false;
334     }
335 
336     return true;
337 }
338 
CheckCoherencyLocalHeader(const ZipEntry & zipEntry,uint16_t & extraSize) const339 bool ZipFile::CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const
340 {
341     LocalHeader localHeader = {0};
342 
343     if (zipEntry.localHeaderOffset >= fileLength_) {
344         APP_LOGE("check local file header offset is overflow %{public}d", zipEntry.localHeaderOffset);
345         return false;
346     }
347 
348     if (fseek(file_, fileStartPos_ + zipEntry.localHeaderOffset, SEEK_SET) != 0) {
349         APP_LOGE("check local header seek failed, error: %{public}d", errno);
350         return false;
351     }
352 
353     if (fread(&localHeader, sizeof(LocalHeader), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
354         APP_LOGE("check local header read localheader failed, error: %{public}d", errno);
355         return false;
356     }
357 
358     if ((localHeader.signature != LOCAL_HEADER_SIGNATURE) ||
359         (zipEntry.compressionMethod != localHeader.compressionMethod)) {
360         APP_LOGE("check local header signature or compressionMethod failed");
361         return false;
362     }
363 
364     // current only support store and Z_DEFLATED method
365     if ((zipEntry.compressionMethod != Z_DEFLATED) && (zipEntry.compressionMethod != 0)) {
366         APP_LOGE("check local header compressionMethod(%{public}d) not support", zipEntry.compressionMethod);
367         return false;
368     }
369 
370     std::string fileName;
371     fileName.reserve(MAX_FILE_PATH);
372     fileName.resize(MAX_FILE_PATH - 1);
373     size_t fileLength = (localHeader.nameSize >= MAX_FILE_PATH) ? (MAX_FILE_PATH - 1) : localHeader.nameSize;
374     if (fileLength != zipEntry.fileName.length()) {
375         APP_LOGE("check local header file name size failed");
376         return false;
377     }
378     if (fread(&(fileName[0]), fileLength, FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
379         APP_LOGE("check local header read file name failed, error: %{public}d", errno);
380         return false;
381     }
382     fileName.resize(fileLength);
383     if (zipEntry.fileName != fileName) {
384         APP_LOGE("check local header file name corrupted");
385         return false;
386     }
387 
388     if (!CheckDataDesc(zipEntry, localHeader)) {
389         APP_LOGE("check data desc failed");
390         return false;
391     }
392 
393     extraSize = localHeader.extraSize;
394     return true;
395 }
396 
SeekToEntryStart(const ZipEntry & zipEntry,const uint16_t extraSize) const397 bool ZipFile::SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const
398 {
399     ZipPos startOffset = zipEntry.localHeaderOffset;
400     // get data offset, add signature+localheader+namesize+extrasize
401     startOffset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
402     if (startOffset + zipEntry.compressedSize > fileLength_) {
403         APP_LOGE("startOffset(%{public}lld)+entryCompressedSize(%{public}ud) > fileLength(%{public}llu)",
404             startOffset,
405             zipEntry.compressedSize,
406             fileLength_);
407         return false;
408     }
409     startOffset += fileStartPos_;  // add file start relative to file stream
410 
411     APP_LOGD("seek to entry start 0x%{public}08llx", startOffset);
412     if (fseek(file_, startOffset, SEEK_SET) != 0) {
413         APP_LOGE("seek failed, error: %{public}d", errno);
414         return false;
415     }
416     return true;
417 }
418 
UnzipWithStore(const ZipEntry & zipEntry,const uint16_t extraSize,std::ostream & dest) const419 bool ZipFile::UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
420 {
421     APP_LOGD("unzip with store");
422 
423     if (!SeekToEntryStart(zipEntry, extraSize)) {
424         APP_LOGE("seek to entry start failed");
425         return false;
426     }
427 
428     uint32_t remainSize = zipEntry.compressedSize;
429     std::string readBuffer;
430     readBuffer.reserve(UNZIP_BUF_OUT_LEN);
431     readBuffer.resize(UNZIP_BUF_OUT_LEN - 1);
432     while (remainSize > 0) {
433         size_t readBytes;
434         size_t readLen = (remainSize > UNZIP_BUF_OUT_LEN) ? UNZIP_BUF_OUT_LEN : remainSize;
435         readBytes = fread(&(readBuffer[0]), sizeof(Byte), readLen, file_);
436         if (readBytes == 0) {
437             APP_LOGE("unzip store read failed, error: %{public}d", ferror(file_));
438             return false;
439         }
440         remainSize -= readBytes;
441         dest.write(&(readBuffer[0]), readBytes);
442     }
443 
444     return true;
445 }
446 
InitZStream(z_stream & zstream) const447 bool ZipFile::InitZStream(z_stream &zstream) const
448 {
449     // init zlib stream
450     if (memset_s(&zstream, sizeof(z_stream), 0, sizeof(z_stream))) {
451         APP_LOGE("unzip stream buffer init failed");
452         return false;
453     }
454     int32_t zlibErr = inflateInit2(&zstream, -MAX_WBITS);
455     if (zlibErr != Z_OK) {
456         APP_LOGE("unzip inflated init failed");
457         return false;
458     }
459 
460     BytePtr bufOut = new (std::nothrow) Byte[UNZIP_BUF_OUT_LEN];
461     if (bufOut == nullptr) {
462         APP_LOGE("unzip inflated new out buffer failed");
463         return false;
464     }
465 
466     BytePtr bufIn = new (std::nothrow) Byte[UNZIP_BUF_IN_LEN];
467     if (bufIn == nullptr) {
468         APP_LOGE("unzip inflated new in buffer failed");
469         delete[] bufOut;
470         return false;
471     }
472     zstream.next_out = bufOut;
473     zstream.next_in = bufIn;
474     zstream.avail_out = UNZIP_BUF_OUT_LEN;
475     return true;
476 }
477 
ReadZStream(const BytePtr & buffer,z_stream & zstream,uint32_t & remainCompressedSize) const478 bool ZipFile::ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize) const
479 {
480     if (zstream.avail_in == 0) {
481         size_t readBytes;
482         size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize;
483         readBytes = fread(buffer, sizeof(Byte), remainBytes, file_);
484         if (readBytes == 0) {
485             APP_LOGE("unzip inflated read failed, error: %{public}d", ferror(file_));
486             return false;
487         }
488 
489         remainCompressedSize -= readBytes;
490         zstream.avail_in = readBytes;
491         zstream.next_in = buffer;
492     }
493     return true;
494 }
495 
UnzipWithInflated(const ZipEntry & zipEntry,const uint16_t extraSize,std::ostream & dest) const496 bool ZipFile::UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
497 {
498     APP_LOGD("unzip with inflated");
499 
500     z_stream zstream;
501     if (!SeekToEntryStart(zipEntry, extraSize) || !InitZStream(zstream)) {
502         return false;
503     }
504 
505     BytePtr bufIn = zstream.next_in;
506     BytePtr bufOut = zstream.next_out;
507 
508     bool ret = true;
509     int32_t zlibErr = Z_OK;
510     uint32_t remainCompressedSize = zipEntry.compressedSize;
511     uint8_t errorTimes = 0;
512     while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) {
513         if (!ReadZStream(bufIn, zstream, remainCompressedSize)) {
514             ret = false;
515             break;
516         }
517 
518         zlibErr = inflate(&zstream, Z_SYNC_FLUSH);
519         if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) {
520             APP_LOGE("unzip inflated inflate, error: %{public}d, err msg: %{public}s", zlibErr, zstream.msg);
521             ret = false;
522             break;
523         }
524 
525         size_t inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out;
526         if (inflateLen > 0) {
527             dest.write(reinterpret_cast<const char *>(bufOut), inflateLen);
528             zstream.next_out = bufOut;
529             zstream.avail_out = UNZIP_BUF_OUT_LEN;
530             errorTimes = 0;
531         } else {
532             errorTimes++;
533         }
534         if (errorTimes >= INFLATE_ERROR_TIMES) {
535             APP_LOGE("unzip inflated data is abnormal!");
536             ret = false;
537             break;
538         }
539     }
540 
541     // free all dynamically allocated data structures except the next_in and next_out for this stream.
542     zlibErr = inflateEnd(&zstream);
543     if (zlibErr != Z_OK) {
544         APP_LOGE("unzip inflateEnd error, error: %{public}d", zlibErr);
545         ret = false;
546     }
547 
548     delete[] bufOut;
549     delete[] bufIn;
550     return ret;
551 }
552 
GetEntryDataOffset(const ZipEntry & zipEntry,const uint16_t extraSize) const553 ZipPos ZipFile::GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const
554 {
555     // get entry data offset relative file
556     ZipPos offset = zipEntry.localHeaderOffset;
557 
558     offset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
559     offset += fileStartPos_;
560 
561     return offset;
562 }
563 
GetDataOffsetRelative(const std::string & file,ZipPos & offset,uint32_t & length) const564 bool ZipFile::GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const
565 {
566     APP_LOGD("get data relative offset for file %{private}s", file.c_str());
567 
568     ZipEntry zipEntry;
569     if (!GetEntry(file, zipEntry)) {
570         APP_LOGE("extract file: not find file");
571         return false;
572     }
573 
574     uint16_t extraSize = 0;
575     if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
576         APP_LOGE("check coherency local header failed");
577         return false;
578     }
579 
580     offset = GetEntryDataOffset(zipEntry, extraSize);
581     length = zipEntry.compressedSize;
582     return true;
583 }
584 
ExtractFile(const std::string & file,std::ostream & dest) const585 bool ZipFile::ExtractFile(const std::string &file, std::ostream &dest) const
586 {
587     APP_LOGD("extract file %{private}s", file.c_str());
588 
589     ZipEntry zipEntry;
590     if (!GetEntry(file, zipEntry)) {
591         APP_LOGE("extract file: not find file");
592         return false;
593     }
594 
595     uint16_t extraSize = 0;
596     if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
597         APP_LOGE("check coherency local header failed");
598         return false;
599     }
600 
601     bool ret = true;
602     if (zipEntry.compressionMethod == 0) {
603         ret = UnzipWithStore(zipEntry, extraSize, dest);
604     } else {
605         ret = UnzipWithInflated(zipEntry, extraSize, dest);
606     }
607 
608     return ret;
609 }
610 }  // namespace AppExecFwk
611 }  // namespace OHOS
612