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