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