• 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,bool canRecovery,bool isPublic)50 static int HnpGenerateSoftLinkAllByJson(const char *installPath, const char *dstPath, HnpCfgInfo *hnpCfg,
51     bool canRecovery, bool isPublic)
52 {
53     char srcFile[MAX_FILE_PATH_LEN];
54     char dstFile[MAX_FILE_PATH_LEN];
55     NativeBinLink *currentLink = hnpCfg->links;
56     char *fileNameTmp;
57 
58     if (access(dstPath, F_OK) != 0) {
59         int ret = mkdir(dstPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
60         if ((ret != 0) && (errno != EEXIST)) {
61             HNP_LOGE("mkdir [%{public}s] unsuccess, ret=%{public}d, errno:%{public}d", dstPath, ret, errno);
62             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
63         }
64     }
65 
66     for (unsigned int i = 0; i < hnpCfg->linkNum; i++) {
67         if (strstr(currentLink->source, "..") || strstr(currentLink->target, "..")) {
68             HNP_LOGE("hnp json link source[%{public}s],target[%{public}s],does not allow the use of ..",
69                 currentLink->source, currentLink->target);
70             return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
71         }
72         int ret = sprintf_s(srcFile, MAX_FILE_PATH_LEN, "%s/%s", installPath, currentLink->source);
73         char *fileName;
74         if (ret < 0) {
75             HNP_LOGE("sprintf install bin src file unsuccess.");
76             return HNP_ERRNO_BASE_SPRINTF_FAILED;
77         }
78         /* 如果target为空则使用源二进制名称 */
79         if (strcmp(currentLink->target, "") == 0) {
80             fileNameTmp = currentLink->source;
81         } else {
82             fileNameTmp = currentLink->target;
83         }
84         fileName = strrchr(fileNameTmp, DIR_SPLIT_SYMBOL);
85         if (fileName == NULL) {
86             fileName = fileNameTmp;
87         } else {
88             fileName++;
89         }
90         ret = sprintf_s(dstFile, MAX_FILE_PATH_LEN, "%s/%s", dstPath, fileName);
91         HNP_ERROR_CHECK(ret > 0, return HNP_ERRNO_BASE_SPRINTF_FAILED,
92             "sprintf install bin dst file unsuccess.");
93 
94         /* 生成软链接 */
95         ret = HnpSymlink(srcFile, dstFile, hnpCfg, canRecovery, isPublic);
96         HNP_ERROR_CHECK(ret == 0, return ret, "hnpSymlink failed");
97 
98         currentLink++;
99     }
100 
101     return 0;
102 }
103 
HnpGenerateSoftLinkAll(const char * installPath,const char * dstPath,HnpCfgInfo * hnpCfg,bool canRecovery,bool isPublic)104 static int HnpGenerateSoftLinkAll(const char *installPath, const char *dstPath, HnpCfgInfo *hnpCfg,
105     bool canRecovery, bool isPublic)
106 {
107     char srcPath[MAX_FILE_PATH_LEN];
108     char srcFile[MAX_FILE_PATH_LEN];
109     char dstFile[MAX_FILE_PATH_LEN];
110     int ret;
111     DIR *dir;
112     struct dirent *entry;
113 
114     ret = sprintf_s(srcPath, MAX_FILE_PATH_LEN, "%s/bin", installPath);
115     HNP_ERROR_CHECK(ret > 0, return HNP_ERRNO_BASE_SPRINTF_FAILED,
116         "sprintf install bin path unsuccess.");
117 
118     if ((dir = opendir(srcPath)) == NULL) {
119         HNP_LOGI("soft link bin file:%{public}s not exist", srcPath);
120         return 0;
121     }
122 
123     if (access(dstPath, F_OK) != 0) {
124         ret = mkdir(dstPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
125         if ((ret != 0) && (errno != EEXIST)) {
126             closedir(dir);
127             HNP_LOGE("mkdir [%{public}s] unsuccess, ret=%{public}d, errno:%{public}d", dstPath, ret, errno);
128             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
129         }
130     }
131 
132     while (((entry = readdir(dir)) != NULL)) {
133         /* 非二进制文件跳过 */
134         if (entry->d_type != DT_REG) {
135             continue;
136         }
137         ret = sprintf_s(srcFile, MAX_FILE_PATH_LEN, "%s/%s", srcPath, entry->d_name);
138         if (ret < 0) {
139             closedir(dir);
140             HNP_LOGE("sprintf install bin src file unsuccess.");
141             return HNP_ERRNO_BASE_SPRINTF_FAILED;
142         }
143 
144         ret = sprintf_s(dstFile, MAX_FILE_PATH_LEN, "%s/%s", dstPath, entry->d_name);
145         if (ret < 0) {
146             closedir(dir);
147             HNP_LOGE("sprintf install bin dst file unsuccess.");
148             return HNP_ERRNO_BASE_SPRINTF_FAILED;
149         }
150         /* 生成软链接 */
151         ret = HnpSymlink(srcFile, dstFile, hnpCfg, canRecovery, isPublic);
152         if (ret != 0) {
153             closedir(dir);
154             return ret;
155         }
156     }
157 
158     closedir(dir);
159     return 0;
160 }
161 
HnpGenerateSoftLink(HnpInstallInfo * hnpInfo,HnpCfgInfo * hnpCfg)162 static int HnpGenerateSoftLink(HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg)
163 {
164     HNP_ERROR_CHECK(hnpInfo != NULL, return HNP_ERRNO_BASE_PARAMS_INVALID,
165         "invalid hnpInfp");
166     bool canRecovery = CanRecovery(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg);
167     int ret = 0;
168     char binPath[MAX_FILE_PATH_LEN];
169 
170     ret = sprintf_s(binPath, MAX_FILE_PATH_LEN, "%s/bin", hnpInfo->hnpBasePath);
171     HNP_ERROR_CHECK(ret > 0, return HNP_ERRNO_BASE_SPRINTF_FAILED,
172         "sprintf install bin path unsuccess.");
173 
174     if (hnpCfg->linkNum == 0) {
175         ret = HnpGenerateSoftLinkAll(hnpInfo->hnpVersionPath, binPath, hnpCfg,
176             canRecovery, hnpInfo->isPublic);
177     } else {
178         ret = HnpGenerateSoftLinkAllByJson(hnpInfo->hnpVersionPath, binPath, hnpCfg,
179             canRecovery, hnpInfo->isPublic);
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, hnpCfg);
198 }
199 
200 /**
201  * 删除 ../hnppublic/bin目录下所有失效的hnp
202  */
ClearSoftLink(int uid)203 APPSPAWN_STATIC void ClearSoftLink(int uid)
204 {
205     char path[MAX_FILE_PATH_LEN] = {0};
206     ssize_t bytes = snprintf_s(path, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN - 1,
207         HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnppublic/bin", uid);
208     HNP_ERROR_CHECK(bytes > 0, return,
209         "Build bin path failed %{public}d %{public}zd", uid, bytes);
210 
211     DIR *dir = opendir(path);
212     HNP_ERROR_CHECK(dir != NULL, return,
213         "open bin path failed %{public}s %{public}d", path, errno);
214 
215     struct dirent *entry;
216     int count = 0;
217     while ((entry = readdir(dir)) != NULL) {
218         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
219             continue;
220         }
221         count++;
222         HNP_INFO_CHECK(entry->d_type == DT_LNK, continue,
223             "not lnk file %s skip to next", entry->d_name);
224 
225         char sourcePath[MAX_FILE_PATH_LEN] = {0};
226         bytes = snprintf_s(sourcePath, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN - 1,
227             "%s/%s", path, entry->d_name);
228         HNP_ERROR_CHECK(bytes > 0, continue,
229             "build soft link path failed %{public}s", entry->d_name);
230 
231         char targetPath[MAX_FILE_PATH_LEN] = {0};
232         bytes = readlink(sourcePath, targetPath, MAX_FILE_PATH_LEN);
233         HNP_ERROR_CHECK(bytes > 0, continue, "readlink failed %{public}s", sourcePath);
234 
235         char linkPath[MAX_FILE_PATH_LEN] = {0};
236         bytes = snprintf_s(linkPath, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN - 1,
237             "%s/%s", path, targetPath);
238         HNP_ERROR_CHECK(bytes > 0, continue, "build link file source path failed %{public}s", targetPath);
239 
240         if (access(linkPath, F_OK) != 0) {
241             int ret = unlink(sourcePath);
242             HNP_LOGI("unlink file %{public}s %{public}d", sourcePath, ret);
243         }
244     }
245     HNP_LOGI("file count is %d", count);
246     closedir(dir);
247 }
248 
249 /**
250  * 卸载公共hnp.
251  *
252  * @param packageName hap名称.
253  * @param name  hnp名称
254  * @param version 版本号.
255  * @param uid 用户id.
256  * @param isInstallVersion 是否卸载安装版本.
257  *
258  * @return 0:success;other means failure.
259  */
HnpUnInstallPublicHnp(const char * packageName,const char * name,const char * version,int uid,bool isInstallVersion)260 static int HnpUnInstallPublicHnp(const char* packageName, const char *name, const char *version, int uid,
261     bool isInstallVersion)
262 {
263     int ret;
264     char hnpNamePath[MAX_FILE_PATH_LEN];
265     char hnpVersionPath[MAX_FILE_PATH_LEN];
266     char sandboxPath[MAX_FILE_PATH_LEN];
267 
268     if (sprintf_s(hnpNamePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnppublic/%s.org", uid, name) < 0) {
269         HNP_LOGE("hnp uninstall name path sprintf unsuccess,uid:%{public}d,name:%{public}s", uid, name);
270         return HNP_ERRNO_BASE_SPRINTF_FAILED;
271     }
272 
273     if (sprintf_s(hnpVersionPath, MAX_FILE_PATH_LEN, "%s/%s_%s", hnpNamePath, name, version) < 0) {
274         HNP_LOGE("hnp uninstall sprintf version path unsuccess.");
275         return HNP_ERRNO_BASE_SPRINTF_FAILED;
276     }
277 
278     if (sprintf_s(sandboxPath, MAX_FILE_PATH_LEN, HNP_SANDBOX_BASE_PATH"/%s.org", name) < 0) {
279         HNP_LOGE("sprintf unstall base path unsuccess.");
280         return HNP_ERRNO_BASE_SPRINTF_FAILED;
281     }
282 
283     ret = HnpProcessRunCheck(sandboxPath);
284     if (ret != 0) {
285         return ret;
286     }
287 
288     if (!isInstallVersion) {
289         ret = HnpPackageInfoHnpDelete(packageName, name, version);
290         if (ret != 0) {
291             return ret;
292         }
293     }
294 
295     ret = HnpDeleteFolder(hnpVersionPath);
296     if (ret != 0) {
297         return ret;
298     }
299 
300     if (HnpPathFileCount(hnpNamePath) == 0) {
301         ClearSoftLink(uid);
302         return HnpDeleteFolder(hnpNamePath);
303     }
304 
305     return 0;
306 }
307 
HnpNativeUnInstall(HnpPackageInfo * packageInfo,int uid,const char * packageName)308 static int HnpNativeUnInstall(HnpPackageInfo *packageInfo, int uid, const char *packageName)
309 {
310     int ret = 0;
311 
312     HNP_LOGI("hnp uninstall start now! name=%{public}s,version=[%{public}s,%{public}s],uid=%{public}d,"
313         "package=%{public}s", packageInfo->name, packageInfo->currentVersion, packageInfo->installVersion, uid,
314         packageName);
315 
316     if (!packageInfo->hnpExist) {
317         ret = HnpUnInstallPublicHnp(packageName, packageInfo->name, packageInfo->currentVersion, uid, false);
318         if (ret != 0) {
319             return ret;
320         }
321     }
322 
323     if (strcmp(packageInfo->installVersion, "none") != 0 &&
324         strcmp(packageInfo->currentVersion, packageInfo->installVersion) != 0) {
325         ret = HnpUnInstallPublicHnp(packageName, packageInfo->name, packageInfo->installVersion, uid, true);
326         if (ret != 0) {
327             return ret;
328         }
329     }
330     HNP_LOGI("hnp uninstall end! ret=%{public}d", ret);
331 
332     return 0;
333 }
334 
HnpUnInstall(int uid,const char * packageName)335 static int HnpUnInstall(int uid, const char *packageName)
336 {
337     HnpPackageInfo *packageInfo = NULL;
338     int count = 0;
339     char privatePath[MAX_FILE_PATH_LEN];
340     char dstPath[MAX_FILE_PATH_LEN];
341 
342     /* 拼接卸载路径 */
343     if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", uid) < 0) {
344         HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", uid);
345         return HNP_ERRNO_BASE_SPRINTF_FAILED;
346     }
347 
348     /* 验证卸载路径是否存在 */
349     if (access(dstPath, F_OK) != 0) {
350         HNP_LOGE("hnp uninstall uid path[%{public}s] is not exist", dstPath);
351         return HNP_ERRNO_UNINSTALLER_HNP_PATH_NOT_EXIST;
352     }
353 
354     int ret = HnpPackageInfoGet(packageName, &packageInfo, &count);
355     if (ret != 0) {
356         return ret;
357     }
358 
359     /* 卸载公有native */
360     for (int i = 0; i < count; i++) {
361         ret = HnpNativeUnInstall(&packageInfo[i], uid, packageName);
362         if (ret != 0) {
363             free(packageInfo);
364             return ret;
365         }
366     }
367     free(packageInfo);
368 
369     ret = HnpPackageInfoDelete(packageName);
370     if (ret != 0) {
371         return ret;
372     }
373 
374     if (sprintf_s(privatePath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d/hnp/%s", uid, packageName) < 0) {
375         HNP_LOGE("hnp uninstall private path sprintf unsuccess, uid:%{public}d,package name[%{public}s]", uid,
376             packageName);
377         return HNP_ERRNO_BASE_SPRINTF_FAILED;
378     }
379 
380     (void)HnpDeleteFolder(privatePath);
381 
382     return 0;
383 }
384 
HnpInstallForceCheck(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)385 static int HnpInstallForceCheck(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
386 {
387     int ret = 0;
388 
389     /* 判断安装目录是否存在,存在判断是否是强制安装,如果是则走卸载流程,否则返回错误 */
390     if (access(hnpInfo->hnpSoftwarePath, F_OK) == 0) {
391         if (hnpInfo->hapInstallInfo->isForce == false) {
392             HNP_LOGE("hnp install path[%{public}s] exist, but force is false", hnpInfo->hnpSoftwarePath);
393             return HNP_ERRNO_INSTALLER_PATH_IS_EXIST;
394         }
395         if (hnpInfo->isPublic == false) {
396             if (HnpDeleteFolder(hnpInfo->hnpSoftwarePath) != 0) {
397                 return ret;
398             }
399         }
400     }
401 
402     ret = HnpCreateFolder(hnpInfo->hnpVersionPath);
403     if (ret != 0) {
404         return HnpDeleteFolder(hnpInfo->hnpVersionPath);
405     }
406     return ret;
407 }
408 
HnpInstallPathGet(HnpCfgInfo * hnpCfgInfo,HnpInstallInfo * hnpInfo)409 static int HnpInstallPathGet(HnpCfgInfo *hnpCfgInfo, HnpInstallInfo *hnpInfo)
410 {
411     int ret;
412 
413     /* 拼接安装路径 */
414     ret = sprintf_s(hnpInfo->hnpSoftwarePath, MAX_FILE_PATH_LEN, "%s/%s.org", hnpInfo->hnpBasePath,
415         hnpCfgInfo->name);
416     if (ret < 0) {
417         HNP_LOGE("hnp install sprintf hnp base path unsuccess.");
418         return HNP_ERRNO_BASE_SPRINTF_FAILED;
419     }
420 
421     /* 拼接安装路径 */
422     ret = sprintf_s(hnpInfo->hnpVersionPath, MAX_FILE_PATH_LEN, "%s/%s_%s", hnpInfo->hnpSoftwarePath,
423         hnpCfgInfo->name, hnpCfgInfo->version);
424     if (ret < 0) {
425         HNP_LOGE("hnp install sprintf install path unsuccess.");
426         return HNP_ERRNO_BASE_SPRINTF_FAILED;
427     }
428     if (strstr(hnpInfo->hnpVersionPath, "..")) {
429         HNP_LOGE("hnp version path[%{public}s], does not allow the use of ..", hnpInfo->hnpVersionPath);
430         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
431     }
432 
433     return 0;
434 }
435 
HnpPublicDealAfterInstall(HnpInstallInfo * hnpInfo,HnpCfgInfo * hnpCfg)436 static int HnpPublicDealAfterInstall(HnpInstallInfo *hnpInfo, HnpCfgInfo *hnpCfg)
437 {
438     char *version = HnpCurrentVersionUninstallCheck(hnpCfg->name);
439     if (version == NULL) {
440         version = HnpCurrentVersionGet(hnpCfg->name);
441         if (version != NULL) {
442             HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg->name, version,
443                 hnpInfo->hapInstallInfo->uid, true);
444         }
445     }
446     if (version != NULL) {
447         free(version);
448         version = NULL;
449     }
450     hnpCfg->isInstall = true;
451 
452     return HnpInstallInfoJsonWrite(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg);
453 }
454 
HnpReadAndInstall(char * srcFile,HnpInstallInfo * hnpInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)455 static int HnpReadAndInstall(char *srcFile, HnpInstallInfo *hnpInfo, HnpSignMapInfo *hnpSignMapInfos, int *count)
456 {
457     int ret;
458     HnpCfgInfo hnpCfg = {0};
459 
460     HNP_LOGI("hnp install start now! src file=%{public}s, dst path=%{public}s", srcFile, hnpInfo->hnpBasePath);
461     /* 从hnp zip获取cfg信息 */
462     ret = HnpCfgGetFromZip(srcFile, &hnpCfg);
463     if (ret != 0) {
464         return ret;
465     }
466 
467     ret = HnpInstallPathGet(&hnpCfg, hnpInfo);
468     if (ret != 0) {
469         // 释放软链接占用的内存
470         if (hnpCfg.links != NULL) {
471             free(hnpCfg.links);
472         }
473         return ret;
474     }
475 
476     /* 存在对应版本的公有hnp包跳过安装 */
477     if (access(hnpInfo->hnpVersionPath, F_OK) == 0 && hnpInfo->isPublic) {
478         /* 刷新软链 */
479         ret = HnpGenerateSoftLink(hnpInfo, &hnpCfg);
480 
481         // 释放软链接占用的内存
482         HNP_ONLY_EXPER(hnpCfg.links != NULL, free(hnpCfg.links));
483         HNP_ONLY_EXPER(ret != 0, return ret);
484 
485         return HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
486     }
487 
488     ret = HnpInstallForceCheck(&hnpCfg, hnpInfo);
489     if (ret != 0) {
490         // 释放软链接占用的内存
491         if (hnpCfg.links != NULL) {
492             free(hnpCfg.links);
493         }
494         return ret;
495     }
496 
497     /* hnp安装 */
498     ret = HnpInstall(srcFile, hnpInfo, &hnpCfg, hnpSignMapInfos, count);
499     // 释放软链接占用的内存
500     if (hnpCfg.links != NULL) {
501         free(hnpCfg.links);
502     }
503     if (ret != 0) {
504         HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
505             hnpInfo->hapInstallInfo->uid, false);
506         return ret;
507     }
508 
509     if (hnpInfo->isPublic) {
510         ret = HnpPublicDealAfterInstall(hnpInfo, &hnpCfg);
511         if (ret != 0) {
512             HnpUnInstallPublicHnp(hnpInfo->hapInstallInfo->hapPackageName, hnpCfg.name, hnpCfg.version,
513                 hnpInfo->hapInstallInfo->uid, false);
514         }
515     }
516 
517     return ret;
518 }
519 
HnpFileCheck(const char * file)520 static bool HnpFileCheck(const char *file)
521 {
522     const char suffix[] = ".hnp";
523     int len = strlen(file);
524     int suffixLen = strlen(suffix);
525     if ((len >= suffixLen) && (strcmp(file + len - suffixLen, suffix) == 0)) {
526         return true;
527     }
528 
529     return false;
530 }
531 
HnpPackageGetAndInstall(const char * dirPath,HnpInstallInfo * hnpInfo,char * sunDir,HnpSignMapInfo * hnpSignMapInfos,int * count)532 static int HnpPackageGetAndInstall(const char *dirPath, HnpInstallInfo *hnpInfo, char *sunDir,
533     HnpSignMapInfo *hnpSignMapInfos, int *count)
534 {
535     DIR *dir;
536     struct dirent *entry;
537     char path[MAX_FILE_PATH_LEN];
538     char sunDirNew[MAX_FILE_PATH_LEN];
539 
540     if ((dir = opendir(dirPath)) == NULL) {
541         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", dirPath, errno);
542         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
543     }
544 
545     while ((entry = readdir(dir)) != NULL) {
546         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
547             continue;
548         }
549         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", dirPath, entry->d_name) < 0) {
550             HNP_LOGE("hnp install sprintf unsuccess, dir[%{public}s], path[%{public}s]", dirPath, entry->d_name);
551             closedir(dir);
552             return HNP_ERRNO_BASE_SPRINTF_FAILED;
553         }
554 
555         if (entry->d_type == DT_DIR) {
556             if (sprintf_s(sunDirNew, MAX_FILE_PATH_LEN, "%s%s/", sunDir, entry->d_name) < 0) {
557                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
558                 closedir(dir);
559                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
560             }
561             int ret = HnpPackageGetAndInstall(path, hnpInfo, sunDirNew, hnpSignMapInfos, count);
562             if (ret != 0) {
563                 closedir(dir);
564                 return ret;
565             }
566         } else {
567             if (HnpFileCheck(path) == false) {
568                 continue;
569             }
570             if (sprintf_s(hnpInfo->hnpSignKeyPrefix, MAX_FILE_PATH_LEN, "hnp/%s/%s%s", hnpInfo->hapInstallInfo->abi,
571                 sunDir, entry->d_name) < 0) {
572                 HNP_LOGE("hnp install sprintf unsuccess,sub[%{public}s],path[%{public}s]", sunDir, entry->d_name);
573                 closedir(dir);
574                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
575             }
576             int ret = HnpReadAndInstall(path, hnpInfo, hnpSignMapInfos, count);
577             HNP_LOGI("hnp install end, ret=%{public}d", ret);
578             if (ret != 0) {
579                 closedir(dir);
580                 return ret;
581             }
582         }
583     }
584     closedir(dir);
585     return 0;
586 }
587 
HapReadAndInstall(const char * dstPath,HapInstallInfo * installInfo,HnpSignMapInfo * hnpSignMapInfos,int * count)588 static int HapReadAndInstall(const char *dstPath, HapInstallInfo *installInfo, HnpSignMapInfo *hnpSignMapInfos,
589     int *count)
590 {
591     struct dirent *entry;
592     char hnpPath[MAX_FILE_PATH_LEN];
593     HnpInstallInfo hnpInfo = {0};
594     int ret;
595 
596     DIR *dir = opendir(installInfo->hnpRootPath);
597     if (dir == NULL) {
598         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", installInfo->hnpRootPath, errno);
599         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
600     }
601 
602     hnpInfo.hapInstallInfo = installInfo;
603     /* 遍历src目录 */
604     while ((entry = readdir(dir)) != NULL) {
605         if (strcmp(entry->d_name, "public") == 0) {
606             hnpInfo.isPublic = true;
607             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnppublic", dstPath) < 0) ||
608                 (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/public", installInfo->hnpRootPath) < 0)) {
609                 HNP_LOGE("hnp install public base path sprintf unsuccess.");
610                 closedir(dir);
611                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
612             }
613         } else if (strcmp(entry->d_name, "private") == 0) {
614             hnpInfo.isPublic = false;
615             if ((sprintf_s(hnpInfo.hnpBasePath, MAX_FILE_PATH_LEN, "%s/hnp/%s", dstPath,
616                 installInfo->hapPackageName) < 0) || (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/private",
617                 installInfo->hnpRootPath) < 0)) {
618                 HNP_LOGE("hnp install private base path sprintf unsuccess.");
619                 closedir(dir);
620                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
621             }
622         } else {
623             continue;
624         }
625 
626         ret = HnpPackageGetAndInstall(hnpPath, &hnpInfo, "", hnpSignMapInfos, count);
627         if (ret != 0) {
628             closedir(dir);
629             return ret;
630         }
631     }
632 
633     closedir(dir);
634     return 0;
635 }
636 
HnpInstallHnpFileCountGet(char * hnpPath,int * count)637 static int HnpInstallHnpFileCountGet(char *hnpPath, int *count)
638 {
639     DIR *dir;
640     struct dirent *entry;
641     char path[MAX_FILE_PATH_LEN];
642     int ret;
643 
644     if ((dir = opendir(hnpPath)) == NULL) {
645         HNP_LOGE("hnp install count get opendir:%{public}s unsuccess, errno=%{public}d", hnpPath, errno);
646         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
647     }
648 
649     while ((entry = readdir(dir)) != NULL) {
650         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
651             continue;
652         }
653 
654         if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
655             HNP_LOGE("hnp install count get sprintf unsuccess, dir[%{public}s], path[%{public}s]", hnpPath,
656                 entry->d_name);
657             closedir(dir);
658             return HNP_ERRNO_BASE_SPRINTF_FAILED;
659         }
660 
661         if (entry->d_type == DT_DIR) {
662             if (sprintf_s(path, MAX_FILE_PATH_LEN, "%s/%s", hnpPath, entry->d_name) < 0) {
663                 HNP_LOGE("hnp install sprintf sub dir unsuccess");
664                 closedir(dir);
665                 return HNP_ERRNO_BASE_SPRINTF_FAILED;
666             }
667             ret = HnpInstallHnpFileCountGet(path, count);
668             if (ret != 0) {
669                 closedir(dir);
670                 return ret;
671             }
672         } else {
673             if (HnpFileCheck(path) == false) {
674                 continue;
675             }
676             ret = HnpFileCountGet(path, count);
677             if (ret != 0) {
678                 closedir(dir);
679                 return ret;
680             }
681         }
682     }
683 
684     closedir(dir);
685     return 0;
686 }
687 
HnpInstallHapFileCountGet(const char * root,int * count)688 static int HnpInstallHapFileCountGet(const char *root, int *count)
689 {
690     struct dirent *entry;
691     char hnpPath[MAX_FILE_PATH_LEN];
692     char realPath[MAX_FILE_PATH_LEN] = {0};
693 
694     if ((realpath(root, realPath) == NULL) || (strnlen(realPath, MAX_FILE_PATH_LEN) >= MAX_FILE_PATH_LEN)) {
695         HNP_LOGE("hnp root path:%{public}s invalid", root);
696         return HNP_ERRNO_BASE_PARAMS_INVALID;
697     }
698 
699     DIR *dir = opendir(realPath);
700     if (dir == NULL) {
701         HNP_LOGE("hnp install opendir:%{public}s unsuccess, errno=%{public}d", realPath, errno);
702         return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
703     }
704 
705     while ((entry = readdir(dir)) != NULL) {
706         if ((strcmp(entry->d_name, "public") != 0) && (strcmp(entry->d_name, "private") != 0)) {
707             continue;
708         }
709         if (sprintf_s(hnpPath, MAX_FILE_PATH_LEN, "%s/%s", realPath, entry->d_name) < 0) {
710             HNP_LOGE("hnp install private base path sprintf unsuccess.");
711             closedir(dir);
712             return HNP_ERRNO_BASE_SPRINTF_FAILED;
713         }
714 
715         int ret = HnpInstallHnpFileCountGet(hnpPath, count);
716         if (ret != 0) {
717             closedir(dir);
718             return ret;
719         }
720     }
721 
722     closedir(dir);
723     return 0;
724 }
725 
SetHnpRestorecon(char * path)726 static int SetHnpRestorecon(char *path)
727 {
728     int ret;
729     char publicPath[MAX_FILE_PATH_LEN] = {0};
730     if (sprintf_s(publicPath, MAX_FILE_PATH_LEN, "%s/hnppublic", path) < 0) {
731         HNP_LOGE("sprintf fail, get hnp restorecon path fail");
732         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
733     }
734 
735     if (access(publicPath, F_OK) != 0) {
736         ret = mkdir(publicPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
737         if ((ret != 0) && (errno != EEXIST)) {
738             HNP_LOGE("mkdir public path fail");
739             return HNP_ERRNO_BASE_MKDIR_PATH_FAILED;
740         }
741     }
742 
743     if (RestoreconRecurse(publicPath)) {
744         HNP_LOGE("restorecon hnp path fail");
745         return HNP_ERRNO_INSTALLER_RESTORECON_HNP_PATH_FAIL;
746     }
747 
748     return 0;
749 }
750 
CheckInstallPath(char * dstPath,HapInstallInfo * installInfo)751 static int CheckInstallPath(char *dstPath, HapInstallInfo *installInfo)
752 {
753     /* 拼接安装路径 */
754     if (sprintf_s(dstPath, MAX_FILE_PATH_LEN, HNP_DEFAULT_INSTALL_ROOT_PATH"/%d", installInfo->uid) < 0) {
755         HNP_LOGE("hnp install sprintf unsuccess, uid:%{public}d", installInfo->uid);
756         return HNP_ERRNO_INSTALLER_GET_HNP_PATH_FAILED;
757     }
758 
759     /* 验证安装路径是否存在 */
760     if (access(dstPath, F_OK) != 0) {
761         HNP_LOGE("hnp install uid path[%{public}s] is not exist", dstPath);
762         return HNP_ERRNO_INSTALLER_GET_REALPATH_FAILED;
763     }
764 
765     /* restorecon hnp 安装目录 */
766     return SetHnpRestorecon(dstPath);
767 }
768 
HnpInsatllPre(HapInstallInfo * installInfo)769 static int HnpInsatllPre(HapInstallInfo *installInfo)
770 {
771     char dstPath[MAX_FILE_PATH_LEN];
772     int count = 0;
773     HnpSignMapInfo *hnpSignMapInfos = NULL;
774 #ifdef CODE_SIGNATURE_ENABLE
775     struct EntryMapEntryData data = {0};
776     int i;
777 #endif
778     int ret;
779 
780     if ((ret = CheckInstallPath(dstPath, installInfo)) != 0 ||
781         (ret = HnpInstallHapFileCountGet(installInfo->hnpRootPath, &count)) != 0) {
782         return ret;
783     }
784 
785     if (count > 0) {
786         hnpSignMapInfos = (HnpSignMapInfo *)malloc(sizeof(HnpSignMapInfo) * count);
787         if (hnpSignMapInfos == NULL) {
788             return HNP_ERRNO_NOMEM;
789         }
790     }
791 
792     count = 0;
793     ret = HapReadAndInstall(dstPath, installInfo, hnpSignMapInfos, &count);
794     HNP_LOGI("sign start hap path[%{public}s],abi[%{public}s],count=%{public}d", installInfo->hapPath, installInfo->abi,
795         count);
796 #ifdef CODE_SIGNATURE_ENABLE
797     if ((ret == 0) && (count > 0)) {
798         data.entries = malloc(sizeof(struct EntryMapEntry) * count);
799         if (data.entries == NULL) {
800             free(hnpSignMapInfos);
801             return HNP_ERRNO_NOMEM;
802         }
803         for (i = 0; i < count; i++) {
804             data.entries[i].key = hnpSignMapInfos[i].key;
805             data.entries[i].value = hnpSignMapInfos[i].value;
806         }
807         data.count = count;
808         ret = EnforceCodeSignForApp(installInfo->hapPath, &data, FILE_ENTRY_ONLY);
809         HNP_LOGI("sign end ret=%{public}d,last key[%{public}s],value[%{public}s]", ret, data.entries[i - 1].key,
810             data.entries[i - 1].value);
811         free(data.entries);
812         if (ret != 0) {
813             HnpUnInstall(installInfo->uid, installInfo->hapPackageName);
814             ret = HNP_ERRNO_INSTALLER_CODE_SIGN_APP_FAILED;
815         }
816     }
817 #endif
818     free(hnpSignMapInfos);
819     return ret;
820 }
821 
ParseInstallArgs(int argc,char * argv[],HapInstallInfo * installInfo)822 static int ParseInstallArgs(int argc, char *argv[], HapInstallInfo *installInfo)
823 {
824     int ret;
825     int ch;
826 
827     optind = 1; // 从头开始遍历参数
828     while ((ch = getopt_long(argc, argv, "hu:p:i:s:a:f", NULL, NULL)) != -1) {
829         switch (ch) {
830             case 'h' :
831                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
832             case 'u': // 用户id
833                 ret = HnpInstallerUidGet(optarg, &installInfo->uid);
834                 if (ret != 0) {
835                     HNP_LOGE("hnp install argv uid[%{public}s] invalid", optarg);
836                     return ret;
837                 }
838                 break;
839             case 'p': // app名称
840                 installInfo->hapPackageName = (char *)optarg;
841                 break;
842             case 'i': // hnp安装目录
843                 installInfo->hnpRootPath = (char *)optarg;
844                 break;
845             case 's': // hap目录
846                 installInfo->hapPath = (char *)optarg;
847                 break;
848             case 'a': // 系统abi路径
849                 installInfo->abi = (char *)optarg;
850                 break;
851             case 'f': // is force
852                 installInfo->isForce = true;
853                 break;
854             default:
855                 break;
856         }
857     }
858 
859     if ((installInfo->uid == -1) || (installInfo->hnpRootPath == NULL) || (installInfo->hapPath == NULL) ||
860         (installInfo->abi == NULL) || (installInfo->hapPackageName == NULL)) {
861         HNP_LOGE("argv params is missing.");
862         return HNP_ERRNO_OPERATOR_ARGV_MISS;
863     }
864 
865     return 0;
866 }
867 
HnpCmdInstall(int argc,char * argv[])868 int HnpCmdInstall(int argc, char *argv[])
869 {
870     HapInstallInfo installInfo = {0};
871 
872     installInfo.uid = -1; // 预设值,判断简单
873     // 解析参数并生成安装信息
874     int ret = ParseInstallArgs(argc, argv, &installInfo);
875     if (ret != 0) {
876         return ret;
877     }
878 
879     return HnpInsatllPre(&installInfo);
880 }
881 
HnpCmdUnInstall(int argc,char * argv[])882 int HnpCmdUnInstall(int argc, char *argv[])
883 {
884     int uid;
885     char *uidArg = NULL;
886     char *packageName = NULL;
887     int ret;
888     int ch;
889 
890     optind = 1; // 从头开始遍历参数
891     while ((ch = getopt_long(argc, argv, "hu:p:", NULL, NULL)) != -1) {
892         switch (ch) {
893             case 'h' :
894                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
895             case 'u': // uid
896                 uidArg = optarg;
897                 ret = HnpInstallerUidGet(uidArg, &uid);
898                 if (ret != 0) {
899                     HNP_LOGE("hnp install arg uid[%{public}s] invalid", uidArg);
900                     return ret;
901                 }
902                 break;
903             case 'p': // hnp package name
904                 packageName = (char *)optarg;
905                 break;
906             default:
907                 break;
908             }
909     }
910 
911     if ((uidArg == NULL) || (packageName == NULL)) {
912         HNP_LOGE("hnp uninstall params invalid uid[%{public}s], package name[%{public}s]", uidArg, packageName);
913         return HNP_ERRNO_OPERATOR_ARGV_MISS;
914     }
915 
916     return HnpUnInstall(uid, packageName);
917 }
918 
919 #ifdef __cplusplus
920 }
921 #endif