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