• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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  */
HnpUnInstallPublicHnp(const char * packageName,const char * name,const char * version,int uid,bool isInstallVersion)211 static 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 
HnpNativeUnInstall(HnpPackageInfo * packageInfo,int uid,const char * packageName)258 static 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 
HnpUnInstall(int uid,const char * packageName)285 static 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 
HnpInstallForceCheck(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)335 static 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 
HnpInstallPathGet(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)359 static 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     if (strstr(hnpInfo->hnpVersionPath, "..")) {
379         HNP_LOGE("hnp version path[%{public}s], does not allow the use of ..", hnpInfo->hnpVersionPath);
380         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
381     }
382 
383     return 0;
384 }
385 
HnpPublicDealAfterInstall(HnpInstallInfo * hnpInfo,HnpCfgInfo * hnpCfg)386 static int HnpPublicDealAfterInstall(HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg)
387 {
388     char *version = HnpCurrentVersionUninstallCheck(hnpCfg->name);
389     if (version == NULL) {
390         version = HnpCurrentVersionGet(hnpCfg->name);
391         if (version != NULL) {
392             HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg->name, version,
393                 hnpInfo->hapInstallInfo->uid, true);
394         }
395     }
396     if (version != NULL) {
397         free(version);
398         version = NULL;
399     }
400     hnpCfg->isInstall = true;
401 
402     return HnpInstallInfoJsonWrite(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg);
403 }
404 
HnpReadAndInstall(char * srcFile,HnpInstallInfo * hnpInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)405 static int HnpReadAndInstall(char *srcFile, HnpInstallInfo *hnpInfo, HnpSignMapInfo *hnpSignMapInfos, int *count)
406 {
407     int ret;
408     HnpCfgInfo hnpCfg = {0};
409 
410     HNP_LOGI("hnp install start now! src file=%{public}s, dst path=%{public}s", srcFile, hnpInfo->hnpBasePath);
411     /* 从hnp zip获取cfg信息 */
412     ret = HnpCfgGetFromZip(srcFile, &hnpCfg);
413     if (ret != 0) {
414         return ret;
415     }
416 
417     ret = HnpInstallPathGet(&hnpCfg, hnpInfo);
418     if (ret != 0) {
419         // 释放软链接占用的内存
420         if (hnpCfg.links != NULL) {
421             free(hnpCfg.links);
422         }
423         return ret;
424     }
425 
426     /* 存在对应版本的公有hnp包跳过安装 */
427     if (access(hnpInfo->hnpVersionPath, F_OK) == 0 && hnpInfo->isPublic) {
428         /* 刷新软链 */
429         ret = HnpGenerateSoftLink(hnpInfo->hnpVersionPath, hnpInfo->hnpBasePath, &hnpCfg);
430         if (ret != 0) {
431             return ret;
432         }
433         // 释放软链接占用的内存
434         if (hnpCfg.links != NULL) {
435             free(hnpCfg.links);
436         }
437         return HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
438     }
439 
440     ret = HnpInstallForceCheck(&hnpCfg, hnpInfo);
441     if (ret != 0) {
442         // 释放软链接占用的内存
443         if (hnpCfg.links != NULL) {
444             free(hnpCfg.links);
445         }
446         return ret;
447     }
448 
449     /* hnp安装 */
450     ret = HnpInstall(srcFile, hnpInfo, &hnpCfg, hnpSignMapInfos, count);
451     // 释放软链接占用的内存
452     if (hnpCfg.links != NULL) {
453         free(hnpCfg.links);
454     }
455     if (ret != 0) {
456         HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
457             hnpInfo->hapInstallInfo->uid, false);
458         return ret;
459     }
460 
461     if (hnpInfo->isPublic) {
462         ret = HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
463         if (ret != 0) {
464             HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
465                 hnpInfo->hapInstallInfo->uid, false);
466         }
467     }
468 
469     return ret;
470 }
471 
HnpFileCheck(const char * file)472 static bool HnpFileCheck(const char *file)
473 {
474     const char suffix[] = ".hnp";
475     int len = strlen(file);
476     int suffixLen = strlen(suffix);
477     if ((len >= suffixLen) && (strcmp(file + len - suffixLen, suffix) == 0)) {
478         return true;
479     }
480 
481     return false;
482 }
483 
HnpPackageGetAndInstall(const char * dirPath,HnpInstallInfo * hnpInfo,char * sunDir,HnpSignMapInfo * hnpSignMapInfos,int * count)484 static int HnpPackageGetAndInstall(const char *dirPath, HnpInstallInfo *hnpInfo, char *sunDir,
485     HnpSignMapInfo *hnpSignMapInfos, int *count)
486 {
487     DIR *dir;
488     struct dirent *entry;
489     char path[MAX_FILE_PATH_LEN];
490     char sunDirNew[MAX_FILE_PATH_LEN];
491 
492     if ((dir = opendir(dirPath)) == NULL) {
493         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", dirPath, errno);
494         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
495     }
496 
497     while ((entry = readdir(dir)) != NULL) {
498         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
499             continue;
500         }
501         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", dirPath, entry->d_name) < 0) {
502             HNP_LOGE("hnp install sprintf unsuccess, dir[%{public}s], path[%{public}s]", dirPath, entry->d_name);
503             closedir(dir);
504             return HNP_ERRNO_BASE_SPRINTF_FAILED;
505         }
506 
507         if (entry->d_type == DT_DIR) {
508             if (sprintf_s(sunDirNew, MAX_FILE_PATH_LEN, "%s%s/", sunDir, entry->d_name) < 0) {
509                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
510                 closedir(dir);
511                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
512             }
513             int ret = HnpPackageGetAndInstall(path, hnpInfo, sunDirNew, hnpSignMapInfos, count);
514             if (ret != 0) {
515                 closedir(dir);
516                 return ret;
517             }
518         } else {
519             if (HnpFileCheck(path) == false) {
520                 continue;
521             }
522             if (sprintf_s(hnpInfo->hnpSignKeyPrefix, MAX_FILE_PATH_LEN, "hnp/%s/%s%s", hnpInfo->hapInstallInfo->abi,
523                 sunDir, entry->d_name) < 0) {
524                 HNP_LOGE("hnp install sprintf unsuccess,sub[%{public}s],path[%{public}s]", sunDir, entry->d_name);
525                 closedir(dir);
526                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
527             }
528             int ret = HnpReadAndInstall(path, hnpInfo, hnpSignMapInfos, count);
529             HNP_LOGI("hnp install end, ret=%{public}d", ret);
530             if (ret != 0) {
531                 closedir(dir);
532                 return ret;
533             }
534         }
535     }
536     closedir(dir);
537     return 0;
538 }
539 
HapReadAndInstall(const char * dstPath,HapInstallInfo * installInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)540 static int HapReadAndInstall(const char *dstPath, HapInstallInfo *installInfo, HnpSignMapInfo *hnpSignMapInfos,
541     int *count)
542 {
543     struct dirent *entry;
544     char hnpPath[MAX_FILE_PATH_LEN];
545     HnpInstallInfo hnpInfo = {0};
546     int ret;
547 
548     DIR *dir = opendir(installInfo->hnpRootPath);
549     if (dir == NULL) {
550         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", installInfo->hnpRootPath, errno);
551         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
552     }
553 
554     hnpInfo.hapInstallInfo = installInfo;
555     /* 遍历src目录 */
556     while ((entry = readdir(dir)) != NULL) {
557         if (strcmp(entry->d_name, "public") == 0) {
558             hnpInfo.isPublic = true;
559             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnppublic", dstPath) < 0) ||
560                 (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/public", installInfo->hnpRootPath) < 0)) {
561                 HNP_LOGE("hnp install public base path sprintf unsuccess.");
562                 closedir(dir);
563                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
564             }
565         } else if (strcmp(entry->d_name, "private") == 0) {
566             hnpInfo.isPublic = false;
567             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnp/%s", dstPath,
568                 installInfo->hapPackageName) < 0) || (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/private",
569                 installInfo->hnpRootPath) < 0)) {
570                 HNP_LOGE("hnp install private base path sprintf unsuccess.");
571                 closedir(dir);
572                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
573             }
574         } else {
575             continue;
576         }
577 
578         ret = HnpPackageGetAndInstall(hnpPath, &hnpInfo, "", hnpSignMapInfos, count);
579         if (ret != 0) {
580             closedir(dir);
581             return ret;
582         }
583     }
584 
585     closedir(dir);
586     return 0;
587 }
588 
HnpInstallHnpFileCountGet(char * hnpPath,int * count)589 static int HnpInstallHnpFileCountGet(char *hnpPath, int *count)
590 {
591     DIR *dir;
592     struct dirent *entry;
593     char path[MAX_FILE_PATH_LEN];
594     int ret;
595 
596     if ((dir = opendir(hnpPath)) == NULL) {
597         HNP_LOGE("hnp install count get opendir:%{public}s unsuccess, errno=%{public}d", hnpPath, errno);
598         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
599     }
600 
601     while ((entry = readdir(dir)) != NULL) {
602         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
603             continue;
604         }
605 
606         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
607             HNP_LOGE("hnp install count get sprintf unsuccess, dir[%{public}s], path[%{public}s]", hnpPath,
608                 entry->d_name);
609             closedir(dir);
610             return HNP_ERRNO_BASE_SPRINTF_FAILED;
611         }
612 
613         if (entry->d_type == DT_DIR) {
614             if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
615                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
616                 closedir(dir);
617                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
618             }
619             ret = HnpInstallHnpFileCountGet(path, count);
620             if (ret != 0) {
621                 closedir(dir);
622                 return ret;
623             }
624         } else {
625             if (HnpFileCheck(path) == false) {
626                 continue;
627             }
628             ret = HnpFileCountGet(path, count);
629             if (ret != 0) {
630                 closedir(dir);
631                 return ret;
632             }
633         }
634     }
635 
636     closedir(dir);
637     return 0;
638 }
639 
HnpInstallHapFileCountGet(const char * root,int * count)640 static int HnpInstallHapFileCountGet(const char *root, int *count)
641 {
642     struct dirent *entry;
643     char hnpPath[MAX_FILE_PATH_LEN];
644     char realPath[MAX_FILE_PATH_LEN] = {0};
645 
646     if ((realpath(root, realPath) == NULL) || (strnlen(realPath, MAX_FILE_PATH_LEN) >= MAX_FILE_PATH_LEN)) {
647         HNP_LOGE("hnp root path:%{public}s invalid", root);
648         return HNP_ERRNO_BASE_PARAMS_INVALID;
649     }
650 
651     DIR *dir = opendir(realPath);
652     if (dir == NULL) {
653         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", realPath, errno);
654         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
655     }
656 
657     while ((entry = readdir(dir)) != NULL) {
658         if ((strcmp(entry->d_name, "public") != 0) && (strcmp(entry->d_name, "private") != 0)) {
659             continue;
660         }
661         if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", realPath, entry->d_name) < 0) {
662             HNP_LOGE("hnp install private base path sprintf unsuccess.");
663             closedir(dir);
664             return HNP_ERRNO_BASE_SPRINTF_FAILED;
665         }
666 
667         int ret = HnpInstallHnpFileCountGet(hnpPath, count);
668         if (ret != 0) {
669             closedir(dir);
670             return ret;
671         }
672     }
673 
674     closedir(dir);
675     return 0;
676 }
677 
SetHnpRestorecon(char * path)678 static int SetHnpRestorecon(char *path)
679 {
680     int ret;
681     char publicPath[MAX_FILE_PATH_LEN] = {0};
682     if (sprintf_s(publicPath, MAX_FILE_PATH_LEN, "%s/hnppublic", path) < 0) {
683         HNP_LOGE("sprintf fail, get hnp restorecon path fail");
684         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
685     }
686 
687     if (access(publicPath, F_OK) != 0) {
688         ret = mkdir(publicPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
689         if ((ret != 0) && (errno != EEXIST)) {
690             HNP_LOGE("mkdir public path fail");
691             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
692         }
693     }
694 
695     if (RestoreconRecurse(publicPath)) {
696         HNP_LOGE("restorecon hnp path fail");
697         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
698     }
699 
700     return 0;
701 }
702 
CheckInstallPath(char * dstPath,HapInstallInfo * installInfo)703 static int CheckInstallPath(char *dstPath, HapInstallInfo *installInfo)
704 {
705     /* 拼接安装路径 */
706     if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", installInfo->uid) < 0) {
707         HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", installInfo->uid);
708         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
709     }
710 
711     /* 验证安装路径是否存在 */
712     if (access(dstPath, F_OK) != 0) {
713         HNP_LOGE("hnp install uid path[%{public}s] is not exist", dstPath);
714         return HNP_ERRNO_INSTALLER_GET_REALPATH_FAILED;
715     }
716 
717     /* restorecon hnp 安装目录 */
718     return SetHnpRestorecon(dstPath);
719 }
720 
HnpInsatllPre(HapInstallInfo * installInfo)721 static int HnpInsatllPre(HapInstallInfo *installInfo)
722 {
723     char dstPath[MAX_FILE_PATH_LEN];
724     int count = 0;
725     HnpSignMapInfo *hnpSignMapInfos = NULL;
726 #ifdef CODE_SIGNATURE_ENABLE
727     struct EntryMapEntryData data = {0};
728     int i;
729 #endif
730     int ret;
731 
732     if ((ret = CheckInstallPath(dstPath, installInfo)) != 0 ||
733         (ret = HnpInstallHapFileCountGet(installInfo->hnpRootPath, &count)) != 0) {
734         return ret;
735     }
736 
737     if (count > 0) {
738         hnpSignMapInfos = (HnpSignMapInfo *)malloc(sizeof(HnpSignMapInfo) * count);
739         if (hnpSignMapInfos == NULL) {
740             return HNP_ERRNO_NOMEM;
741         }
742     }
743 
744     count = 0;
745     ret = HapReadAndInstall(dstPath, installInfo, hnpSignMapInfos, &count);
746     HNP_LOGI("sign start hap path[%{public}s],abi[%{public}s],count=%{public}d", installInfo->hapPath, installInfo->abi,
747         count);
748 #ifdef CODE_SIGNATURE_ENABLE
749     if ((ret == 0) && (count > 0)) {
750         data.entries = malloc(sizeof(struct EntryMapEntry) * count);
751         if (data.entries == NULL) {
752             free(hnpSignMapInfos);
753             return HNP_ERRNO_NOMEM;
754         }
755         for (i = 0; i < count; i++) {
756             data.entries[i].key = hnpSignMapInfos[i].key;
757             data.entries[i].value = hnpSignMapInfos[i].value;
758         }
759         data.count = count;
760         ret = EnforceCodeSignForApp(installInfo->hapPath, &data, FILE_ENTRY_ONLY);
761         HNP_LOGI("sign end ret=%{public}d,last key[%{public}s],value[%{public}s]", ret, data.entries[i - 1].key,
762             data.entries[i - 1].value);
763         free(data.entries);
764         if (ret != 0) {
765             HnpUnInstall(installInfo->uid, installInfo->hapPackageName);
766             ret = HNP_ERRNO_INSTALLER_CODE_SIGN_APP_FAILED;
767         }
768     }
769 #endif
770     free(hnpSignMapInfos);
771     return ret;
772 }
773 
ParseInstallArgs(int argc,char * argv[],HapInstallInfo * installInfo)774 static int ParseInstallArgs(int argc, char *argv[], HapInstallInfo *installInfo)
775 {
776     int ret;
777     int ch;
778 
779     optind = 1; // 从头开始遍历参数
780     while ((ch = getopt_long(argc, argv, "hu:p:i:s:a:f", NULL, NULL)) != -1) {
781         switch (ch) {
782             case 'h' :
783                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
784             case 'u': // 用户id
785                 ret = HnpInstallerUidGet(optarg, &installInfo->uid);
786                 if (ret != 0) {
787                     HNP_LOGE("hnp install argv uid[%{public}s] invalid", optarg);
788                     return ret;
789                 }
790                 break;
791             case 'p': // app名称
792                 installInfo->hapPackageName = (char *)optarg;
793                 break;
794             case 'i': // hnp安装目录
795                 installInfo->hnpRootPath = (char *)optarg;
796                 break;
797             case 's': // hap目录
798                 installInfo->hapPath = (char *)optarg;
799                 break;
800             case 'a': // 系统abi路径
801                 installInfo->abi = (char *)optarg;
802                 break;
803             case 'f': // is force
804                 installInfo->isForce = true;
805                 break;
806             default:
807                 break;
808         }
809     }
810 
811     if ((installInfo->uid == -1) || (installInfo->hnpRootPath == NULL) || (installInfo->hapPath == NULL) ||
812         (installInfo->abi == NULL) || (installInfo->hapPackageName == NULL)) {
813         HNP_LOGE("argv params is missing.");
814         return HNP_ERRNO_OPERATOR_ARGV_MISS;
815     }
816 
817     return 0;
818 }
819 
HnpCmdInstall(int argc,char * argv[])820 int HnpCmdInstall(int argc, char *argv[])
821 {
822     HapInstallInfo installInfo = {0};
823 
824     installInfo.uid = -1; // 预设值,判断简单
825     // 解析参数并生成安装信息
826     int ret = ParseInstallArgs(argc, argv, &installInfo);
827     if (ret != 0) {
828         return ret;
829     }
830 
831     return HnpInsatllPre(&installInfo);
832 }
833 
HnpCmdUnInstall(int argc,char * argv[])834 int HnpCmdUnInstall(int argc, char *argv[])
835 {
836     int uid;
837     char *uidArg = NULL;
838     char *packageName = NULL;
839     int ret;
840     int ch;
841 
842     optind = 1; // 从头开始遍历参数
843     while ((ch = getopt_long(argc, argv, "hu:p:", NULL, NULL)) != -1) {
844         switch (ch) {
845             case 'h' :
846                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
847             case 'u': // uid
848                 uidArg = optarg;
849                 ret = HnpInstallerUidGet(uidArg, &uid);
850                 if (ret != 0) {
851                     HNP_LOGE("hnp install arg uid[%{public}s] invalid", uidArg);
852                     return ret;
853                 }
854                 break;
855             case 'p': // hnp package name
856                 packageName = (char *)optarg;
857                 break;
858             default:
859                 break;
860             }
861     }
862 
863     if ((uidArg == NULL) || (packageName == NULL)) {
864         HNP_LOGE("hnp uninstall params invalid uid[%{public}s], package name[%{public}s]", uidArg, packageName);
865         return HNP_ERRNO_OPERATOR_ARGV_MISS;
866     }
867 
868     return HnpUnInstall(uid, packageName);
869 }
870 
871 #ifdef __cplusplus
872 }
873 #endif