• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "zip_internal.h"
16 #include <unistd.h>
17 #include <stddef.h>
18 #include <algorithm>
19 #include "zip_utils.h"
20 #include "securec.h"
21 #include "hilog_wrapper.h"
22 
23 namespace OHOS {
24 namespace AAFwk {
25 namespace LIBZIP {
26 
GetTmDataFromTickts(int64_t sec)27 struct tm GetTmDataFromTickts(int64_t sec)
28 {
29     time_t second = (time_t)sec;
30     struct tm now {
31         .tm_year = 0,
32         .tm_mon = 0,
33         .tm_mday = 0,
34         .tm_hour = 0,
35         .tm_min = 0,
36         .tm_sec = 0,
37     };
38     struct tm *tmNow = localtime(&second);
39     if (tmNow == nullptr) {
40         return now;
41     }
42     int baseYeaar = 1900;
43     now = *tmNow;
44     now.tm_year += baseYeaar;
45     now.tm_mon += 1;
46     return now;
47 }
48 
49 // Callback function for zlib that opens a file stream from a file descriptor.
50 // Since we do not own the file descriptor, dup it so that we can fdopen/fclose
51 // a file stream.
FdOpenFileFunc(void * opaque,const char * filename,int mode)52 void *FdOpenFileFunc(void *opaque, const char *filename, int mode)
53 {
54     FILE *file = NULL;
55     const char *mode_fopen = NULL;
56     uint32_t modeInner = static_cast<uint32_t>(mode);
57     if ((modeInner & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
58         mode_fopen = "rb";
59     else if (modeInner & ZLIB_FILEFUNC_MODE_EXISTING)
60         mode_fopen = "r+b";
61     else if (modeInner & ZLIB_FILEFUNC_MODE_CREATE)
62         mode_fopen = "wb";
63 
64     if ((filename != NULL) && (mode_fopen != NULL)) {
65         int fd = dup(*static_cast<int *>(opaque));
66         if (fd != -1)
67             file = fdopen(fd, mode_fopen);
68     }
69 
70     return file;
71 }
72 
FdCloseFileFunc(void * opaque,void * stream)73 int FdCloseFileFunc(void *opaque, void *stream)
74 {
75     fclose(static_cast<FILE *>(stream));
76     free(opaque);  // malloc'ed in FillFdOpenFileFunc()
77     return 0;
78 }
79 
80 // Fills |pzlib_filecunc_def| appropriately to handle the zip file
81 // referred to by |fd|.
FillFdOpenFileFunc(zlib_filefunc_def * pzlibFilefuncDef,PlatformFile fd)82 void FillFdOpenFileFunc(zlib_filefunc_def *pzlibFilefuncDef, PlatformFile fd)
83 {
84     fill_fopen_filefunc(pzlibFilefuncDef);
85     pzlibFilefuncDef->zopen_file = FdOpenFileFunc;
86     pzlibFilefuncDef->zclose_file = FdCloseFileFunc;
87     int *ptrFd = static_cast<int *>(malloc(sizeof(fd)));
88     if (ptrFd == nullptr) {
89         return;
90     }
91     *ptrFd = fd;
92     pzlibFilefuncDef->opaque = ptrFd;
93 }
94 
95 // A struct that contains data required for zlib functions to extract files from
96 // a zip archive stored in memory directly. The following I/O API functions
97 // expect their opaque parameters refer to this struct.
98 struct ZipBuffer {
99     const char *data;
100     size_t length;
101     size_t offset;
102 };
103 
104 // Opens the specified file. When this function returns a non-NULL pointer, zlib
105 // uses this pointer as a stream parameter while compressing or uncompressing
106 // data. (Returning NULL represents an error.) This function initializes the
107 // given opaque parameter and returns it because this parameter stores all
108 // information needed for uncompressing data. (This function does not support
109 // writing compressed data and it returns NULL for this case.)
OpenZipBuffer(void * opaque,const char *,int mode)110 void *OpenZipBuffer(void *opaque, const char *, int mode)
111 {
112     uint32_t modeInner = static_cast<uint32_t>(mode);
113     if ((modeInner & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) {
114         HILOG_INFO("%{public}s called, mode is not ZLIB_FILEFUNC_MODE_READ.", __func__);
115         return NULL;
116     }
117     ZipBuffer *buffer = static_cast<ZipBuffer *>(opaque);
118     if (!buffer || !buffer->data || !buffer->length) {
119         return NULL;
120     }
121     buffer->offset = 0;
122     return opaque;
123 }
124 
125 // Reads compressed data from the specified stream. This function copies data
126 // refered by the opaque parameter and returns the size actually copied.
ReadZipBuffer(void * opaque,void *,void * buf,uLong size)127 uLong ReadZipBuffer(void *opaque, void *, void *buf, uLong size)
128 {
129     ZipBuffer *buffer = static_cast<ZipBuffer *>(opaque);
130     if (buffer == nullptr) {
131         HILOG_INFO("%{public}s called, buffer = nullptr.", __func__);
132         return 0;
133     }
134     if (buffer->offset > buffer->length) {
135         HILOG_INFO("%{public}s called, buffer->offset > buffer->length.", __func__);
136         return 0;
137     }
138 
139     size_t remaining_bytes = buffer->length - buffer->offset;
140     if (!buffer || !buffer->data || !remaining_bytes) {
141         return 0;
142     }
143     size = std::min(size, static_cast<uLong>(remaining_bytes));
144     if (memcpy_s(buf, size, &buffer->data[buffer->offset], size) != EOK) {
145         return 0;
146     }
147     buffer->offset += size;
148     return size;
149 }
150 
151 // Writes compressed data to the stream. This function always returns zero
152 // because this implementation is only for reading compressed data.
WriteZipBuffer(void * opaque,void * stream,const void * buf,uLong)153 uLong WriteZipBuffer(void *opaque, void *stream, const void *buf, uLong)
154 {
155     HILOG_INFO("%{public}s called. opaque=%p, stream=%p, buf=%p", __func__, opaque, stream, buf);
156     return 0;
157 }
158 
159 // Returns the offset from the beginning of the data.
GetOffsetOfZipBuffer(void * opaque,void *)160 long GetOffsetOfZipBuffer(void *opaque, void *)
161 {
162     ZipBuffer *buffer = static_cast<ZipBuffer *>(opaque);
163     if (!buffer) {
164         return -1;
165     }
166     return static_cast<long>(buffer->offset);
167 }
168 
169 // Moves the current offset to the specified position.
SeekZipBuffer(void * opaque,void *,uLong offset,int origin)170 long SeekZipBuffer(void *opaque, void *, uLong offset, int origin)
171 {
172     ZipBuffer *buffer = static_cast<ZipBuffer *>(opaque);
173     if (!buffer) {
174         return -1;
175     }
176     if (origin == ZLIB_FILEFUNC_SEEK_CUR) {
177         buffer->offset = std::min(buffer->offset + static_cast<size_t>(offset), buffer->length);
178         return 0;
179     }
180     if (origin == ZLIB_FILEFUNC_SEEK_END) {
181         buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0;
182         return 0;
183     }
184     if (origin == ZLIB_FILEFUNC_SEEK_SET) {
185         buffer->offset = std::min(buffer->length, static_cast<size_t>(offset));
186         return 0;
187     }
188     HILOG_INFO("%{public}s called. origin is not supported.", __func__);
189     return -1;
190 }
191 
192 // Closes the input offset and deletes all resources used for compressing or
193 // uncompressing data. This function deletes the ZipBuffer object referred by
194 // the opaque parameter since zlib deletes the unzFile object and it does not
195 // use this object any longer.
CloseZipBuffer(void * opaque,void *)196 int CloseZipBuffer(void *opaque, void *)
197 {
198     if (opaque) {
199         free(opaque);
200     }
201     return 0;
202 }
203 
204 // Returns the last error happened when reading or writing data. This function
205 // always returns zero, which means there are not any errors.
GetErrorOfZipBuffer(void *,void *)206 int GetErrorOfZipBuffer(void *, void *)
207 {
208     return 0;
209 }
210 
TimeToZipFileInfo(const struct tm * fileTime,zip_fileinfo & zipInfo)211 bool TimeToZipFileInfo(const struct tm *fileTime, zip_fileinfo &zipInfo)
212 {
213     if (fileTime == nullptr) {
214         return false;
215     }
216 
217     zipInfo.tmz_date.tm_year = (int)fileTime->tm_year + 1900;
218     zipInfo.tmz_date.tm_mon = (int)fileTime->tm_mon + 1;
219     zipInfo.tmz_date.tm_mday = (int)fileTime->tm_mday;
220     zipInfo.tmz_date.tm_hour = (int)fileTime->tm_hour;
221     zipInfo.tmz_date.tm_min = (int)fileTime->tm_min;
222     zipInfo.tmz_date.tm_sec = (int)fileTime->tm_sec;
223     return true;
224 }
225 
OpenForUnzipping(std::string & fileNameUtf8)226 unzFile OpenForUnzipping(std::string &fileNameUtf8)
227 {
228     zlib_filefunc_def *zipFuncPtrs = nullptr;
229     return unzOpen2(fileNameUtf8.c_str(), zipFuncPtrs);
230 }
231 
OpenFdForUnzipping(int zipFD)232 unzFile OpenFdForUnzipping(int zipFD)
233 {
234     zlib_filefunc_def zipFuncs;
235     FillFdOpenFileFunc(&zipFuncs, zipFD);
236     return unzOpen2("fd", &zipFuncs);
237 }
238 
239 // static
PrepareMemoryForUnzipping(const std::string & data)240 unzFile PrepareMemoryForUnzipping(const std::string &data)
241 {
242     if (data.empty()) {
243         return NULL;
244     }
245     ZipBuffer *buffer = static_cast<ZipBuffer *>(malloc(sizeof(ZipBuffer)));
246     if (!buffer) {
247         return NULL;
248     }
249     buffer->data = data.data();
250     buffer->length = data.length();
251     buffer->offset = 0;
252 
253     zlib_filefunc_def zipFunctions;
254     zipFunctions.zopen_file = OpenZipBuffer;
255     zipFunctions.zread_file = ReadZipBuffer;
256     zipFunctions.zwrite_file = WriteZipBuffer;
257     zipFunctions.ztell_file = GetOffsetOfZipBuffer;
258     zipFunctions.zseek_file = SeekZipBuffer;
259     zipFunctions.zclose_file = CloseZipBuffer;
260     zipFunctions.zerror_file = GetErrorOfZipBuffer;
261     zipFunctions.opaque = static_cast<void *>(buffer);
262     return unzOpen2(NULL, &zipFunctions);
263 }
264 
OpenForZipping(const std::string & fileNameUtf8,int appendFlag)265 zipFile OpenForZipping(const std::string &fileNameUtf8, int appendFlag)
266 {
267     zlib_filefunc_def *zipFuncPtrs = NULL;
268     return zipOpen2(fileNameUtf8.c_str(),
269         appendFlag,
270         NULL,
271         zipFuncPtrs);
272 }
273 
OpenFdForZipping(PlatformFile zipFd,int appendFlag)274 zipFile OpenFdForZipping(PlatformFile zipFd, int appendFlag)
275 {
276     zlib_filefunc_def zipFuncs;
277     FillFdOpenFileFunc(&zipFuncs, zipFd);
278     // Passing dummy "fd" filename to zlib.
279     return zipOpen2("fd", appendFlag, NULL, &zipFuncs);
280 }
281 
ZipOpenNewFileInZip(zipFile zipFile,const std::string & strPath,const OPTIONS & options,const struct tm * lastModifiedTime)282 bool ZipOpenNewFileInZip(
283     zipFile zipFile, const std::string &strPath, const OPTIONS &options, const struct tm *lastModifiedTime)
284 {
285     const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11;
286 
287     zip_fileinfo fileInfo = {};
288     TimeToZipFileInfo(lastModifiedTime, fileInfo);
289     if (ZIP_OK != zipOpenNewFileInZip4(zipFile,    // file
290         strPath.c_str(),    // filename
291         &fileInfo,    // zip_fileinfo
292         NULL,    // extrafield_local,
293         0u,   // size_extrafield_local
294         NULL,    // extrafield_global
295         0u,    // size_extrafield_global
296         NULL,    // comment
297         Z_DEFLATED,    // method
298         (int)options.level,    // level:default Z_DEFAULT_COMPRESSION
299         0,    // raw
300         -MAX_WBITS,    // windowBits
301         (int)options.memLevel,    // memLevel: default DEF_MEM_LEVEL
302         (int)options.strategy,    // strategy:default Z_DEFAULT_STRATEGY
303         NULL,    // password
304         0,    // crcForCrypting
305         0,    // versionMadeBy
306         LANGUAGE_ENCODING_FLAG)) {    // flagBase
307         return false;
308     }
309     return true;
310 }
311 
312 }  // namespace LIBZIP
313 }  // namespace AAFwk
314 }  // namespace OHOS
315