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