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 
16 #include "gt_extractor_util.h"
17 
18 #include <climits>
19 #include "appexecfwk_errors.h"
20 #include "bundle_common.h"
21 #include "bundle_util.h"
22 #include "bundlems_log.h"
23 #include "cstdio"
24 #include "dirent.h"
25 #include "fcntl.h"
26 #include "sys/stat.h"
27 #include "unistd.h"
28 #include "utils.h"
29 
30 namespace OHOS {
31 const uint8_t MAGIC_NUMBER_VALUE = 190;
32 const uint8_t SHIFT_NUM = 8;
33 
ReadInt(int32_t fp)34 uint32_t GtExtractorUtil::ReadInt(int32_t fp)
35 {
36     unsigned char buf[INT_LENGTH] = {0};
37     if (read(fp, buf, INT_LENGTH) != INT_LENGTH) {
38         return UINT_MAX;
39     }
40 
41     uint32_t result = 0;
42     for (uint8_t i = 0; i < INT_LENGTH; i++) {
43         if (result > MAX_INT) {
44             return UINT_MAX;
45         }
46         result += (static_cast<uint32_t>(buf[i])) << (SHIFT_NUM * (INT_LENGTH - i - 1));
47     }
48     return result;
49 }
50 
CheckMagicNumber(int32_t fp)51 bool GtExtractorUtil::CheckMagicNumber(int32_t fp)
52 {
53     unsigned char buf[MAGIC_NUMBER_LEN] = {0};
54     if (read(fp, buf, MAGIC_NUMBER_LEN) != MAGIC_NUMBER_LEN) {
55         return false;
56     }
57     if (static_cast<uint8_t>(buf[MAGIC_NUMBER_LEN - 1]) != MAGIC_NUMBER_VALUE) {
58         return false;
59     }
60     return true;
61 }
62 
ReadLong(int32_t fp)63 uint64_t GtExtractorUtil::ReadLong(int32_t fp)
64 {
65     unsigned char buf[LONG_LENGTH] = {0};
66     if (read(fp, buf, LONG_LENGTH) != LONG_LENGTH) {
67         return 0;
68     }
69 
70     uint64_t result = 0;
71     for (uint8_t i = 0; i < LONG_LENGTH; i++) {
72         if (result > LONG_MAX) {
73             return 0;
74         }
75         result += (static_cast<uint64_t>(buf[i])) << (SHIFT_NUM * (LONG_LENGTH - i - 1));
76     }
77     return result;
78 }
79 
ReadString(int32_t fp,uint32_t len)80 unsigned char *GtExtractorUtil::ReadString(int32_t fp, uint32_t len)
81 {
82     unsigned char *buf = reinterpret_cast<unsigned char *>(UI_Malloc((len + 1) * sizeof(unsigned char)));
83     if (buf == nullptr) {
84         return nullptr;
85     }
86 
87     if (len == 0) {
88         *buf = '\0';
89         return buf;
90     }
91 
92     if (read(fp, buf, len) != len) {
93         UI_Free(buf);
94         return nullptr;
95     }
96     *(buf + len) = '\0';
97     return buf;
98 }
99 
ExtractFileHeaderInfo(int32_t fp,char ** bundleName)100 uint8_t GtExtractorUtil::ExtractFileHeaderInfo(int32_t fp, char **bundleName)
101 {
102     if (!CheckMagicNumber(fp)) {
103         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
104     }
105 
106     uint32_t bundleNameLen = ReadInt(fp);
107     if (bundleNameLen == UINT_MAX) {
108         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
109     }
110 
111     if ((*bundleName = reinterpret_cast<char *>(ReadString(fp, bundleNameLen))) == nullptr) {
112         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
113     }
114     return ERR_OK;
115 }
116 
ExtractFileToPath(const char * appInstallPath,int32_t fp,uint64_t & fileSize,char ** fileName,char ** relativeFilePath)117 uint8_t GtExtractorUtil::ExtractFileToPath(const char *appInstallPath, int32_t fp, uint64_t &fileSize, char **fileName,
118     char **relativeFilePath)
119 {
120     RefreshAllServiceTimeStamp();
121     uint8_t errorCode = ExtractFileAttr(fp, fileName, relativeFilePath, fileSize);
122     if (errorCode != ERR_OK) {
123         return errorCode;
124     }
125 
126     if (!HasWrittenFile(appInstallPath, *relativeFilePath, *fileName, fp, fileSize)) {
127         return ERR_APPEXECFWK_INSTALL_FAILED_CREATE_FILE_ERROR;
128     }
129     return ERR_OK;
130 }
131 
ExtractFileAttr(int32_t fp,char ** fileName,char ** relativeFilePath,uint64_t & fileSize)132 uint8_t GtExtractorUtil::ExtractFileAttr(int32_t fp, char **fileName, char **relativeFilePath, uint64_t &fileSize)
133 {
134     uint32_t nameLen = ReadInt(fp);
135     if (nameLen == UINT_MAX) {
136         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read name Int fail");
137         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
138     }
139 
140     if ((*fileName = reinterpret_cast<char *>(ReadString(fp, nameLen))) == nullptr) {
141         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read fileName fail");
142         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
143     }
144 
145     uint32_t pathLen = ReadInt(fp);
146     if (pathLen == UINT_MAX) {
147         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read path Int fail");
148         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
149     } else {
150         if ((*relativeFilePath = reinterpret_cast<char *>(ReadString(fp, pathLen))) == nullptr) {
151             HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read relativeFilePath fail");
152             return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
153         }
154     }
155 
156     fileSize = ReadLong(fp);
157     if (fileSize == 0) {
158         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read fail size fail");
159         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
160     }
161     return ERR_OK;
162 }
163 
ExtractFileAttr(int32_t fp,char ** fileName,uint32_t & pathLen,uint64_t & fileSize)164 uint8_t GtExtractorUtil::ExtractFileAttr(int32_t fp, char **fileName, uint32_t &pathLen, uint64_t &fileSize)
165 {
166     uint32_t nameLen = ReadInt(fp);
167     if (nameLen == UINT_MAX) {
168         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read name Int fail");
169         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
170     }
171 
172     if ((*fileName = reinterpret_cast<char *>(ReadString(fp, nameLen))) == nullptr) {
173         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read fileName fail");
174         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
175     }
176 
177     pathLen = ReadInt(fp);
178     if (pathLen == UINT_MAX) {
179         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read path Int fail");
180         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
181     } else {
182         int32_t ret = lseek(fp, pathLen, SEEK_CUR);
183         if (ret < 0) {
184             return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
185         }
186     }
187 
188     fileSize = ReadLong(fp);
189     if (fileSize == 0) {
190         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] Read fail size fail");
191         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_DATA_INVALID;
192     }
193     return ERR_OK;
194 }
195 
HasWrittenFile(const char * installPath,const char * path,const char * filename,int32_t fp,uint64_t size)196 bool GtExtractorUtil::HasWrittenFile(const char *installPath, const char *path, const char *filename, int32_t fp,
197     uint64_t size)
198 {
199     if (installPath == nullptr || path == nullptr || filename == nullptr) {
200         return false;
201     }
202 
203     int32_t len = strlen(installPath) + strlen(path) + 1;
204     char *destPath = reinterpret_cast<char *>(UI_Malloc(len));
205     if (destPath == nullptr) {
206         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] malloc destPath addr fail");
207         return false;
208     }
209     if (sprintf_s(destPath, len, "%s%s", installPath, path) < 0) {
210         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] strcat destPath path fail");
211         UI_Free(destPath);
212         return false;
213     }
214 
215     if (!BundleUtil::MkDirs(destPath)) {
216         UI_Free(destPath);
217         return false;
218     }
219     UI_Free(destPath);
220 
221     char destName[PATH_LENGTH] = { 0 };
222     if (sprintf_s(destName, PATH_LENGTH, "%s%s/%s", installPath, path, filename) < 0) {
223         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] strcat file path fail");
224         return false;
225     }
226 
227     if (!HasCopiedData(destName, fp, size)) {
228         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] copy file data fail");
229         return false;
230     }
231     return true;
232 }
233 
HasCopiedData(const char * filePath,int32_t fp,uint64_t size)234 bool GtExtractorUtil::HasCopiedData(const char *filePath, int32_t fp, uint64_t size)
235 {
236     uint64_t remain = size;
237     uint64_t reading = (remain > READ_SIZE) ? READ_SIZE : remain;
238 
239     if (!BundleUtil::CheckRealPath(filePath)) {
240         return false;
241     }
242 
243     int32_t dfp = open(filePath, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
244     if (dfp < 0) {
245         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] open file when copy file data");
246         return false;
247     }
248 
249     char *buf = reinterpret_cast<char *>(UI_Malloc(reading));
250     if (buf == nullptr) {
251         close(dfp);
252         return false;
253     }
254     while (remain > 0) {
255         int32_t ret = read(fp, buf, reading);
256         if (ret < 0 || ret != reading) {
257             HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] read file when copy file data");
258             close(dfp);
259             UI_Free(buf);
260             return false;
261         }
262         ret = write(dfp, buf, reading);
263         if (ret < 0 || ret != reading) {
264             HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] write file when copy file data");
265             close(dfp);
266             UI_Free(buf);
267             return false;
268         }
269         remain = remain - reading;
270         reading = (remain > READ_SIZE) ? READ_SIZE : remain;
271     }
272     UI_Free(buf);
273     close(dfp);
274     return true;
275 }
276 } // namespace OHOS