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 <unistd.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <sys/wait.h>
20
21 #include "hilog/log.h"
22 #include "appspawn_utils.h"
23 #include "securec.h"
24 #include "parameter.h"
25
26 #include "hnp_api.h"
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #define HNPAPI_LOG(fmt, ...) \
33 HILOG_INFO(LOG_CORE, "[%{public}s:%{public}d]" fmt, (__FILE_NAME__), (__LINE__), ##__VA_ARGS__)
34 #define MAX_ARGV_NUM 256
35 #define MAX_ENV_NUM (128 + 2)
36 #define IS_OPTION_SET(x, option) ((x) & (1 << (option)))
37 #define BUFFER_SIZE 1024
38 #define CMD_API_TEXT_LEN 50
39 #define PARAM_BUFFER_SIZE 10
40
41 /* 数字索引 */
42 enum {
43 HNP_INDEX_0 = 0,
44 HNP_INDEX_1,
45 HNP_INDEX_2,
46 HNP_INDEX_3,
47 HNP_INDEX_4,
48 HNP_INDEX_5,
49 HNP_INDEX_6,
50 HNP_INDEX_7
51 };
52
HnpCmdApiReturnGet(int readFd,int * ret)53 static int HnpCmdApiReturnGet(int readFd, int *ret)
54 {
55 char buffer[BUFFER_SIZE] = {0};
56 ssize_t bytesRead;
57 int bufferEnd = 0; // 跟踪缓冲区中有效数据的末尾
58 const char *prefix = "native manager process exit. ret=";
59
60 // 循环读取子进程的输出,直到结束
61 while ((bytesRead = read(readFd, buffer + bufferEnd, BUFFER_SIZE - bufferEnd - 1)) > 0) {
62 // 更新有效数据的末尾
63 bufferEnd += bytesRead;
64
65 // 如果缓冲区中的数据超过或等于50个字节,移动数据以保留最后50个字节
66 if (bufferEnd >= CMD_API_TEXT_LEN) {
67 if (memmove_s(buffer, BUFFER_SIZE, buffer + bufferEnd - CMD_API_TEXT_LEN, CMD_API_TEXT_LEN) != EOK) {
68 HNPAPI_LOG("\r\n [HNP API] mem move unsuccess!\r\n");
69 return HNP_API_ERRNO_MEMMOVE_FAILED;
70 }
71 bufferEnd = CMD_API_TEXT_LEN;
72 }
73
74 buffer[bufferEnd] = '\0';
75 }
76
77 if (bytesRead == -1) {
78 HNPAPI_LOG("\r\n [HNP API] read stream unsuccess!\r\n");
79 return HNP_API_ERRNO_PIPE_READ_FAILED;
80 }
81
82 char *retStr = strstr(buffer, prefix);
83
84 if (retStr != NULL) {
85 // 获取后续的数字字符串
86 retStr += strlen(prefix);
87 *ret = atoi(retStr);
88
89 return 0;
90 }
91
92 HNPAPI_LOG("\r\n [HNP API] get return unsuccess!, buffer is:%{public}s\r\n", buffer);
93 return HNP_API_ERRNO_RETURN_VALUE_GET_FAILED;
94 }
95
StartHnpProcess(char * const argv[],char * const apcEnv[])96 static int StartHnpProcess(char *const argv[], char *const apcEnv[])
97 {
98 int fd[2];
99 pid_t pid;
100 int exitVal = -1;
101 int ret;
102 int status;
103
104 if (pipe(fd) < 0) {
105 HNPAPI_LOG("\r\n [HNP API] pipe fd unsuccess!\r\n");
106 return HNP_API_ERRNO_PIPE_CREATED_FAILED;
107 }
108
109 pid = vfork();
110 if (pid < 0) {
111 HNPAPI_LOG("\r\n [HNP API] fork unsuccess!\r\n");
112 return HNP_API_ERRNO_FORK_FAILED;
113 } else if (pid == 0) {
114 close(fd[0]);
115 // 将子进程的stdout重定向到管道的写端
116 dup2(fd[1], STDOUT_FILENO);
117 close(fd[1]);
118
119 ret = execve("/system/bin/hnp", argv, apcEnv);
120 if (ret < 0) {
121 HNPAPI_LOG("\r\n [HNP API] execve unsuccess!\r\n");
122 _exit(-1);
123 }
124 _exit(0);
125 }
126
127 HNPAPI_LOG("\r\n [HNP API] this is fork father! chid=%{public}d\r\n", pid);
128 close(fd[1]);
129 if (waitpid(pid, &status, 0) == -1) {
130 close(fd[0]);
131 HNPAPI_LOG("\r\n [HNP API] wait pid unsuccess!\r\n");
132 return HNP_API_WAIT_PID_FAILED;
133 }
134 ret = HnpCmdApiReturnGet(fd[0], &exitVal);
135 close(fd[0]);
136 if (ret != 0) {
137 HNPAPI_LOG("\r\n [HNP API] get api return value unsuccess!\r\n");
138 return ret;
139 }
140 HNPAPI_LOG("\r\n [HNP API] Child process exited with exitval=%{public}d\r\n", exitVal);
141
142 return exitVal;
143 }
144
IsHnpInstallEnable()145 static bool IsHnpInstallEnable()
146 {
147 char buffer[PARAM_BUFFER_SIZE] = {0};
148 int ret = GetParameter("const.startup.hnp.install.enable", "false", buffer, PARAM_BUFFER_SIZE);
149 if (ret <= 0) {
150 HNPAPI_LOG("\r\n [HNP API] get hnp install enable param unsuccess! ret =%{public}d\r\n", ret);
151 return false;
152 }
153
154 if (strcmp(buffer, "true") == 0) {
155 return true;
156 }
157
158 return false;
159 }
160
NativeInstallHnp(const char * userId,const char * hnpRootPath,const HapInfo * hapInfo,int installOptions)161 int NativeInstallHnp(const char *userId, const char *hnpRootPath, const HapInfo *hapInfo, int installOptions)
162 {
163 char *argv[MAX_ARGV_NUM] = {0};
164 char *apcEnv[MAX_ENV_NUM] = {0};
165 int index = 0;
166
167 if ((userId == NULL) || (hnpRootPath == NULL) || (hapInfo == NULL)) {
168 return HNP_API_ERRNO_PARAM_INVALID;
169 }
170
171 if (!IsHnpInstallEnable()) {
172 return HNP_API_ERRNO_HNP_INSTALL_DISABLED;
173 }
174
175 HNPAPI_LOG("\r\n [HNP API] native package install! userId=%{public}s, hap path=%{public}s, sys abi=%{public}s, "
176 "hnp root path=%{public}s, package name=%{public}s install options=%{public}d\r\n", userId, hapInfo->hapPath,
177 hapInfo->abi, hnpRootPath, hapInfo->packageName, installOptions);
178
179 argv[index++] = "hnp";
180 argv[index++] = "install";
181 argv[index++] = "-u";
182 argv[index++] = (char *)userId;
183 argv[index++] = "-i";
184 argv[index++] = (char *)hnpRootPath;
185 argv[index++] = "-p";
186 argv[index++] = (char *)hapInfo->packageName;
187 argv[index++] = "-s";
188 argv[index++] = (char *)hapInfo->hapPath;
189 argv[index++] = "-a";
190 argv[index++] = (char *)hapInfo->abi;
191
192 if (installOptions >= 0 && IS_OPTION_SET((unsigned int)installOptions, OPTION_INDEX_FORCE)) {
193 argv[index++] = "-f";
194 }
195
196 return StartHnpProcess(argv, apcEnv);
197 }
198
NativeUnInstallHnp(const char * userId,const char * packageName)199 int NativeUnInstallHnp(const char *userId, const char *packageName)
200 {
201 char *argv[MAX_ARGV_NUM] = {0};
202 char *apcEnv[MAX_ENV_NUM] = {0};
203 int index = 0;
204
205 if ((userId == NULL) || (packageName == NULL)) {
206 return HNP_API_ERRNO_PARAM_INVALID;
207 }
208
209 HNPAPI_LOG("\r\n [HNP API] native package uninstall! userId=%{public}s, package name=%{public}s\r\n", userId,
210 packageName);
211
212 argv[index++] = "hnp";
213 argv[index++] = "uninstall";
214 argv[index++] = "-u";
215 argv[index++] = (char *)userId;
216 argv[index++] = "-p";
217 argv[index++] = (char *)packageName;
218
219 return StartHnpProcess(argv, apcEnv);
220 }
221
222 #ifdef __cplusplus
223 }
224 #endif