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
ConvertedContextSaveAsFile(char * outDirPath,const char * filename,char * convertedBuffer,size_t contextBufLen)95 int32_t ConvertedContextSaveAsFile(char *outDirPath, const char *filename, char *convertedBuffer, size_t contextBufLen)
96 {
97 int32_t ret;
98 FILE *fp = NULL;
99 char path[PATH_MAX + 1] = {0x00};
100
101 #ifdef _POSIX_
102 if (strlen(outDirPath) >= PATH_MAX || strncpy_s(path, PATH_MAX, outDirPath, strlen(outDirPath)) != EOK) {
103 PRINT_ERR("get path(%s) failed\n", outDirPath);
104 return -1;
105 }
106 #else
107 if (strlen(outDirPath) >= PATH_MAX || realpath(outDirPath, path) == NULL) {
108 PRINT_ERR("get file(%s) real path failed\n", outDirPath);
109 return -1;
110 }
111 #endif
112 int32_t pathLen = strlen(path);
113 if (path[pathLen - 1] != '/' && path[pathLen - 1] != '\\') {
114 path[pathLen] = '/';
115 }
116
117 if (strlen(path) + strlen(filename) + 1 > PATH_MAX) {
118 PRINT_ERR("length of path too long.\n");
119 return -1;
120 }
121 ret = strncat_s(path, PATH_MAX, filename, strlen(filename) + 1);
122 if (ret != 0) {
123 PRINT_ERR("strncat_s failed, (%s, %d, %s, %d), errno = %d\n",
124 path, PATH_MAX, filename, (int32_t)strlen(filename) + 1, errno);
125 return -1;
126 }
127
128 fp = fopen(path, "wb");
129 if (fp == NULL) {
130 PRINT_ERR("can't create file(%s), errno = %d\n", path, errno);
131 return -1;
132 }
133
134 if (fwrite(convertedBuffer, contextBufLen, 1, fp) != 1) {
135 PRINT_ERR("can't write file(%s),errno = %d\n", path, errno);
136 (void)fclose(fp);
137 return -1;
138 }
139
140 (void)fclose(fp);
141
142 return 0;
143 }
144
CheckRpcidFormat(const char * inputFile,char ** buffer,uint32_t * len)145 int32_t CheckRpcidFormat(const char *inputFile, char **buffer, uint32_t *len)
146 {
147 uint32_t bufferLen;
148 uint16_t sysCaptype, sysCapLength;
149 char *contextBuffer = NULL;
150 RPCIDHead *rpcidHeader = NULL;
151
152 if (GetFileContext(inputFile, &contextBuffer, &bufferLen)) {
153 PRINT_ERR("GetFileContext failed, input file : %s\n", inputFile);
154 return -1;
155 }
156 if (bufferLen < (2 * sizeof(uint32_t))) { // 2, header of rpcid.sc
157 PRINT_ERR("Parse file failed(format is invalid), input file : %s\n", inputFile);
158 return -1;
159 }
160 rpcidHeader = (RPCIDHead *)contextBuffer;
161 if (rpcidHeader->apiVersionType != 1) {
162 PRINT_ERR("Parse file failed(apiVersionType != 1), input file : %s\n", inputFile);
163 return -1;
164 }
165 sysCaptype = NtohsInter(*(uint16_t *)(rpcidHeader + 1));
166 if (sysCaptype != 2) { // 2, app syscap type
167 PRINT_ERR("Parse file failed(sysCaptype != 2), input file : %s\n", inputFile);
168 return -1;
169 }
170 sysCapLength = NtohsInter(*(uint16_t *)((char *)(rpcidHeader + 1) + sizeof(uint16_t)));
171 if (bufferLen < sizeof(RPCIDHead) + sizeof(uint32_t) + sysCapLength) {
172 PRINT_ERR("Parse file failed(SysCap length exceeded), input file : %s\n", inputFile);
173 return -1;
174 }
175
176 *buffer = contextBuffer;
177 *len = bufferLen;
178 return 0;
179 }
180
CreateWholeSyscapJsonObj(void)181 cJSON *CreateWholeSyscapJsonObj(void)
182 {
183 cJSON *syscapJsonObj = cJSON_CreateObject();
184 if (syscapJsonObj == NULL) {
185 PRINT_ERR("interface-create jsonObj failed.");
186 return NULL;
187 }
188
189 size_t syscapNums = sizeof(g_arraySyscap) / sizeof(SyscapWithNum);
190 for (size_t i = 0; i < syscapNums; i++) {
191 cJSON_AddItemToObject(syscapJsonObj, g_arraySyscap[i].str, cJSON_CreateNumber(g_arraySyscap[i].num));
192 }
193 return syscapJsonObj;
194 }
195