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