1 /*
2 * Copyright (c) 2025 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 "app_log_wrapper.h"
17 #include "bundle_error.h"
18 #include "zip_ffi.h"
19 #include "zlib.h"
20
21 using namespace OHOS::CJSystemapi::BundleManager;
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace LIBZIP {
ZlibBusinessError(int32_t errCode)26 static inline ErrCode ZlibBusinessError(int32_t errCode)
27 {
28 if (errCode == Z_STREAM_ERROR) {
29 return ERR_ZLIB_ZSTREAM_ERROR;
30 } else if (errCode == Z_MEM_ERROR) {
31 return ERR_ZLIB_MEMORY_ALLOC_FAILED;
32 } else if (errCode == Z_BUF_ERROR) {
33 return ERR_ZLIB_BUFFER_ERROR;
34 } else {
35 return ERR_ZLIB_INTERNAL_STRUCT_ERROR;
36 }
37 }
38
39 struct CjGZipEntity {
40 int32_t Dopen(int32_t fd, const char* mode);
41 int32_t Open(const char* path, const char* mode);
42 int32_t Eof();
43 int32_t Close(int32_t* errCode);
44 int64_t Write(uint8_t* buf, int64_t len, int32_t* errCode);
45 int64_t Read(uint8_t* buf, int64_t len, int32_t* errCode);
46 int32_t Puts(const char* cstr, int32_t* errCode);
47 char* GzGets(uint8_t* buf, int64_t len, int32_t* errCode);
48
49 gzFile gzs = {};
50 };
51
Dopen(int32_t fd,const char * mode)52 int32_t CjGZipEntity::Dopen(int32_t fd, const char* mode)
53 {
54 gzs = gzdopen(fd, mode);
55 if (gzs == nullptr) {
56 APP_LOGE("gzdopen return nullptr");
57 return ERR_ZLIB_NO_SUCH_FILE_OR_MODE_ERROR;
58 }
59 return 0;
60 }
61
Open(const char * path,const char * mode)62 int32_t CjGZipEntity::Open(const char* path, const char* mode)
63 {
64 #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) && !defined(Z_LARGE64)
65 gzs = gzopen64(path, mode);
66 #else
67 gzs = gzopen(path, mode);
68 #endif
69 if (gzs == nullptr) {
70 APP_LOGE("gzopen return nullptr");
71 return ERR_ZLIB_NO_SUCH_FILE_OR_MODE_ERROR;
72 }
73 return 0;
74 }
75
Eof()76 int32_t CjGZipEntity::Eof()
77 {
78 return gzeof(gzs);
79 }
80
Close(int32_t * errCode)81 int32_t CjGZipEntity::Close(int32_t* errCode)
82 {
83 auto ret = gzclose(gzs);
84 if (ret < 0) {
85 APP_LOGE("gzclose return failed, code: %{public}d", ret);
86 *errCode = ZlibBusinessError(ret);
87 }
88 return ret;
89 }
90
Write(uint8_t * buf,int64_t len,int32_t * errCode)91 int64_t CjGZipEntity::Write(uint8_t* buf, int64_t len, int32_t* errCode)
92 {
93 int64_t writeLen = gzwrite(gzs, buf, static_cast<unsigned int>(len));
94 if (writeLen <= 0) {
95 APP_LOGE("gzwrite return failed, code: %{public}d", static_cast<int32_t>(writeLen));
96 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
97 }
98 return writeLen;
99 }
100
Read(uint8_t * buf,int64_t len,int32_t * errCode)101 int64_t CjGZipEntity::Read(uint8_t* buf, int64_t len, int32_t* errCode)
102 {
103 int64_t readLen = gzread(gzs, reinterpret_cast<void*>(buf), static_cast<unsigned int>(len));
104 if (readLen < 0) {
105 APP_LOGE("gzread return failed, code: %{public}d", static_cast<int32_t>(readLen));
106 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
107 }
108 return readLen;
109 }
110
Puts(const char * cstr,int32_t * errCode)111 int32_t CjGZipEntity::Puts(const char* cstr, int32_t* errCode)
112 {
113 int64_t putLen = gzputs(gzs, cstr);
114 if (putLen < 0) {
115 APP_LOGE("gzputs return failed, code: %{public}d", static_cast<int32_t>(putLen));
116 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
117 }
118 return putLen;
119 }
120
GzGets(uint8_t * buf,int64_t len,int32_t * errCode)121 char* CjGZipEntity::GzGets(uint8_t* buf, int64_t len, int32_t* errCode)
122 {
123 auto nullTerminatedString = gzgets(gzs, reinterpret_cast<char*>(buf), static_cast<int>(len));
124 if (!nullTerminatedString) {
125 APP_LOGE("gzgets return failed");
126 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
127 }
128 return nullTerminatedString;
129 }
130
131 extern "C" {
FfiBundleManagerGZipInstCreate()132 FFI_EXPORT void* FfiBundleManagerGZipInstCreate()
133 {
134 return new CjGZipEntity();
135 }
136
FfiBundleManagerGZipInstDestroy(void * ffiInst)137 FFI_EXPORT void FfiBundleManagerGZipInstDestroy(void* ffiInst)
138 {
139 delete static_cast<CjGZipEntity*>(ffiInst);
140 }
141
FfiBundleManagerGZipDopen(void * ffiInst,int32_t fd,const char * mode,int32_t * errCode)142 FFI_EXPORT void FfiBundleManagerGZipDopen(void* ffiInst, int32_t fd, const char* mode, int32_t* errCode)
143 {
144 *errCode = 0;
145 if (ffiInst == nullptr || mode == nullptr) {
146 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
147 APP_LOGE("FfiBundleManagerGZipDopen param check failed");
148 return;
149 }
150 auto entity = static_cast<CjGZipEntity*>(ffiInst);
151 *errCode = entity->Dopen(fd, mode);
152 return;
153 }
154
FfiBundleManagerGZipOpen(void * ffiInst,const char * path,const char * mode,int32_t * errCode)155 FFI_EXPORT void FfiBundleManagerGZipOpen(void* ffiInst, const char* path, const char* mode, int32_t* errCode)
156 {
157 *errCode = 0;
158 if (ffiInst == nullptr || path == nullptr || mode == nullptr) {
159 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
160 APP_LOGE("FfiBundleManagerGZipOpen param check failed");
161 return;
162 }
163 auto entity = static_cast<CjGZipEntity*>(ffiInst);
164 *errCode = entity->Open(path, mode);
165 return;
166 }
167
FfiBundleManagerGZipEof(void * ffiInst,int32_t * errCode)168 FFI_EXPORT int32_t FfiBundleManagerGZipEof(void* ffiInst, int32_t* errCode)
169 {
170 *errCode = 0;
171 if (ffiInst == nullptr) {
172 APP_LOGE("FfiBundleManagerGZipEof param check failed");
173 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
174 return 0;
175 }
176 auto entity = static_cast<CjGZipEntity*>(ffiInst);
177 return entity->Eof();
178 }
179
FfiBundleManagerGZipClose(void * ffiInst,int32_t * errCode)180 FFI_EXPORT int32_t FfiBundleManagerGZipClose(void* ffiInst, int32_t* errCode)
181 {
182 *errCode = 0;
183 if (ffiInst == nullptr) {
184 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
185 APP_LOGE("FfiBundleManagerGZipClose param check failed");
186 return 0;
187 }
188 auto entity = static_cast<CjGZipEntity*>(ffiInst);
189 return entity->Close(errCode);
190 }
191
FfiBundleManagerGZipWrite(void * ffiInst,uint8_t * buf,int64_t len,int32_t * errCode)192 FFI_EXPORT int64_t FfiBundleManagerGZipWrite(void* ffiInst, uint8_t* buf, int64_t len, int32_t* errCode)
193 {
194 *errCode = 0;
195 if (ffiInst == nullptr || buf == nullptr || len <= 0) {
196 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
197 APP_LOGE("FfiBundleManagerGZipWrite param check failed");
198 return 0;
199 }
200 auto entity = static_cast<CjGZipEntity*>(ffiInst);
201 return entity->Write(buf, len, errCode);
202 }
203
FfiBundleManagerGZipRead(void * ffiInst,uint8_t * buf,int64_t len,int32_t * errCode)204 FFI_EXPORT int64_t FfiBundleManagerGZipRead(void* ffiInst, uint8_t* buf, int64_t len, int32_t* errCode)
205 {
206 *errCode = 0;
207 if (ffiInst == nullptr || buf == nullptr || len <= 0) {
208 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
209 APP_LOGE("FfiBundleManagerGZipRead param check failed");
210 return 0;
211 }
212 auto entity = static_cast<CjGZipEntity*>(ffiInst);
213 return entity->Read(buf, len, errCode);
214 }
215
FfiBundleManagerGZipPuts(void * ffiInst,const char * cstr,int32_t * errCode)216 FFI_EXPORT int32_t FfiBundleManagerGZipPuts(void* ffiInst, const char* cstr, int32_t* errCode)
217 {
218 *errCode = 0;
219 if (ffiInst == nullptr || cstr == nullptr) {
220 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
221 APP_LOGE("FfiBundleManagerGZipPuts param check failed");
222 return 0;
223 }
224 auto entity = static_cast<CjGZipEntity*>(ffiInst);
225 return entity->Puts(cstr, errCode);
226 }
227
FfiBundleManagerGZipGets(void * ffiInst,uint8_t * buf,int64_t len,int32_t * errCode)228 FFI_EXPORT char* FfiBundleManagerGZipGets(void* ffiInst, uint8_t* buf, int64_t len, int32_t* errCode)
229 {
230 *errCode = 0;
231 if (ffiInst == nullptr || buf == nullptr || len <= 0) {
232 *errCode = ERR_ZLIB_INTERNAL_STRUCT_ERROR;
233 APP_LOGE("FfiBundleManagerGZipGets param check failed");
234 return 0;
235 }
236 auto entity = static_cast<CjGZipEntity*>(ffiInst);
237 return entity->GzGets(buf, len, errCode);
238 }
239 } // extern "C"
240 } // namespace LIBZIP
241 } // namespace AppExecFwk
242 } // namespace OHOS
243