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
33extern "C" {
34#endif
35
36static 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
50static 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
106static 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
165static 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
185static 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
200/**
201 * 卸载公共hnp.
202 *
203 * @param packageName hap名称.
204 * @param name  hnp名称
205 * @param version 版本号.
206 * @param uid 用户id.
207 * @param isInstallVersion 是否卸载安装版本.
208 *
209 * @return 0:success;other means failure.
210 */
211static int HnpUnInstallPublicHnp(const char* packageName, const char *name, const char *version, int uid,
212    bool isInstallVersion)
213{
214    int ret;
215    char hnpNamePath[MAX_FILE_PATH_LEN];
216    char hnpVersionPath[MAX_FILE_PATH_LEN];
217    char sandboxPath[MAX_FILE_PATH_LEN];
218
219    if (sprintf_s(hnpNamePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnppublic/%s.org", uid, name) < 0) {
220        HNP_LOGE("hnp uninstall name path sprintf unsuccess,uid:%{public}d,name:%{public}s", uid, name);
221        return HNP_ERRNO_BASE_SPRINTF_FAILED;
222    }
223
224    if (sprintf_s(hnpVersionPath, MAX_FILE_PATH_LEN, "%s/%s_%s", hnpNamePath, name, version) < 0) {
225        HNP_LOGE("hnp uninstall sprintf version path unsuccess.");
226        return HNP_ERRNO_BASE_SPRINTF_FAILED;
227    }
228
229    if (sprintf_s(sandboxPath, MAX_FILE_PATH_LEN, HNP_SANDBOX_BASE_PATH"/%s.org", name) < 0) {
230        HNP_LOGE("sprintf unstall base path unsuccess.");
231        return HNP_ERRNO_BASE_SPRINTF_FAILED;
232    }
233
234    ret = HnpProcessRunCheck(sandboxPath);
235    if (ret != 0) {
236        return ret;
237    }
238
239    if (!isInstallVersion) {
240        ret = HnpPackageInfoHnpDelete(packageName, name, version);
241        if (ret != 0) {
242            return ret;
243        }
244    }
245
246    ret = HnpDeleteFolder(hnpVersionPath);
247    if (ret != 0) {
248        return ret;
249    }
250
251    if (HnpPathFileCount(hnpNamePath) == 0) {
252        return HnpDeleteFolder(hnpNamePath);
253    }
254
255    return 0;
256}
257
258static int HnpNativeUnInstall(HnpPackageInfo *packageInfo, int uid, const char *packageName)
259{
260    int ret = 0;
261
262    HNP_LOGI("hnp uninstall start now! name=%{public}s,version=[%{public}s,%{public}s],uid=%{public}d,"
263        "package=%{public}s", packageInfo->name, packageInfo->currentVersion, packageInfo->installVersion, uid,
264        packageName);
265
266    if (!packageInfo->hnpExist) {
267        ret = HnpUnInstallPublicHnp(packageName, packageInfo->name, packageInfo->currentVersion, uid, false);
268        if (ret != 0) {
269            return ret;
270        }
271    }
272
273    if (strcmp(packageInfo->installVersion, "none") != 0 &&
274        strcmp(packageInfo->currentVersion, packageInfo->installVersion) != 0) {
275        ret = HnpUnInstallPublicHnp(packageName, packageInfo->name, packageInfo->installVersion, uid, true);
276        if (ret != 0) {
277            return ret;
278        }
279    }
280    HNP_LOGI("hnp uninstall end! ret=%{public}d", ret);
281
282    return 0;
283}
284
285static int HnpUnInstall(int uid, const char *packageName)
286{
287    HnpPackageInfo *packageInfo = NULL;
288    int count = 0;
289    char privatePath[MAX_FILE_PATH_LEN];
290    char dstPath[MAX_FILE_PATH_LEN];
291
292    /* 拼接卸载路径 */
293    if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", uid) < 0) {
294        HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", uid);
295        return HNP_ERRNO_BASE_SPRINTF_FAILED;
296    }
297
298    /* 验证卸载路径是否存在 */
299    if (access(dstPath, F_OK) != 0) {
300        HNP_LOGE("hnp uninstall uid path[%{public}s] is not exist", dstPath);
301        return HNP_ERRNO_UNINSTALLER_HNP_PATH_NOT_EXIST;
302    }
303
304    int ret = HnpPackageInfoGet(packageName, &packageInfo, &count);
305    if (ret != 0) {
306        return ret;
307    }
308
309    /* 卸载公有native */
310    for (int i = 0; i < count; i++) {
311        ret = HnpNativeUnInstall(&packageInfo[i], uid, packageName);
312        if (ret != 0) {
313            free(packageInfo);
314            return ret;
315        }
316    }
317    free(packageInfo);
318
319    ret = HnpPackageInfoDelete(packageName);
320    if (ret != 0) {
321        return ret;
322    }
323
324    if (sprintf_s(privatePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnp/%s", uid, packageName) < 0) {
325        HNP_LOGE("hnp uninstall private path sprintf unsuccess, uid:%{public}d,package name[%{public}s]", uid,
326            packageName);
327        return HNP_ERRNO_BASE_SPRINTF_FAILED;
328    }
329
330    (void)HnpDeleteFolder(privatePath);
331
332    return 0;
333}
334
335static int HnpInstallForceCheck(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
336{
337    int ret = 0;
338
339    /* 判断安装目录是否存在,存在判断是否是强制安装,如果是则走卸载流程,否则返回错误 */
340    if (access(hnpInfo->hnpSoftwarePath, F_OK) == 0) {
341        if (hnpInfo->hapInstallInfo->isForce == false) {
342            HNP_LOGE("hnp install path[%{public}s] exist, but force is false", hnpInfo->hnpSoftwarePath);
343            return HNP_ERRNO_INSTALLER_PATH_IS_EXIST;
344        }
345        if (hnpInfo->isPublic == false) {
346            if (HnpDeleteFolder(hnpInfo->hnpSoftwarePath) != 0) {
347                return ret;
348            }
349        }
350    }
351
352    ret = HnpCreateFolder(hnpInfo->hnpVersionPath);
353    if (ret != 0) {
354        return HnpDeleteFolder(hnpInfo->hnpVersionPath);
355    }
356    return ret;
357}
358
359static int HnpInstallPathGet(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
360{
361    int ret;
362
363    /* 拼接安装路径 */
364    ret = sprintf_s(hnpInfo->hnpSoftwarePath, MAX_FILE_PATH_LEN, "%s/%s.org", hnpInfo->hnpBasePath,
365        hnpCfgInfo->name);
366    if (ret < 0) {
367        HNP_LOGE("hnp install sprintf hnp base path unsuccess.");
368        return HNP_ERRNO_BASE_SPRINTF_FAILED;
369    }
370
371    /* 拼接安装路径 */
372    ret = sprintf_s(hnpInfo->hnpVersionPath, MAX_FILE_PATH_LEN, "%s/%s_%s", hnpInfo->hnpSoftwarePath,
373        hnpCfgInfo->name, hnpCfgInfo->version);
374    if (ret < 0) {
375        HNP_LOGE("hnp install sprintf install path unsuccess.");
376        return HNP_ERRNO_BASE_SPRINTF_FAILED;
377    }
378
379    return 0;
380}
381
382static int HnpPublicDealAfterInstall(HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg)
383{
384    char *version = HnpCurrentVersionUninstallCheck(hnpCfg->name);
385    if (version == NULL) {
386        version = HnpCurrentVersionGet(hnpCfg->name);
387        if (version != NULL) {
388            HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg->name, version,
389                hnpInfo->hapInstallInfo->uid, true);
390        }
391    }
392    if (version != NULL) {
393        free(version);
394    }
395    hnpCfg->isInstall = true;
396
397    return HnpInstallInfoJsonWrite(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg);
398}
399
400static int HnpReadAndInstall(char *srcFile, HnpInstallInfo *hnpInfo, HnpSignMapInfo *hnpSignMapInfos, int *count)
401{
402    int ret;
403    HnpCfgInfo hnpCfg = {0};
404
405    HNP_LOGI("hnp install start now! src file=%{public}s, dst path=%{public}s", srcFile, hnpInfo->hnpBasePath);
406    /* 从hnp zip获取cfg信息 */
407    ret = HnpCfgGetFromZip(srcFile, &hnpCfg);
408    if (ret != 0) {
409        return ret;
410    }
411
412    ret = HnpInstallPathGet(&hnpCfg, hnpInfo);
413    if (ret != 0) {
414        // 释放软链接占用的内存
415        if (hnpCfg.links != NULL) {
416            free(hnpCfg.links);
417        }
418        return ret;
419    }
420
421    /* 存在对应版本的公有hnp包跳过安装 */
422    if (access(hnpInfo->hnpVersionPath, F_OK) == 0 && hnpInfo->isPublic) {
423        /* 刷新软链 */
424        ret = HnpGenerateSoftLink(hnpInfo->hnpVersionPath, hnpInfo->hnpBasePath, &hnpCfg);
425        if (ret != 0) {
426            return ret;
427        }
428        // 释放软链接占用的内存
429        if (hnpCfg.links != NULL) {
430            free(hnpCfg.links);
431        }
432        return HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
433    }
434
435    ret = HnpInstallForceCheck(&hnpCfg, hnpInfo);
436    if (ret != 0) {
437        // 释放软链接占用的内存
438        if (hnpCfg.links != NULL) {
439            free(hnpCfg.links);
440        }
441        return ret;
442    }
443
444    /* hnp安装 */
445    ret = HnpInstall(srcFile, hnpInfo, &hnpCfg, hnpSignMapInfos, count);
446    // 释放软链接占用的内存
447    if (hnpCfg.links != NULL) {
448        free(hnpCfg.links);
449    }
450    if (ret != 0) {
451        HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
452            hnpInfo->hapInstallInfo->uid, false);
453        return ret;
454    }
455
456    if (hnpInfo->isPublic) {
457        ret = HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
458        if (ret != 0) {
459            HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
460                hnpInfo->hapInstallInfo->uid, false);
461        }
462    }
463
464    return ret;
465}
466
467static bool HnpFileCheck(const char *file)
468{
469    const char suffix[] = ".hnp";
470    int len = strlen(file);
471    int suffixLen = strlen(suffix);
472    if ((len >= suffixLen) && (strcmp(file + len - suffixLen, suffix) == 0)) {
473        return true;
474    }
475
476    return false;
477}
478
479static int HnpPackageGetAndInstall(const char *dirPath, HnpInstallInfo *hnpInfo, char *sunDir,
480    HnpSignMapInfo *hnpSignMapInfos, int *count)
481{
482    DIR *dir;
483    struct dirent *entry;
484    char path[MAX_FILE_PATH_LEN];
485    char sunDirNew[MAX_FILE_PATH_LEN];
486
487    if ((dir = opendir(dirPath)) == NULL) {
488        HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", dirPath, errno);
489        return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
490    }
491
492    while ((entry = readdir(dir)) != NULL) {
493        if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
494            continue;
495        }
496        if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", dirPath, entry->d_name) < 0) {
497            HNP_LOGE("hnp install sprintf unsuccess, dir[%{public}s], path[%{public}s]", dirPath, entry->d_name);
498            closedir(dir);
499            return HNP_ERRNO_BASE_SPRINTF_FAILED;
500        }
501
502        if (entry->d_type == DT_DIR) {
503            if (sprintf_s(sunDirNew, MAX_FILE_PATH_LEN, "%s%s/", sunDir, entry->d_name) < 0) {
504                HNP_LOGE("hnp install sprintf sub dir unsuccess");
505                closedir(dir);
506                return HNP_ERRNO_BASE_SPRINTF_FAILED;
507            }
508            int ret = HnpPackageGetAndInstall(path, hnpInfo, sunDirNew, hnpSignMapInfos, count);
509            if (ret != 0) {
510                closedir(dir);
511                return ret;
512            }
513        } else {
514            if (HnpFileCheck(path) == false) {
515                continue;
516            }
517            if (sprintf_s(hnpInfo->hnpSignKeyPrefix, MAX_FILE_PATH_LEN, "hnp/%s/%s%s", hnpInfo->hapInstallInfo->abi,
518                sunDir, entry->d_name) < 0) {
519                HNP_LOGE("hnp install sprintf unsuccess,sub[%{public}s],path[%{public}s]", sunDir, entry->d_name);
520                closedir(dir);
521                return HNP_ERRNO_BASE_SPRINTF_FAILED;
522            }
523            int ret = HnpReadAndInstall(path, hnpInfo, hnpSignMapInfos, count);
524            HNP_LOGI("hnp install end, ret=%{public}d", ret);
525            if (ret != 0) {
526                closedir(dir);
527                return ret;
528            }
529        }
530    }
531    closedir(dir);
532    return 0;
533}
534
535static int HapReadAndInstall(const char *dstPath, HapInstallInfo *installInfo, HnpSignMapInfo *hnpSignMapInfos,
536    int *count)
537{
538    struct dirent *entry;
539    char hnpPath[MAX_FILE_PATH_LEN];
540    HnpInstallInfo hnpInfo = {0};
541    int ret;
542
543    DIR *dir = opendir(installInfo->hnpRootPath);
544    if (dir == NULL) {
545        HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", installInfo->hnpRootPath, errno);
546        return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
547    }
548
549    hnpInfo.hapInstallInfo = installInfo;
550    /* 遍历src目录 */
551    while ((entry = readdir(dir)) != NULL) {
552        if (strcmp(entry->d_name, "public") == 0) {
553            hnpInfo.isPublic = true;
554            if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnppublic", dstPath) < 0) ||
555                (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/public", installInfo->hnpRootPath) < 0)) {
556                HNP_LOGE("hnp install public base path sprintf unsuccess.");
557                closedir(dir);
558                return HNP_ERRNO_BASE_SPRINTF_FAILED;
559            }
560        } else if (strcmp(entry->d_name, "private") == 0) {
561            hnpInfo.isPublic = false;
562            if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnp/%s", dstPath,
563                installInfo->hapPackageName) < 0) || (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/private",
564                installInfo->hnpRootPath) < 0)) {
565                HNP_LOGE("hnp install private base path sprintf unsuccess.");
566                closedir(dir);
567                return HNP_ERRNO_BASE_SPRINTF_FAILED;
568            }
569        } else {
570            continue;
571        }
572
573        ret = HnpPackageGetAndInstall(hnpPath, &hnpInfo, "", hnpSignMapInfos, count);
574        if (ret != 0) {
575            closedir(dir);
576            return ret;
577        }
578    }
579
580    closedir(dir);
581    return 0;
582}
583
584static int HnpInstallHnpFileCountGet(char *hnpPath, int *count)
585{
586    DIR *dir;
587    struct dirent *entry;
588    char path[MAX_FILE_PATH_LEN];
589    int ret;
590
591    if ((dir = opendir(hnpPath)) == NULL) {
592        HNP_LOGE("hnp install count get opendir:%{public}s unsuccess, errno=%{public}d", hnpPath, errno);
593        return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
594    }
595
596    while ((entry = readdir(dir)) != NULL) {
597        if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
598            continue;
599        }
600
601        if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
602            HNP_LOGE("hnp install count get sprintf unsuccess, dir[%{public}s], path[%{public}s]", hnpPath,
603                entry->d_name);
604            closedir(dir);
605            return HNP_ERRNO_BASE_SPRINTF_FAILED;
606        }
607
608        if (entry->d_type == DT_DIR) {
609            if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
610                HNP_LOGE("hnp install sprintf sub dir unsuccess");
611                closedir(dir);
612                return HNP_ERRNO_BASE_SPRINTF_FAILED;
613            }
614            ret = HnpInstallHnpFileCountGet(path, count);
615            if (ret != 0) {
616                closedir(dir);
617                return ret;
618            }
619        } else {
620            if (HnpFileCheck(path) == false) {
621                continue;
622            }
623            ret = HnpFileCountGet(path, count);
624            if (ret != 0) {
625                closedir(dir);
626                return ret;
627            }
628        }
629    }
630
631    closedir(dir);
632    return 0;
633}
634
635static int HnpInstallHapFileCountGet(const char *root, int *count)
636{
637    struct dirent *entry;
638    char hnpPath[MAX_FILE_PATH_LEN];
639
640    DIR *dir = opendir(root);
641    if (dir == NULL) {
642        HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", root, errno);
643        return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
644    }
645
646    while ((entry = readdir(dir)) != NULL) {
647        if ((strcmp(entry->d_name, "public") != 0) && (strcmp(entry->d_name, "private") != 0)) {
648            continue;
649        }
650        if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", root, entry->d_name) < 0) {
651            HNP_LOGE("hnp install private base path sprintf unsuccess.");
652            closedir(dir);
653            return HNP_ERRNO_BASE_SPRINTF_FAILED;
654        }
655
656        int ret = HnpInstallHnpFileCountGet(hnpPath, count);
657        if (ret != 0) {
658            closedir(dir);
659            return ret;
660        }
661    }
662
663    closedir(dir);
664    return 0;
665}
666
667static int SetHnpRestorecon(char *path)
668{
669    int ret;
670    char publicPath[MAX_FILE_PATH_LEN] = {0};
671    if (sprintf_s(publicPath, MAX_FILE_PATH_LEN, "%s/hnppublic", path) < 0) {
672        HNP_LOGE("sprintf fail, get hnp restorecon path fail");
673        return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
674    }
675
676    if (access(publicPath, F_OK) != 0) {
677        ret = mkdir(publicPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
678        if ((ret != 0) && (errno != EEXIST)) {
679            HNP_LOGE("mkdir public path fail");
680            return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
681        }
682    }
683
684    if (RestoreconRecurse(publicPath)) {
685        HNP_LOGE("restorecon hnp path fail");
686        return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
687    }
688
689    return 0;
690}
691
692static int CheckInstallPath(char *dstPath, HapInstallInfo *installInfo)
693{
694    /* 拼接安装路径 */
695    if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", installInfo->uid) < 0) {
696        HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", installInfo->uid);
697        return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
698    }
699
700    /* 验证安装路径是否存在 */
701    if (access(dstPath, F_OK) != 0) {
702        HNP_LOGE("hnp install uid path[%{public}s] is not exist", dstPath);
703        return HNP_ERRNO_INSTALLER_GET_REALPATH_FAILED;
704    }
705
706    /* restorecon hnp 安装目录 */
707    return SetHnpRestorecon(dstPath);
708}
709
710static int HnpInsatllPre(HapInstallInfo *installInfo)
711{
712    char dstPath[MAX_FILE_PATH_LEN];
713    int count = 0;
714    HnpSignMapInfo *hnpSignMapInfos = NULL;
715#ifdef CODE_SIGNATURE_ENABLE
716    struct EntryMapEntryData data = {0};
717    int i;
718#endif
719    int ret;
720
721    if ((ret = CheckInstallPath(dstPath, installInfo)) != 0 ||
722        (ret = HnpInstallHapFileCountGet(installInfo->hnpRootPath, &count)) != 0) {
723        return ret;
724    }
725
726    if (count > 0) {
727        hnpSignMapInfos = (HnpSignMapInfo *)malloc(sizeof(HnpSignMapInfo) * count);
728        if (hnpSignMapInfos == NULL) {
729            return HNP_ERRNO_NOMEM;
730        }
731    }
732
733    count = 0;
734    ret = HapReadAndInstall(dstPath, installInfo, hnpSignMapInfos, &count);
735    HNP_LOGI("sign start hap path[%{public}s],abi[%{public}s],count=%{public}d", installInfo->hapPath, installInfo->abi,
736        count);
737#ifdef CODE_SIGNATURE_ENABLE
738    if ((ret == 0) && (count > 0)) {
739        data.entries = malloc(sizeof(struct EntryMapEntry) * count);
740        if (data.entries == NULL) {
741            return HNP_ERRNO_NOMEM;
742        }
743        for (i = 0; i < count; i++) {
744            data.entries[i].key = hnpSignMapInfos[i].key;
745            data.entries[i].value = hnpSignMapInfos[i].value;
746        }
747        data.count = count;
748        ret = EnforceCodeSignForApp(installInfo->hapPath, &data, FILE_ENTRY_ONLY);
749        HNP_LOGI("sign end ret=%{public}d,last key[%{public}s],value[%{public}s]", ret, data.entries[i - 1].key,
750            data.entries[i - 1].value);
751        free(data.entries);
752        if (ret != 0) {
753            HnpUnInstall(installInfo->uid, installInfo->hapPackageName);
754            ret = HNP_ERRNO_INSTALLER_CODE_SIGN_APP_FAILED;
755        }
756    }
757#endif
758    free(hnpSignMapInfos);
759    return ret;
760}
761
762static int ParseInstallArgs(int argc, char *argv[], HapInstallInfo *installInfo)
763{
764    int ret;
765    int ch;
766
767    optind = 1; // 从头开始遍历参数
768    while ((ch = getopt_long(argc, argv, "hu:p:i:s:a:f", NULL, NULL)) != -1) {
769        switch (ch) {
770            case 'h' :
771                return HNP_ERRNO_OPERATOR_ARGV_MISS;
772            case 'u': // 用户id
773                ret = HnpInstallerUidGet(optarg, &installInfo->uid);
774                if (ret != 0) {
775                    HNP_LOGE("hnp install argv uid[%{public}s] invalid", optarg);
776                    return ret;
777                }
778                break;
779            case 'p': // app名称
780                installInfo->hapPackageName = (char *)optarg;
781                break;
782            case 'i': // hnp安装目录
783                installInfo->hnpRootPath = (char *)optarg;
784                break;
785            case 's': // hap目录
786                installInfo->hapPath = (char *)optarg;
787                break;
788            case 'a': // 系统abi路径
789                installInfo->abi = (char *)optarg;
790                break;
791            case 'f': // is force
792                installInfo->isForce = true;
793                break;
794            default:
795                break;
796        }
797    }
798
799    if ((installInfo->uid == -1) || (installInfo->hnpRootPath == NULL) || (installInfo->hapPath == NULL) ||
800        (installInfo->abi == NULL) || (installInfo->hapPackageName == NULL)) {
801        HNP_LOGE("argv params is missing.");
802        return HNP_ERRNO_OPERATOR_ARGV_MISS;
803    }
804
805    return 0;
806}
807
808int HnpCmdInstall(int argc, char *argv[])
809{
810    HapInstallInfo installInfo = {0};
811
812    installInfo.uid = -1; // 预设值,判断简单
813    // 解析参数并生成安装信息
814    int ret = ParseInstallArgs(argc, argv, &installInfo);
815    if (ret != 0) {
816        return ret;
817    }
818
819    return HnpInsatllPre(&installInfo);
820}
821
822int HnpCmdUnInstall(int argc, char *argv[])
823{
824    int uid;
825    char *uidArg = NULL;
826    char *packageName = NULL;
827    int ret;
828    int ch;
829
830    optind = 1; // 从头开始遍历参数
831    while ((ch = getopt_long(argc, argv, "hu:p:", NULL, NULL)) != -1) {
832        switch (ch) {
833            case 'h' :
834                return HNP_ERRNO_OPERATOR_ARGV_MISS;
835            case 'u': // uid
836                uidArg = optarg;
837                ret = HnpInstallerUidGet(uidArg, &uid);
838                if (ret != 0) {
839                    HNP_LOGE("hnp install arg uid[%{public}s] invalid", uidArg);
840                    return ret;
841                }
842                break;
843            case 'p': // hnp package name
844                packageName = (char *)optarg;
845                break;
846            default:
847                break;
848            }
849    }
850
851    if ((uidArg == NULL) || (packageName == NULL)) {
852        HNP_LOGE("hnp uninstall params invalid uid[%{public}s], package name[%{public}s]", uidArg, packageName);
853        return HNP_ERRNO_OPERATOR_ARGV_MISS;
854    }
855
856    return HnpUnInstall(uid, packageName);
857}
858
859#ifdef __cplusplus
860}
861#endif
862