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