1 /*
2  * Copyright (c) 2024 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 <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <dirent.h>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <getopt.h>
25 
26 #include "policycoreutils.h"
27 #ifdef CODE_SIGNATURE_ENABLE
28 #include "code_sign_utils_in_c.h"
29 #endif
30 #include "hnp_installer.h"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
HnpInstallerUidGet(const char * uidIn,int * uidOut)36 static int HnpInstallerUidGet(const char *uidIn, int *uidOut)
37 {
38     int index;
39 
40     for (index = 0; uidIn[index] != '\0'; index++) {
41         if (!isdigit(uidIn[index])) {
42             return HNP_ERRNO_INSTALLER_ARGV_UID_INVALID;
43         }
44     }
45 
46     *uidOut = atoi(uidIn); // 转化为10进制
47     return 0;
48 }
49 
HnpGenerateSoftLinkAllByJson(const char * installPath,const char * dstPath,HnpCfgInfo * hnpCfg)50 static int HnpGenerateSoftLinkAllByJson(const char *installPath, const char *dstPath, HnpCfgInfo *hnpCfg)
51 {
52     char srcFile[MAX_FILE_PATH_LEN];
53     char dstFile[MAX_FILE_PATH_LEN];
54     NativeBinLink *currentLink = hnpCfg->links;
55     char *fileNameTmp;
56 
57     if (access(dstPath, F_OK) != 0) {
58         int ret = mkdir(dstPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
59         if ((ret != 0) && (errno != EEXIST)) {
60             HNP_LOGE("mkdir [%{public}s] unsuccess, ret=%{public}d, errno:%{public}d", dstPath, ret, errno);
61             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
62         }
63     }
64 
65     for (unsigned int i = 0; i < hnpCfg->linkNum; i++) {
66         if (strstr(currentLink->source, "../") || strstr(currentLink->target, "../")) {
67             HNP_LOGE("hnp json link source[%{public}s],target[%{public}s],does not allow the use of ../",
68                 currentLink->source, currentLink->target);
69             return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
70         }
71         int ret = sprintf_s(srcFile, MAX_FILE_PATH_LEN, "%s/%s", installPath, currentLink->source);
72         char *fileName;
73         if (ret < 0) {
74             HNP_LOGE("sprintf install bin src file unsuccess.");
75             return HNP_ERRNO_BASE_SPRINTF_FAILED;
76         }
77         /* 如果target为空则使用源二进制名称 */
78         if (strcmp(currentLink->target, "") == 0) {
79             fileNameTmp = currentLink->source;
80         } else {
81             fileNameTmp = currentLink->target;
82         }
83         fileName = strrchr(fileNameTmp, DIR_SPLIT_SYMBOL);
84         if (fileName == NULL) {
85             fileName = fileNameTmp;
86         } else {
87             fileName++;
88         }
89         ret = sprintf_s(dstFile, MAX_FILE_PATH_LEN, "%s/%s", dstPath, fileName);
90         if (ret < 0) {
91             HNP_LOGE("sprintf install bin dst file unsuccess.");
92             return HNP_ERRNO_BASE_SPRINTF_FAILED;
93         }
94         /* 生成软链接 */
95         ret = HnpSymlink(srcFile, dstFile);
96         if (ret != 0) {
97             return ret;
98         }
99 
100         currentLink++;
101     }
102 
103     return 0;
104 }
105 
HnpGenerateSoftLinkAll(const char * installPath,const char * dstPath)106 static int HnpGenerateSoftLinkAll(const char *installPath, const char *dstPath)
107 {
108     char srcPath[MAX_FILE_PATH_LEN];
109     char srcFile[MAX_FILE_PATH_LEN];
110     char dstFile[MAX_FILE_PATH_LEN];
111     int ret;
112     DIR *dir;
113     struct dirent *entry;
114 
115     ret = sprintf_s(srcPath, MAX_FILE_PATH_LEN, "%s/bin", installPath);
116     if (ret < 0) {
117         HNP_LOGE("sprintf install bin path unsuccess.");
118         return HNP_ERRNO_BASE_SPRINTF_FAILED;
119     }
120 
121     if ((dir = opendir(srcPath)) == NULL) {
122         HNP_LOGI("soft link bin file:%{public}s not exist", srcPath);
123         return 0;
124     }
125 
126     if (access(dstPath, F_OK) != 0) {
127         ret = mkdir(dstPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
128         if ((ret != 0) && (errno != EEXIST)) {
129             closedir(dir);
130             HNP_LOGE("mkdir [%{public}s] unsuccess, ret=%{public}d, errno:%{public}d", dstPath, ret, errno);
131             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
132         }
133     }
134 
135     while (((entry = readdir(dir)) != NULL)) {
136         /* 非二进制文件跳过 */
137         if (entry->d_type != DT_REG) {
138             continue;
139         }
140         ret = sprintf_s(srcFile, MAX_FILE_PATH_LEN, "%s/%s", srcPath, entry->d_name);
141         if (ret < 0) {
142             closedir(dir);
143             HNP_LOGE("sprintf install bin src file unsuccess.");
144             return HNP_ERRNO_BASE_SPRINTF_FAILED;
145         }
146 
147         ret = sprintf_s(dstFile, MAX_FILE_PATH_LEN, "%s/%s", dstPath, entry->d_name);
148         if (ret < 0) {
149             closedir(dir);
150             HNP_LOGE("sprintf install bin dst file unsuccess.");
151             return HNP_ERRNO_BASE_SPRINTF_FAILED;
152         }
153         /* 生成软链接 */
154         ret = HnpSymlink(srcFile, dstFile);
155         if (ret != 0) {
156             closedir(dir);
157             return ret;
158         }
159     }
160 
161     closedir(dir);
162     return 0;
163 }
164 
HnpGenerateSoftLink(const char * installPath,const char * hnpBasePath,HnpCfgInfo * hnpCfg)165 static int HnpGenerateSoftLink(const char *installPath, const char *hnpBasePath, HnpCfgInfo *hnpCfg)
166 {
167     int ret = 0;
168     char binPath[MAX_FILE_PATH_LEN];
169 
170     ret = sprintf_s(binPath, MAX_FILE_PATH_LEN, "%s/bin", hnpBasePath);
171     if (ret < 0) {
172         HNP_LOGE("sprintf install bin path unsuccess.");
173         return HNP_ERRNO_BASE_SPRINTF_FAILED;
174     }
175 
176     if (hnpCfg->linkNum == 0) {
177         ret = HnpGenerateSoftLinkAll(installPath, binPath);
178     } else {
179         ret = HnpGenerateSoftLinkAllByJson(installPath, binPath, hnpCfg);
180     }
181 
182     return ret;
183 }
184 
HnpInstall(const char * hnpFile,HnpInstallInfo * hnpInfo,HnpCfgInfo * hnpCfg,HnpSignMapInfo * hnpSignMapInfos,int * count)185 static int HnpInstall(const char *hnpFile, HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg,
186     HnpSignMapInfo *hnpSignMapInfos, int *count)
187 {
188     int ret;
189 
190     /* 解压hnp文件 */
191     ret = HnpUnZip(hnpFile, hnpInfo->hnpVersionPath, hnpInfo->hnpSignKeyPrefix, hnpSignMapInfos, count);
192     if (ret != 0) {
193         return ret; /* 内部已打印日志 */
194     }
195 
196     /* 生成软链 */
197     return HnpGenerateSoftLink(hnpInfo->hnpVersionPath, hnpInfo->hnpBasePath, hnpCfg);
198 }
199 
HnpUnInstallPublicHnp(const char * packageName,const char * name,const char * version,int uid)200 static int HnpUnInstallPublicHnp(const char* packageName, const char *name, const char *version, int uid)
201 {
202     int ret;
203     char hnpNamePath[MAX_FILE_PATH_LEN];
204     char sandboxPath[MAX_FILE_PATH_LEN];
205 
206     if (sprintf_s(hnpNamePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnppublic/%s.org", uid, name) < 0) {
207         HNP_LOGE("hnp uninstall name path sprintf unsuccess,uid:%{public}d,name:%{public}s", uid, name);
208         return HNP_ERRNO_BASE_SPRINTF_FAILED;
209     }
210 
211     if (sprintf_s(sandboxPath, MAX_FILE_PATH_LEN, HNP_SANDBOX_BASE_PATH"/%s.org", name) < 0) {
212         HNP_LOGE("sprintf unstall base path unsuccess.");
213         return HNP_ERRNO_BASE_SPRINTF_FAILED;
214     }
215 
216     ret = HnpProcessRunCheck(sandboxPath);
217     if (ret != 0) {
218         return ret;
219     }
220 
221     ret = HnpPackageInfoHnpDelete(packageName, name, version);
222     if (ret != 0) {
223         return ret;
224     }
225 
226     return HnpDeleteFolder(hnpNamePath);
227 }
228 
HnpUnInstall(int uid,const char * packageName)229 static int HnpUnInstall(int uid, const char *packageName)
230 {
231     HnpPackageInfo *packageInfo = NULL;
232     int count = 0;
233     char privatePath[MAX_FILE_PATH_LEN];
234     char dstPath[MAX_FILE_PATH_LEN];
235 
236     /* 拼接卸载路径 */
237     if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", uid) < 0) {
238         HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", uid);
239         return HNP_ERRNO_BASE_SPRINTF_FAILED;
240     }
241 
242     /* 验证卸载路径是否存在 */
243     if (access(dstPath, F_OK) != 0) {
244         HNP_LOGE("hnp uninstall uid path[%{public}s] is not exist", dstPath);
245         return HNP_ERRNO_UNINSTALLER_HNP_PATH_NOT_EXIST;
246     }
247 
248     int ret = HnpPackageInfoGet(packageName, &packageInfo, &count);
249     if (ret != 0) {
250         return ret;
251     }
252 
253     /* 卸载公有native */
254     for (int i = 0; i < count; i++) {
255         HNP_LOGI("hnp uninstall start now! name=%{public}s,version=%{public}s,uid=%{public}d,package=%{public}s",
256             packageInfo[i].name, packageInfo[i].version, uid, packageName);
257         ret = HnpUnInstallPublicHnp(packageName, packageInfo[i].name, packageInfo[i].version, uid);
258         HNP_LOGI("hnp uninstall end! ret=%{public}d", ret);
259         if (ret != 0) {
260             free(packageInfo);
261             return ret;
262         }
263     }
264     free(packageInfo);
265 
266     ret = HnpPackageInfoDelete(packageName);
267     if (ret != 0) {
268         return ret;
269     }
270 
271     if (sprintf_s(privatePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnp/%s", uid, packageName) < 0) {
272         HNP_LOGE("hnp uninstall private path sprintf unsuccess, uid:%{public}d,package name[%{public}s]", uid,
273             packageName);
274         return HNP_ERRNO_BASE_SPRINTF_FAILED;
275     }
276 
277     (void)HnpDeleteFolder(privatePath);
278 
279     return 0;
280 }
281 
HnpInstallForceCheck(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)282 static int HnpInstallForceCheck(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
283 {
284     int ret = 0;
285     char *version = NULL;
286 
287     /* 判断安装目录是否存在,存在判断是否是强制安装,如果是则走卸载流程,否则返回错误 */
288     if (access(hnpInfo->hnpSoftwarePath, F_OK) == 0) {
289         if (hnpInfo->hapInstallInfo->isForce == false) {
290             HNP_LOGE("hnp install path[%{public}s] exist, but force is false", hnpInfo->hnpSoftwarePath);
291             return HNP_ERRNO_INSTALLER_PATH_IS_EXIST;
292         }
293         if (hnpInfo->isPublic) {
294             version = HnpPackgeHnpVersionGet(hnpInfo->hapInstallInfo->hapPackageName, hnpCfgInfo->name);
295             if (version != NULL) {
296                 ret = HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfgInfo->name, version,
297                     hnpInfo->hapInstallInfo->uid);
298             }
299         } else {
300             ret = HnpDeleteFolder(hnpInfo->hnpSoftwarePath);
301         }
302         if (ret != 0) {
303             return ret;
304         }
305     }
306 
307     ret = HnpCreateFolder(hnpInfo->hnpVersionPath);
308     if (ret != 0) {
309         return HnpDeleteFolder(hnpInfo->hnpVersionPath);
310     }
311     return ret;
312 }
313 
HnpInstallPathGet(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)314 static int HnpInstallPathGet(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
315 {
316     int ret;
317 
318     /* 拼接安装路径 */
319     ret = sprintf_s(hnpInfo->hnpSoftwarePath, MAX_FILE_PATH_LEN, "%s/%s.org", hnpInfo->hnpBasePath,
320         hnpCfgInfo->name);
321     if (ret < 0) {
322         HNP_LOGE("hnp install sprintf hnp base path unsuccess.");
323         return HNP_ERRNO_BASE_SPRINTF_FAILED;
324     }
325 
326     /* 拼接安装路径 */
327     ret = sprintf_s(hnpInfo->hnpVersionPath, MAX_FILE_PATH_LEN, "%s/%s_%s", hnpInfo->hnpSoftwarePath,
328         hnpCfgInfo->name, hnpCfgInfo->version);
329     if (ret < 0) {
330         HNP_LOGE("hnp install sprintf install path unsuccess.");
331         return HNP_ERRNO_BASE_SPRINTF_FAILED;
332     }
333     if (strstr(hnpInfo->hnpVersionPath, "../")) {
334         HNP_LOGE("hnp version path[%{public}s], does not allow the use of ../", hnpInfo->hnpVersionPath);
335         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
336     }
337 
338     return 0;
339 }
340 
HnpReadAndInstall(char * srcFile,HnpInstallInfo * hnpInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)341 static int HnpReadAndInstall(char *srcFile, HnpInstallInfo *hnpInfo, HnpSignMapInfo *hnpSignMapInfos, int *count)
342 {
343     int ret;
344     HnpCfgInfo hnpCfg = {0};
345 
346     HNP_LOGI("hnp install start now! src file=%{public}s, dst path=%{public}s", srcFile, hnpInfo->hnpBasePath);
347     /* 从hnp zip获取cfg信息 */
348     ret = HnpCfgGetFromZip(srcFile, &hnpCfg);
349     if (ret != 0) {
350         return ret;
351     }
352 
353     ret = HnpInstallPathGet(&hnpCfg, hnpInfo);
354     if (ret != 0) {
355         // 释放软链接占用的内存
356         if (hnpCfg.links != NULL) {
357             free(hnpCfg.links);
358         }
359         return ret;
360     }
361 
362     /* 存在对应版本的公有hnp包跳过安装 */
363     if (access(hnpInfo->hnpVersionPath, F_OK) == 0 && hnpInfo->isPublic) {
364         // 释放软链接占用的内存
365         if (hnpCfg.links != NULL) {
366             free(hnpCfg.links);
367         }
368         return HnpInstallInfoJsonWrite(hnpInfo->hapInstallInfo->hapPackageName, &hnpCfg);
369     }
370 
371     ret = HnpInstallForceCheck(&hnpCfg, hnpInfo);
372     if (ret != 0) {
373         // 释放软链接占用的内存
374         if (hnpCfg.links != NULL) {
375             free(hnpCfg.links);
376         }
377         return ret;
378     }
379 
380     /* hnp安装 */
381     ret = HnpInstall(srcFile, hnpInfo, &hnpCfg, hnpSignMapInfos, count);
382     // 释放软链接占用的内存
383     if (hnpCfg.links != NULL) {
384         free(hnpCfg.links);
385     }
386     if (ret != 0) {
387         HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
388             hnpInfo->hapInstallInfo->uid);
389         return ret;
390     }
391     if (hnpInfo->isPublic) {
392         ret = HnpInstallInfoJsonWrite(hnpInfo->hapInstallInfo->hapPackageName, &hnpCfg);
393         if (ret != 0) {
394             HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
395                 hnpInfo->hapInstallInfo->uid);
396         }
397     }
398 
399     return ret;
400 }
401 
HnpFileCheck(const char * file)402 static bool HnpFileCheck(const char *file)
403 {
404     const char suffix[] = ".hnp";
405     int len = strlen(file);
406     int suffixLen = strlen(suffix);
407     if ((len >= suffixLen) && (strcmp(file + len - suffixLen, suffix) == 0)) {
408         return true;
409     }
410 
411     return false;
412 }
413 
HnpPackageGetAndInstall(const char * dirPath,HnpInstallInfo * hnpInfo,char * sunDir,HnpSignMapInfo * hnpSignMapInfos,int * count)414 static int HnpPackageGetAndInstall(const char *dirPath, HnpInstallInfo *hnpInfo, char *sunDir,
415     HnpSignMapInfo *hnpSignMapInfos, int *count)
416 {
417     DIR *dir;
418     struct dirent *entry;
419     char path[MAX_FILE_PATH_LEN];
420     char sunDirNew[MAX_FILE_PATH_LEN];
421 
422     if ((dir = opendir(dirPath)) == NULL) {
423         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", dirPath, errno);
424         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
425     }
426 
427     while ((entry = readdir(dir)) != NULL) {
428         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
429             continue;
430         }
431         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", dirPath, entry->d_name) < 0) {
432             HNP_LOGE("hnp install sprintf unsuccess, dir[%{public}s], path[%{public}s]", dirPath, entry->d_name);
433             closedir(dir);
434             return HNP_ERRNO_BASE_SPRINTF_FAILED;
435         }
436 
437         if (entry->d_type == DT_DIR) {
438             if (sprintf_s(sunDirNew, MAX_FILE_PATH_LEN, "%s%s/", sunDir, entry->d_name) < 0) {
439                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
440                 closedir(dir);
441                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
442             }
443             int ret = HnpPackageGetAndInstall(path, hnpInfo, sunDirNew, hnpSignMapInfos, count);
444             if (ret != 0) {
445                 closedir(dir);
446                 return ret;
447             }
448         } else {
449             if (HnpFileCheck(path) == false) {
450                 continue;
451             }
452             if (sprintf_s(hnpInfo->hnpSignKeyPrefix, MAX_FILE_PATH_LEN, "hnp/%s/%s%s", hnpInfo->hapInstallInfo->abi,
453                 sunDir, entry->d_name) < 0) {
454                 HNP_LOGE("hnp install sprintf unsuccess,sub[%{public}s],path[%{public}s]", sunDir, entry->d_name);
455                 closedir(dir);
456                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
457             }
458             int ret = HnpReadAndInstall(path, hnpInfo, hnpSignMapInfos, count);
459             HNP_LOGI("hnp install end, ret=%{public}d", ret);
460             if (ret != 0) {
461                 closedir(dir);
462                 return ret;
463             }
464         }
465     }
466     closedir(dir);
467     return 0;
468 }
469 
HapReadAndInstall(const char * dstPath,HapInstallInfo * installInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)470 static int HapReadAndInstall(const char *dstPath, HapInstallInfo *installInfo, HnpSignMapInfo *hnpSignMapInfos,
471     int *count)
472 {
473     struct dirent *entry;
474     char hnpPath[MAX_FILE_PATH_LEN];
475     HnpInstallInfo hnpInfo = {0};
476     int ret;
477 
478     DIR *dir = opendir(installInfo->hnpRootPath);
479     if (dir == NULL) {
480         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", installInfo->hnpRootPath, errno);
481         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
482     }
483 
484     hnpInfo.hapInstallInfo = installInfo;
485     /* 遍历src目录 */
486     while ((entry = readdir(dir)) != NULL) {
487         if (strcmp(entry->d_name, "public") == 0) {
488             hnpInfo.isPublic = true;
489             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnppublic", dstPath) < 0) ||
490                 (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/public", installInfo->hnpRootPath) < 0)) {
491                 HNP_LOGE("hnp install public base path sprintf unsuccess.");
492                 closedir(dir);
493                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
494             }
495         } else if (strcmp(entry->d_name, "private") == 0) {
496             hnpInfo.isPublic = false;
497             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnp/%s", dstPath,
498                 installInfo->hapPackageName) < 0) || (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/private",
499                 installInfo->hnpRootPath) < 0)) {
500                 HNP_LOGE("hnp install private base path sprintf unsuccess.");
501                 closedir(dir);
502                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
503             }
504         } else {
505             continue;
506         }
507 
508         ret = HnpPackageGetAndInstall(hnpPath, &hnpInfo, "", hnpSignMapInfos, count);
509         if (ret != 0) {
510             closedir(dir);
511             return ret;
512         }
513     }
514 
515     closedir(dir);
516     return 0;
517 }
518 
HnpInstallHnpFileCountGet(char * hnpPath,int * count)519 static int HnpInstallHnpFileCountGet(char *hnpPath, int *count)
520 {
521     DIR *dir;
522     struct dirent *entry;
523     char path[MAX_FILE_PATH_LEN];
524     int ret;
525 
526     if ((dir = opendir(hnpPath)) == NULL) {
527         HNP_LOGE("hnp install count get opendir:%{public}s unsuccess, errno=%{public}d", hnpPath, errno);
528         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
529     }
530 
531     while ((entry = readdir(dir)) != NULL) {
532         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
533             continue;
534         }
535 
536         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
537             HNP_LOGE("hnp install count get sprintf unsuccess, dir[%{public}s], path[%{public}s]", hnpPath,
538                 entry->d_name);
539             closedir(dir);
540             return HNP_ERRNO_BASE_SPRINTF_FAILED;
541         }
542 
543         if (entry->d_type == DT_DIR) {
544             if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
545                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
546                 closedir(dir);
547                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
548             }
549             ret = HnpInstallHnpFileCountGet(path, count);
550             if (ret != 0) {
551                 closedir(dir);
552                 return ret;
553             }
554         } else {
555             if (HnpFileCheck(path) == false) {
556                 continue;
557             }
558             ret = HnpFileCountGet(path, count);
559             if (ret != 0) {
560                 closedir(dir);
561                 return ret;
562             }
563         }
564     }
565 
566     closedir(dir);
567     return 0;
568 }
569 
HnpInstallHapFileCountGet(const char * root,int * count)570 static int HnpInstallHapFileCountGet(const char *root, int *count)
571 {
572     struct dirent *entry;
573     char hnpPath[MAX_FILE_PATH_LEN];
574 
575     DIR *dir = opendir(root);
576     if (dir == NULL) {
577         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", root, errno);
578         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
579     }
580 
581     while ((entry = readdir(dir)) != NULL) {
582         if ((strcmp(entry->d_name, "public") != 0) && (strcmp(entry->d_name, "private") != 0)) {
583             continue;
584         }
585         if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", root, entry->d_name) < 0) {
586             HNP_LOGE("hnp install private base path sprintf unsuccess.");
587             closedir(dir);
588             return HNP_ERRNO_BASE_SPRINTF_FAILED;
589         }
590 
591         int ret = HnpInstallHnpFileCountGet(hnpPath, count);
592         if (ret != 0) {
593             closedir(dir);
594             return ret;
595         }
596     }
597 
598     closedir(dir);
599     return 0;
600 }
601 
SetHnpRestorecon(char * path)602 static int SetHnpRestorecon(char *path)
603 {
604     int ret;
605     char publicPath[MAX_FILE_PATH_LEN] = {0};
606     if (sprintf_s(publicPath, MAX_FILE_PATH_LEN, "%s/hnppublic", path) < 0) {
607         HNP_LOGE("sprintf fail, get hnp restorecon path fail");
608         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
609     }
610 
611     if (access(publicPath, F_OK) != 0) {
612         ret = mkdir(publicPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
613         if ((ret != 0) && (errno != EEXIST)) {
614             HNP_LOGE("mkdir public path fail");
615             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
616         }
617     }
618 
619     if (RestoreconRecurse(publicPath)) {
620         HNP_LOGE("restorecon hnp path fail");
621         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
622     }
623 
624     return 0;
625 }
626 
CheckInstallPath(char * dstPath,HapInstallInfo * installInfo)627 static int CheckInstallPath(char *dstPath, HapInstallInfo *installInfo)
628 {
629     /* 拼接安装路径 */
630     if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", installInfo->uid) < 0) {
631         HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", installInfo->uid);
632         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
633     }
634 
635     /* 验证安装路径是否存在 */
636     if (access(dstPath, F_OK) != 0) {
637         HNP_LOGE("hnp install uid path[%{public}s] is not exist", dstPath);
638         return HNP_ERRNO_INSTALLER_GET_REALPATH_FAILED;
639     }
640 
641     /* restorecon hnp 安装目录 */
642     return SetHnpRestorecon(dstPath);
643 }
644 
HnpInsatllPre(HapInstallInfo * installInfo)645 static int HnpInsatllPre(HapInstallInfo *installInfo)
646 {
647     char dstPath[MAX_FILE_PATH_LEN];
648     int count = 0;
649     HnpSignMapInfo *hnpSignMapInfos = NULL;
650 #ifdef CODE_SIGNATURE_ENABLE
651     struct EntryMapEntryData data = {0};
652     int i;
653 #endif
654     int ret;
655 
656     if ((ret = CheckInstallPath(dstPath, installInfo)) != 0 ||
657         (ret = HnpInstallHapFileCountGet(installInfo->hnpRootPath, &count)) != 0) {
658         return ret;
659     }
660 
661     if (count > 0) {
662         hnpSignMapInfos = (HnpSignMapInfo *)malloc(sizeof(HnpSignMapInfo) * count);
663         if (hnpSignMapInfos == NULL) {
664             return HNP_ERRNO_NOMEM;
665         }
666     }
667 
668     count = 0;
669     ret = HapReadAndInstall(dstPath, installInfo, hnpSignMapInfos, &count);
670     HNP_LOGI("sign start hap path[%{public}s],abi[%{public}s],count=%{public}d", installInfo->hapPath, installInfo->abi,
671         count);
672 #ifdef CODE_SIGNATURE_ENABLE
673     if ((ret == 0) && (count > 0)) {
674         data.entries = malloc(sizeof(struct EntryMapEntry) * count);
675         if (data.entries == NULL) {
676             free(hnpSignMapInfos);
677             return HNP_ERRNO_NOMEM;
678         }
679         for (i = 0; i < count; i++) {
680             data.entries[i].key = hnpSignMapInfos[i].key;
681             data.entries[i].value = hnpSignMapInfos[i].value;
682         }
683         data.count = count;
684         ret = EnforceCodeSignForApp(installInfo->hapPath, &data, FILE_ENTRY_ONLY);
685         HNP_LOGI("sign end ret=%{public}d,last key[%{public}s],value[%{public}s]", ret, data.entries[i - 1].key,
686             data.entries[i - 1].value);
687         free(data.entries);
688         if (ret != 0) {
689             HnpUnInstall(installInfo->uid, installInfo->hapPackageName);
690             ret = HNP_ERRNO_INSTALLER_CODE_SIGN_APP_FAILED;
691         }
692     }
693 #endif
694     free(hnpSignMapInfos);
695     return ret;
696 }
697 
ParseInstallArgs(int argc,char * argv[],HapInstallInfo * installInfo)698 static int ParseInstallArgs(int argc, char *argv[], HapInstallInfo *installInfo)
699 {
700     int ret;
701     int ch;
702 
703     optind = 1; // 从头开始遍历参数
704     while ((ch = getopt_long(argc, argv, "hu:p:i:s:a:f", NULL, NULL)) != -1) {
705         switch (ch) {
706             case 'h' :
707                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
708             case 'u': // 用户id
709                 ret = HnpInstallerUidGet(optarg, &installInfo->uid);
710                 if (ret != 0) {
711                     HNP_LOGE("hnp install argv uid[%{public}s] invalid", optarg);
712                     return ret;
713                 }
714                 break;
715             case 'p': // app名称
716                 installInfo->hapPackageName = (char *)optarg;
717                 break;
718             case 'i': // hnp安装目录
719                 installInfo->hnpRootPath = (char *)optarg;
720                 break;
721             case 's': // hap目录
722                 installInfo->hapPath = (char *)optarg;
723                 break;
724             case 'a': // 系统abi路径
725                 installInfo->abi = (char *)optarg;
726                 break;
727             case 'f': // is force
728                 installInfo->isForce = true;
729                 break;
730             default:
731                 break;
732         }
733     }
734 
735     if ((installInfo->uid == -1) || (installInfo->hnpRootPath == NULL) || (installInfo->hapPath == NULL) ||
736         (installInfo->abi == NULL) || (installInfo->hapPackageName == NULL)) {
737         HNP_LOGE("argv params is missing.");
738         return HNP_ERRNO_OPERATOR_ARGV_MISS;
739     }
740 
741     return 0;
742 }
743 
HnpCmdInstall(int argc,char * argv[])744 int HnpCmdInstall(int argc, char *argv[])
745 {
746     HapInstallInfo installInfo = {0};
747 
748     installInfo.uid = -1; // 预设值,判断简单
749     // 解析参数并生成安装信息
750     int ret = ParseInstallArgs(argc, argv, &installInfo);
751     if (ret != 0) {
752         return ret;
753     }
754 
755     return HnpInsatllPre(&installInfo);
756 }
757 
HnpCmdUnInstall(int argc,char * argv[])758 int HnpCmdUnInstall(int argc, char *argv[])
759 {
760     int uid;
761     char *uidArg = NULL;
762     char *packageName = NULL;
763     int ret;
764     int ch;
765 
766     optind = 1; // 从头开始遍历参数
767     while ((ch = getopt_long(argc, argv, "hu:p:", NULL, NULL)) != -1) {
768         switch (ch) {
769             case 'h' :
770                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
771             case 'u': // uid
772                 uidArg = optarg;
773                 ret = HnpInstallerUidGet(uidArg, &uid);
774                 if (ret != 0) {
775                     HNP_LOGE("hnp install arg uid[%{public}s] invalid", uidArg);
776                     return ret;
777                 }
778                 break;
779             case 'p': // hnp package name
780                 packageName = (char *)optarg;
781                 break;
782             default:
783                 break;
784             }
785     }
786 
787     if ((uidArg == NULL) || (packageName == NULL)) {
788         HNP_LOGE("hnp uninstall params invalid uid[%{public}s], package name[%{public}s]", uidArg, packageName);
789         return HNP_ERRNO_OPERATOR_ARGV_MISS;
790     }
791 
792     return HnpUnInstall(uid, packageName);
793 }
794 
795 #ifdef __cplusplus
796 }
797 #endif
798