169570cc8Sopenharmony_ci/* 269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License. 569570cc8Sopenharmony_ci * You may obtain a copy of the License at 669570cc8Sopenharmony_ci * 769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 869570cc8Sopenharmony_ci * 969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and 1369570cc8Sopenharmony_ci * limitations under the License. 1469570cc8Sopenharmony_ci */ 1569570cc8Sopenharmony_ci 1669570cc8Sopenharmony_ci#include <unistd.h> 1769570cc8Sopenharmony_ci#include <stdlib.h> 1869570cc8Sopenharmony_ci#include <stdio.h> 1969570cc8Sopenharmony_ci#include <sys/wait.h> 2069570cc8Sopenharmony_ci 2169570cc8Sopenharmony_ci#include "hilog/log.h" 2269570cc8Sopenharmony_ci#include "appspawn_utils.h" 2369570cc8Sopenharmony_ci#include "securec.h" 2469570cc8Sopenharmony_ci#include "parameter.h" 2569570cc8Sopenharmony_ci 2669570cc8Sopenharmony_ci#include "hnp_api.h" 2769570cc8Sopenharmony_ci 2869570cc8Sopenharmony_ci#ifdef __cplusplus 2969570cc8Sopenharmony_ciextern "C" { 3069570cc8Sopenharmony_ci#endif 3169570cc8Sopenharmony_ci 3269570cc8Sopenharmony_ci#define HNPAPI_LOG(fmt, ...) \ 3369570cc8Sopenharmony_ci HILOG_INFO(LOG_CORE, "[%{public}s:%{public}d]" fmt, (__FILE_NAME__), (__LINE__), ##__VA_ARGS__) 3469570cc8Sopenharmony_ci#define MAX_ARGV_NUM 256 3569570cc8Sopenharmony_ci#define MAX_ENV_NUM (128 + 2) 3669570cc8Sopenharmony_ci#define IS_OPTION_SET(x, option) ((x) & (1 << (option))) 3769570cc8Sopenharmony_ci#define BUFFER_SIZE 1024 3869570cc8Sopenharmony_ci#define CMD_API_TEXT_LEN 50 3969570cc8Sopenharmony_ci#define PARAM_BUFFER_SIZE 10 4069570cc8Sopenharmony_ci 4169570cc8Sopenharmony_ci/* 数字索引 */ 4269570cc8Sopenharmony_cienum { 4369570cc8Sopenharmony_ci HNP_INDEX_0 = 0, 4469570cc8Sopenharmony_ci HNP_INDEX_1, 4569570cc8Sopenharmony_ci HNP_INDEX_2, 4669570cc8Sopenharmony_ci HNP_INDEX_3, 4769570cc8Sopenharmony_ci HNP_INDEX_4, 4869570cc8Sopenharmony_ci HNP_INDEX_5, 4969570cc8Sopenharmony_ci HNP_INDEX_6, 5069570cc8Sopenharmony_ci HNP_INDEX_7 5169570cc8Sopenharmony_ci}; 5269570cc8Sopenharmony_ci 5369570cc8Sopenharmony_cistatic int HnpCmdApiReturnGet(int readFd, int *ret) 5469570cc8Sopenharmony_ci{ 5569570cc8Sopenharmony_ci char buffer[BUFFER_SIZE] = {0}; 5669570cc8Sopenharmony_ci ssize_t bytesRead; 5769570cc8Sopenharmony_ci int bufferEnd = 0; // 跟踪缓冲区中有效数据的末尾 5869570cc8Sopenharmony_ci const char *prefix = "native manager process exit. ret="; 5969570cc8Sopenharmony_ci 6069570cc8Sopenharmony_ci // 循环读取子进程的输出,直到结束 6169570cc8Sopenharmony_ci while ((bytesRead = read(readFd, buffer + bufferEnd, BUFFER_SIZE - bufferEnd - 1)) > 0) { 6269570cc8Sopenharmony_ci // 更新有效数据的末尾 6369570cc8Sopenharmony_ci bufferEnd += bytesRead; 6469570cc8Sopenharmony_ci 6569570cc8Sopenharmony_ci // 如果缓冲区中的数据超过或等于50个字节,移动数据以保留最后50个字节 6669570cc8Sopenharmony_ci if (bufferEnd >= CMD_API_TEXT_LEN) { 6769570cc8Sopenharmony_ci if (memmove_s(buffer, BUFFER_SIZE, buffer + bufferEnd - CMD_API_TEXT_LEN, CMD_API_TEXT_LEN) != EOK) { 6869570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] mem move unsuccess!\r\n"); 6969570cc8Sopenharmony_ci return HNP_API_ERRNO_MEMMOVE_FAILED; 7069570cc8Sopenharmony_ci } 7169570cc8Sopenharmony_ci bufferEnd = CMD_API_TEXT_LEN; 7269570cc8Sopenharmony_ci } 7369570cc8Sopenharmony_ci 7469570cc8Sopenharmony_ci buffer[bufferEnd] = '\0'; 7569570cc8Sopenharmony_ci } 7669570cc8Sopenharmony_ci 7769570cc8Sopenharmony_ci if (bytesRead == -1) { 7869570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] read stream unsuccess!\r\n"); 7969570cc8Sopenharmony_ci return HNP_API_ERRNO_PIPE_READ_FAILED; 8069570cc8Sopenharmony_ci } 8169570cc8Sopenharmony_ci 8269570cc8Sopenharmony_ci char *retStr = strstr(buffer, prefix); 8369570cc8Sopenharmony_ci 8469570cc8Sopenharmony_ci if (retStr != NULL) { 8569570cc8Sopenharmony_ci // 获取后续的数字字符串 8669570cc8Sopenharmony_ci retStr += strlen(prefix); 8769570cc8Sopenharmony_ci *ret = atoi(retStr); 8869570cc8Sopenharmony_ci 8969570cc8Sopenharmony_ci return 0; 9069570cc8Sopenharmony_ci } 9169570cc8Sopenharmony_ci 9269570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] get return unsuccess!, buffer is:%{public}s\r\n", buffer); 9369570cc8Sopenharmony_ci return HNP_API_ERRNO_RETURN_VALUE_GET_FAILED; 9469570cc8Sopenharmony_ci} 9569570cc8Sopenharmony_ci 9669570cc8Sopenharmony_cistatic int StartHnpProcess(char *const argv[], char *const apcEnv[]) 9769570cc8Sopenharmony_ci{ 9869570cc8Sopenharmony_ci int fd[2]; 9969570cc8Sopenharmony_ci pid_t pid; 10069570cc8Sopenharmony_ci int exitVal = -1; 10169570cc8Sopenharmony_ci int ret; 10269570cc8Sopenharmony_ci int status; 10369570cc8Sopenharmony_ci 10469570cc8Sopenharmony_ci if (pipe(fd) < 0) { 10569570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] pipe fd unsuccess!\r\n"); 10669570cc8Sopenharmony_ci return HNP_API_ERRNO_PIPE_CREATED_FAILED; 10769570cc8Sopenharmony_ci } 10869570cc8Sopenharmony_ci 10969570cc8Sopenharmony_ci pid = vfork(); 11069570cc8Sopenharmony_ci if (pid < 0) { 11169570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] fork unsuccess!\r\n"); 11269570cc8Sopenharmony_ci return HNP_API_ERRNO_FORK_FAILED; 11369570cc8Sopenharmony_ci } else if (pid == 0) { 11469570cc8Sopenharmony_ci close(fd[0]); 11569570cc8Sopenharmony_ci // 将子进程的stdout重定向到管道的写端 11669570cc8Sopenharmony_ci dup2(fd[1], STDOUT_FILENO); 11769570cc8Sopenharmony_ci close(fd[1]); 11869570cc8Sopenharmony_ci 11969570cc8Sopenharmony_ci ret = execve("/system/bin/hnp", argv, apcEnv); 12069570cc8Sopenharmony_ci if (ret < 0) { 12169570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] execve unsuccess!\r\n"); 12269570cc8Sopenharmony_ci _exit(-1); 12369570cc8Sopenharmony_ci } 12469570cc8Sopenharmony_ci _exit(0); 12569570cc8Sopenharmony_ci } 12669570cc8Sopenharmony_ci 12769570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] this is fork father! chid=%{public}d\r\n", pid); 12869570cc8Sopenharmony_ci close(fd[1]); 12969570cc8Sopenharmony_ci if (waitpid(pid, &status, 0) == -1) { 13069570cc8Sopenharmony_ci close(fd[0]); 13169570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] wait pid unsuccess!\r\n"); 13269570cc8Sopenharmony_ci return HNP_API_WAIT_PID_FAILED; 13369570cc8Sopenharmony_ci } 13469570cc8Sopenharmony_ci ret = HnpCmdApiReturnGet(fd[0], &exitVal); 13569570cc8Sopenharmony_ci close(fd[0]); 13669570cc8Sopenharmony_ci if (ret != 0) { 13769570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] get api return value unsuccess!\r\n"); 13869570cc8Sopenharmony_ci return ret; 13969570cc8Sopenharmony_ci } 14069570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] Child process exited with exitval=%{public}d\r\n", exitVal); 14169570cc8Sopenharmony_ci 14269570cc8Sopenharmony_ci return exitVal; 14369570cc8Sopenharmony_ci} 14469570cc8Sopenharmony_ci 14569570cc8Sopenharmony_cistatic bool IsHnpInstallEnable() 14669570cc8Sopenharmony_ci{ 14769570cc8Sopenharmony_ci char buffer[PARAM_BUFFER_SIZE] = {0}; 14869570cc8Sopenharmony_ci int ret = GetParameter("const.startup.hnp.install.enable", "false", buffer, PARAM_BUFFER_SIZE); 14969570cc8Sopenharmony_ci if (ret <= 0) { 15069570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] get hnp install enable param unsuccess! ret =%{public}d\r\n", ret); 15169570cc8Sopenharmony_ci return false; 15269570cc8Sopenharmony_ci } 15369570cc8Sopenharmony_ci 15469570cc8Sopenharmony_ci if (strcmp(buffer, "true") == 0) { 15569570cc8Sopenharmony_ci return true; 15669570cc8Sopenharmony_ci } 15769570cc8Sopenharmony_ci 15869570cc8Sopenharmony_ci return false; 15969570cc8Sopenharmony_ci} 16069570cc8Sopenharmony_ci 16169570cc8Sopenharmony_ciint NativeInstallHnp(const char *userId, const char *hnpRootPath, const HapInfo *hapInfo, int installOptions) 16269570cc8Sopenharmony_ci{ 16369570cc8Sopenharmony_ci char *argv[MAX_ARGV_NUM] = {0}; 16469570cc8Sopenharmony_ci char *apcEnv[MAX_ENV_NUM] = {0}; 16569570cc8Sopenharmony_ci int index = 0; 16669570cc8Sopenharmony_ci 16769570cc8Sopenharmony_ci if (!IsDeveloperModeOpen()) { 16869570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] native package install not in developer mode"); 16969570cc8Sopenharmony_ci return HNP_API_NOT_IN_DEVELOPER_MODE; 17069570cc8Sopenharmony_ci } 17169570cc8Sopenharmony_ci 17269570cc8Sopenharmony_ci if ((userId == NULL) || (hnpRootPath == NULL) || (hapInfo == NULL)) { 17369570cc8Sopenharmony_ci return HNP_API_ERRNO_PARAM_INVALID; 17469570cc8Sopenharmony_ci } 17569570cc8Sopenharmony_ci 17669570cc8Sopenharmony_ci if (!IsHnpInstallEnable()) { 17769570cc8Sopenharmony_ci return HNP_API_ERRNO_HNP_INSTALL_DISABLED; 17869570cc8Sopenharmony_ci } 17969570cc8Sopenharmony_ci 18069570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] native package install! userId=%{public}s, hap path=%{public}s, sys abi=%{public}s, " 18169570cc8Sopenharmony_ci "hnp root path=%{public}s, package name=%{public}s install options=%{public}d\r\n", userId, hapInfo->hapPath, 18269570cc8Sopenharmony_ci hapInfo->abi, hnpRootPath, hapInfo->packageName, installOptions); 18369570cc8Sopenharmony_ci 18469570cc8Sopenharmony_ci argv[index++] = "hnp"; 18569570cc8Sopenharmony_ci argv[index++] = "install"; 18669570cc8Sopenharmony_ci argv[index++] = "-u"; 18769570cc8Sopenharmony_ci argv[index++] = (char *)userId; 18869570cc8Sopenharmony_ci argv[index++] = "-i"; 18969570cc8Sopenharmony_ci argv[index++] = (char *)hnpRootPath; 19069570cc8Sopenharmony_ci argv[index++] = "-p"; 19169570cc8Sopenharmony_ci argv[index++] = (char *)hapInfo->packageName; 19269570cc8Sopenharmony_ci argv[index++] = "-s"; 19369570cc8Sopenharmony_ci argv[index++] = (char *)hapInfo->hapPath; 19469570cc8Sopenharmony_ci argv[index++] = "-a"; 19569570cc8Sopenharmony_ci argv[index++] = (char *)hapInfo->abi; 19669570cc8Sopenharmony_ci 19769570cc8Sopenharmony_ci if (installOptions >= 0 && IS_OPTION_SET((unsigned int)installOptions, OPTION_INDEX_FORCE)) { 19869570cc8Sopenharmony_ci argv[index++] = "-f"; 19969570cc8Sopenharmony_ci } 20069570cc8Sopenharmony_ci 20169570cc8Sopenharmony_ci return StartHnpProcess(argv, apcEnv); 20269570cc8Sopenharmony_ci} 20369570cc8Sopenharmony_ci 20469570cc8Sopenharmony_ciint NativeUnInstallHnp(const char *userId, const char *packageName) 20569570cc8Sopenharmony_ci{ 20669570cc8Sopenharmony_ci char *argv[MAX_ARGV_NUM] = {0}; 20769570cc8Sopenharmony_ci char *apcEnv[MAX_ENV_NUM] = {0}; 20869570cc8Sopenharmony_ci int index = 0; 20969570cc8Sopenharmony_ci 21069570cc8Sopenharmony_ci if (!IsDeveloperModeOpen()) { 21169570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] native package uninstall not in developer mode"); 21269570cc8Sopenharmony_ci return HNP_API_NOT_IN_DEVELOPER_MODE; 21369570cc8Sopenharmony_ci } 21469570cc8Sopenharmony_ci 21569570cc8Sopenharmony_ci if ((userId == NULL) || (packageName == NULL)) { 21669570cc8Sopenharmony_ci return HNP_API_ERRNO_PARAM_INVALID; 21769570cc8Sopenharmony_ci } 21869570cc8Sopenharmony_ci 21969570cc8Sopenharmony_ci HNPAPI_LOG("\r\n [HNP API] native package uninstall! userId=%{public}s, package name=%{public}s\r\n", userId, 22069570cc8Sopenharmony_ci packageName); 22169570cc8Sopenharmony_ci 22269570cc8Sopenharmony_ci argv[index++] = "hnp"; 22369570cc8Sopenharmony_ci argv[index++] = "uninstall"; 22469570cc8Sopenharmony_ci argv[index++] = "-u"; 22569570cc8Sopenharmony_ci argv[index++] = (char *)userId; 22669570cc8Sopenharmony_ci argv[index++] = "-p"; 22769570cc8Sopenharmony_ci argv[index++] = (char *)packageName; 22869570cc8Sopenharmony_ci 22969570cc8Sopenharmony_ci return StartHnpProcess(argv, apcEnv); 23069570cc8Sopenharmony_ci} 23169570cc8Sopenharmony_ci 23269570cc8Sopenharmony_ci#ifdef __cplusplus 23369570cc8Sopenharmony_ci} 23469570cc8Sopenharmony_ci#endif