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