1bae44755Sopenharmony_ci/*
2bae44755Sopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3bae44755Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4bae44755Sopenharmony_ci * you may not use this file except in compliance with the License.
5bae44755Sopenharmony_ci * You may obtain a copy of the License at
6bae44755Sopenharmony_ci *
7bae44755Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8bae44755Sopenharmony_ci *
9bae44755Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10bae44755Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11bae44755Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12bae44755Sopenharmony_ci * See the License for the specific language governing permissions and
13bae44755Sopenharmony_ci * limitations under the License.
14bae44755Sopenharmony_ci */
15bae44755Sopenharmony_ci
16bae44755Sopenharmony_ci#include "context_tool.h"
17bae44755Sopenharmony_ci
18bae44755Sopenharmony_ci#include <stdlib.h>
19bae44755Sopenharmony_ci#include <errno.h>
20bae44755Sopenharmony_ci#include <string.h>
21bae44755Sopenharmony_ci#include <limits.h>
22bae44755Sopenharmony_ci#include <sys/stat.h>
23bae44755Sopenharmony_ci#include "securec.h"
24bae44755Sopenharmony_ci
25bae44755Sopenharmony_ci#include "endian_internal.h"
26bae44755Sopenharmony_ci
27bae44755Sopenharmony_ci#ifdef SYSCAP_DEFINE_EXTERN_ENABLE
28bae44755Sopenharmony_ci#include "syscap_define_custom.h"
29bae44755Sopenharmony_ci#else
30bae44755Sopenharmony_ci#include "syscap_define.h"
31bae44755Sopenharmony_ci#endif
32bae44755Sopenharmony_ci
33bae44755Sopenharmony_civoid FreeContextBuffer(char *contextBuffer)
34bae44755Sopenharmony_ci{
35bae44755Sopenharmony_ci    if (contextBuffer != NULL) {
36bae44755Sopenharmony_ci        (void)free(contextBuffer);
37bae44755Sopenharmony_ci    }
38bae44755Sopenharmony_ci}
39bae44755Sopenharmony_ci
40bae44755Sopenharmony_ciint32_t GetFileContext(const char *inputFile, char **contextBufPtr, uint32_t *bufferLen)
41bae44755Sopenharmony_ci{
42bae44755Sopenharmony_ci    int32_t ret;
43bae44755Sopenharmony_ci    FILE *fp = NULL;
44bae44755Sopenharmony_ci    struct stat statBuf;
45bae44755Sopenharmony_ci    char *contextBuffer = NULL;
46bae44755Sopenharmony_ci    char path[PATH_MAX + 1] = {0x00};
47bae44755Sopenharmony_ci
48bae44755Sopenharmony_ci#ifdef _POSIX_
49bae44755Sopenharmony_ci    if (strlen(inputFile) > PATH_MAX || strncpy_s(path, PATH_MAX, inputFile, strlen(inputFile)) != EOK) {
50bae44755Sopenharmony_ci        PRINT_ERR("get path(%s) failed\n", inputFile);
51bae44755Sopenharmony_ci        return -1;
52bae44755Sopenharmony_ci    }
53bae44755Sopenharmony_ci#else
54bae44755Sopenharmony_ci    if (strlen(inputFile) > PATH_MAX || realpath(inputFile, path) == NULL) {
55bae44755Sopenharmony_ci        PRINT_ERR("get file(%s) real path failed\n", inputFile);
56bae44755Sopenharmony_ci        return -1;
57bae44755Sopenharmony_ci    }
58bae44755Sopenharmony_ci#endif
59bae44755Sopenharmony_ci
60bae44755Sopenharmony_ci    ret = stat(path, &statBuf);
61bae44755Sopenharmony_ci    if (ret != 0) {
62bae44755Sopenharmony_ci        PRINT_ERR("get file(%s) st_mode failed, errno = %d\n", path, errno);
63bae44755Sopenharmony_ci        return -1;
64bae44755Sopenharmony_ci    }
65bae44755Sopenharmony_ci    if (!(statBuf.st_mode & S_IRUSR)) {
66bae44755Sopenharmony_ci        PRINT_ERR("don't have permission to read the file(%s)\n", path);
67bae44755Sopenharmony_ci        return -1;
68bae44755Sopenharmony_ci    }
69bae44755Sopenharmony_ci    contextBuffer = (char *)malloc(statBuf.st_size + 1);
70bae44755Sopenharmony_ci    if (contextBuffer == NULL) {
71bae44755Sopenharmony_ci        PRINT_ERR("malloc buffer failed, size = %d, errno = %d\n", (int32_t)statBuf.st_size + 1, errno);
72bae44755Sopenharmony_ci        return -1;
73bae44755Sopenharmony_ci    }
74bae44755Sopenharmony_ci    fp = fopen(path, "rb");
75bae44755Sopenharmony_ci    if (fp == NULL) {
76bae44755Sopenharmony_ci        PRINT_ERR("open file(%s) failed, errno = %d\n", path, errno);
77bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
78bae44755Sopenharmony_ci        return -1;
79bae44755Sopenharmony_ci    }
80bae44755Sopenharmony_ci    size_t retFread = fread(contextBuffer, statBuf.st_size, 1, fp);
81bae44755Sopenharmony_ci    if (retFread != 1) {
82bae44755Sopenharmony_ci        PRINT_ERR("read file(%s) failed, errno = %d\n", path, errno);
83bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
84bae44755Sopenharmony_ci        (void)fclose(fp);
85bae44755Sopenharmony_ci        return -1;
86bae44755Sopenharmony_ci    }
87bae44755Sopenharmony_ci    contextBuffer[statBuf.st_size] = '\0';
88bae44755Sopenharmony_ci    (void)fclose(fp);
89bae44755Sopenharmony_ci
90bae44755Sopenharmony_ci    *contextBufPtr = contextBuffer;
91bae44755Sopenharmony_ci    *bufferLen = statBuf.st_size + 1;
92bae44755Sopenharmony_ci    return 0;
93bae44755Sopenharmony_ci}
94bae44755Sopenharmony_ci
95bae44755Sopenharmony_ciint32_t CheckFileAndGetFileContext(const char *inputFile, char **contextBufPtr, uint32_t *bufferLen)
96bae44755Sopenharmony_ci{
97bae44755Sopenharmony_ci    if (inputFile == NULL) {
98bae44755Sopenharmony_ci        PRINT_ERR("input file is NULL.\n");
99bae44755Sopenharmony_ci        return -1;
100bae44755Sopenharmony_ci    }
101bae44755Sopenharmony_ci    int32_t ret = GetFileContext(inputFile, contextBufPtr, bufferLen);
102bae44755Sopenharmony_ci    if (ret != 0) {
103bae44755Sopenharmony_ci        PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
104bae44755Sopenharmony_ci    }
105bae44755Sopenharmony_ci    return ret;
106bae44755Sopenharmony_ci}
107bae44755Sopenharmony_ci
108bae44755Sopenharmony_ciint32_t ConvertedContextSaveAsFile(char *outDirPath, const char *filename, char *convertedBuffer, size_t contextBufLen)
109bae44755Sopenharmony_ci{
110bae44755Sopenharmony_ci    int32_t ret;
111bae44755Sopenharmony_ci    FILE *fp = NULL;
112bae44755Sopenharmony_ci    char path[PATH_MAX + 1] = {0x00};
113bae44755Sopenharmony_ci
114bae44755Sopenharmony_ci#ifdef _POSIX_
115bae44755Sopenharmony_ci    if (strlen(outDirPath) >= PATH_MAX || strncpy_s(path, PATH_MAX, outDirPath, strlen(outDirPath)) != EOK) {
116bae44755Sopenharmony_ci        PRINT_ERR("get path(%s) failed\n", outDirPath);
117bae44755Sopenharmony_ci        return -1;
118bae44755Sopenharmony_ci    }
119bae44755Sopenharmony_ci#else
120bae44755Sopenharmony_ci    if (strlen(outDirPath) >= PATH_MAX || realpath(outDirPath, path) == NULL) {
121bae44755Sopenharmony_ci        PRINT_ERR("get file(%s) real path failed\n", outDirPath);
122bae44755Sopenharmony_ci        return -1;
123bae44755Sopenharmony_ci    }
124bae44755Sopenharmony_ci#endif
125bae44755Sopenharmony_ci    int32_t pathLen = strlen(path);
126bae44755Sopenharmony_ci    if (path[pathLen - 1] != '/' && path[pathLen - 1] != '\\') {
127bae44755Sopenharmony_ci        path[pathLen] = '/';
128bae44755Sopenharmony_ci    }
129bae44755Sopenharmony_ci
130bae44755Sopenharmony_ci    if (strlen(path) + strlen(filename) + 1 > PATH_MAX) {
131bae44755Sopenharmony_ci        PRINT_ERR("length of path too long.\n");
132bae44755Sopenharmony_ci        return -1;
133bae44755Sopenharmony_ci    }
134bae44755Sopenharmony_ci    ret = strncat_s(path, PATH_MAX, filename, strlen(filename) + 1);
135bae44755Sopenharmony_ci    if (ret != 0) {
136bae44755Sopenharmony_ci        PRINT_ERR("strncat_s failed, (%s, %d, %s, %d), errno = %d\n",
137bae44755Sopenharmony_ci                  path, PATH_MAX, filename, (int32_t)strlen(filename) + 1, errno);
138bae44755Sopenharmony_ci        return -1;
139bae44755Sopenharmony_ci    }
140bae44755Sopenharmony_ci
141bae44755Sopenharmony_ci    fp = fopen(path, "wb");
142bae44755Sopenharmony_ci    if (fp == NULL) {
143bae44755Sopenharmony_ci        PRINT_ERR("can't create file(%s), errno = %d\n", path, errno);
144bae44755Sopenharmony_ci        return -1;
145bae44755Sopenharmony_ci    }
146bae44755Sopenharmony_ci
147bae44755Sopenharmony_ci    if (fwrite(convertedBuffer, contextBufLen, 1, fp) != 1) {
148bae44755Sopenharmony_ci        PRINT_ERR("can't write file(%s),errno = %d\n", path, errno);
149bae44755Sopenharmony_ci        (void)fclose(fp);
150bae44755Sopenharmony_ci        return -1;
151bae44755Sopenharmony_ci    }
152bae44755Sopenharmony_ci
153bae44755Sopenharmony_ci    (void)fclose(fp);
154bae44755Sopenharmony_ci
155bae44755Sopenharmony_ci    return 0;
156bae44755Sopenharmony_ci}
157bae44755Sopenharmony_ci
158bae44755Sopenharmony_ciint32_t CheckRpcidFormat(const char *inputFile, char **buffer, uint32_t *len)
159bae44755Sopenharmony_ci{
160bae44755Sopenharmony_ci    uint32_t bufferLen;
161bae44755Sopenharmony_ci    uint16_t sysCaptype, sysCapLength;
162bae44755Sopenharmony_ci    char *contextBuffer = NULL;
163bae44755Sopenharmony_ci    RPCIDHead *rpcidHeader = NULL;
164bae44755Sopenharmony_ci
165bae44755Sopenharmony_ci    if (GetFileContext(inputFile, &contextBuffer, &bufferLen)) {
166bae44755Sopenharmony_ci        PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
167bae44755Sopenharmony_ci        return -1;
168bae44755Sopenharmony_ci    }
169bae44755Sopenharmony_ci    if (bufferLen < (2 * sizeof(uint32_t))) { // 2, header of rpcid.sc
170bae44755Sopenharmony_ci        PRINT_ERR("Parse file failed(format is invalid), input file : %s\n", inputFile);
171bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
172bae44755Sopenharmony_ci        return -1;
173bae44755Sopenharmony_ci    }
174bae44755Sopenharmony_ci    rpcidHeader = (RPCIDHead *)contextBuffer;
175bae44755Sopenharmony_ci    if (rpcidHeader->apiVersionType != 1) {
176bae44755Sopenharmony_ci        PRINT_ERR("Parse file failed(apiVersionType != 1), input file : %s\n", inputFile);
177bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
178bae44755Sopenharmony_ci        return -1;
179bae44755Sopenharmony_ci    }
180bae44755Sopenharmony_ci    sysCaptype = NtohsInter(*(uint16_t *)(rpcidHeader + 1));
181bae44755Sopenharmony_ci    if (sysCaptype != 2) { // 2, app syscap type
182bae44755Sopenharmony_ci        PRINT_ERR("Parse file failed(sysCaptype != 2), input file : %s\n", inputFile);
183bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
184bae44755Sopenharmony_ci        return -1;
185bae44755Sopenharmony_ci    }
186bae44755Sopenharmony_ci    sysCapLength = NtohsInter(*(uint16_t *)((char *)(rpcidHeader + 1) + sizeof(uint16_t)));
187bae44755Sopenharmony_ci    if (bufferLen < sizeof(RPCIDHead) + sizeof(uint32_t) + sysCapLength) {
188bae44755Sopenharmony_ci        PRINT_ERR("Parse file failed(SysCap length exceeded), input file : %s\n", inputFile);
189bae44755Sopenharmony_ci        FreeContextBuffer(contextBuffer);
190bae44755Sopenharmony_ci        return -1;
191bae44755Sopenharmony_ci    }
192bae44755Sopenharmony_ci
193bae44755Sopenharmony_ci    *buffer = contextBuffer;
194bae44755Sopenharmony_ci    *len = bufferLen;
195bae44755Sopenharmony_ci    return 0;
196bae44755Sopenharmony_ci}
197bae44755Sopenharmony_ci
198bae44755Sopenharmony_cicJSON *CreateWholeSyscapJsonObj(void)
199bae44755Sopenharmony_ci{
200bae44755Sopenharmony_ci    cJSON *syscapJsonObj =  cJSON_CreateObject();
201bae44755Sopenharmony_ci    if (syscapJsonObj == NULL) {
202bae44755Sopenharmony_ci        PRINT_ERR("interface-create jsonObj failed.");
203bae44755Sopenharmony_ci        return NULL;
204bae44755Sopenharmony_ci    }
205bae44755Sopenharmony_ci
206bae44755Sopenharmony_ci    size_t syscapNums = sizeof(g_arraySyscap) / sizeof(SyscapWithNum);
207bae44755Sopenharmony_ci    for (size_t i = 0; i < syscapNums; i++) {
208bae44755Sopenharmony_ci        cJSON_AddItemToObject(syscapJsonObj, g_arraySyscap[i].str, cJSON_CreateNumber(g_arraySyscap[i].num));
209bae44755Sopenharmony_ci    }
210bae44755Sopenharmony_ci    return syscapJsonObj;
211bae44755Sopenharmony_ci}
212