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 (!IsDeveloperModeOpen()) {
168 HNPAPI_LOG("\r\n [HNP API] native package install not in developer mode");
169 return HNP_API_NOT_IN_DEVELOPER_MODE;
170 }
171
172 if ((userId == NULL) || (hnpRootPath == NULL) || (hapInfo == NULL)) {
173 return HNP_API_ERRNO_PARAM_INVALID;
174 }
175
176 if (!IsHnpInstallEnable()) {
177 return HNP_API_ERRNO_HNP_INSTALL_DISABLED;
178 }
179
180 HNPAPI_LOG("\r\n [HNP API] native package install! userId=%{public}s, hap path=%{public}s, sys abi=%{public}s, "
181 "hnp root path=%{public}s, package name=%{public}s install options=%{public}d\r\n", userId, hapInfo->hapPath,
182 hapInfo->abi, hnpRootPath, hapInfo->packageName, installOptions);
183
184 argv[index++] = "hnp";
185 argv[index++] = "install";
186 argv[index++] = "-u";
187 argv[index++] = (char *)userId;
188 argv[index++] = "-i";
189 argv[index++] = (char *)hnpRootPath;
190 argv[index++] = "-p";
191 argv[index++] = (char *)hapInfo->packageName;
192 argv[index++] = "-s";
193 argv[index++] = (char *)hapInfo->hapPath;
194 argv[index++] = "-a";
195 argv[index++] = (char *)hapInfo->abi;
196
197 if (installOptions >= 0 && IS_OPTION_SET((unsigned int)installOptions, OPTION_INDEX_FORCE)) {
198 argv[index++] = "-f";
199 }
200
201 return StartHnpProcess(argv, apcEnv);
202 }
203
NativeUnInstallHnp(const char * userId,const char * packageName)204 int NativeUnInstallHnp(const char *userId, const char *packageName)
205 {
206 char *argv[MAX_ARGV_NUM] = {0};
207 char *apcEnv[MAX_ENV_NUM] = {0};
208 int index = 0;
209
210 if (!IsDeveloperModeOpen()) {
211 HNPAPI_LOG("\r\n [HNP API] native package uninstall not in developer mode");
212 return HNP_API_NOT_IN_DEVELOPER_MODE;
213 }
214
215 if ((userId == NULL) || (packageName == NULL)) {
216 return HNP_API_ERRNO_PARAM_INVALID;
217 }
218
219 HNPAPI_LOG("\r\n [HNP API] native package uninstall! userId=%{public}s, package name=%{public}s\r\n", userId,
220 packageName);
221
222 argv[index++] = "hnp";
223 argv[index++] = "uninstall";
224 argv[index++] = "-u";
225 argv[index++] = (char *)userId;
226 argv[index++] = "-p";
227 argv[index++] = (char *)packageName;
228
229 return StartHnpProcess(argv, apcEnv);
230 }
231
232 #ifdef __cplusplus
233 }
234 #endif