1 /*
2 * Copyright (c) 2022 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 "syscap_tool.h"
17
18 #include <arpa/inet.h>
19 #include <errno.h>
20 #include <libgen.h>
21 #include <securec.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 #include "hilog/log.h"
31
32 const int32_t OK = 0;
33 const int32_t ERROR = -1;
34 const int32_t API_VERSION_TYPE = 1;
35 const int32_t APP_SYSCAP_TYPE = 2;
36 const int32_t SYSCAP_PREFIX_NAME_LEN = 18;
37 const char SYSCAP_PREFIX_NAME[] = "SystemCapability.";
38
39 typedef struct RequiredProductCompatibilityIDHead {
40 uint16_t apiVersion : 15;
41 uint16_t apiVersionType : 1;
42 } RPCIDHead;
43
FreeContextBuffer(char * contextBuffer)44 static void FreeContextBuffer(char *contextBuffer)
45 {
46 (void)free(contextBuffer);
47 }
48
GetFileContext(char * inputFile,char ** contextBufPtr,uint32_t * bufferLen)49 static int32_t GetFileContext(char *inputFile, char **contextBufPtr, uint32_t *bufferLen)
50 {
51 if (inputFile == NULL) {
52 return ERROR;
53 }
54 int32_t ret;
55 FILE *fp = NULL;
56 struct stat statBuf;
57 char *contextBuffer = NULL;
58 ret = stat(inputFile, &statBuf);
59 if (ret != OK) {
60 HILOG_ERROR(LOG_CORE, "get file(%s) st_mode failed, errno = %d\n", inputFile, errno);
61 return ret;
62 }
63
64 if (!(statBuf.st_mode & S_IRUSR)) {
65 HILOG_ERROR(LOG_CORE, "don't have permission to read the file(%s)\n", inputFile);
66 return ERROR;
67 }
68
69 contextBuffer = (char *)malloc(statBuf.st_size + 1);
70 if (contextBuffer == NULL) {
71 HILOG_ERROR(LOG_CORE, "malloc contextBuffer failed, size = %d, errno = %d\n",
72 (int32_t)statBuf.st_size + 1, errno);
73 return ERROR;
74 }
75
76 fp = fopen(inputFile, "r");
77 if (fp == NULL) {
78 HILOG_ERROR(LOG_CORE, "open file(%s) failed, errno = %d\n", inputFile, errno);
79 FreeContextBuffer(contextBuffer);
80 return ERROR;
81 }
82
83 size_t res = fread(contextBuffer, statBuf.st_size, 1, fp);
84 if (res != 1) {
85 HILOG_ERROR(LOG_CORE, "read file(%s) failed, errno = %d\n", inputFile, errno);
86 FreeContextBuffer(contextBuffer);
87 (void)fclose(fp);
88 return ERROR;
89 }
90
91 contextBuffer[statBuf.st_size] = '\0';
92 (void)fclose(fp);
93 *contextBufPtr = contextBuffer;
94 *bufferLen = statBuf.st_size + 1;
95 return OK;
96 }
97
RPCIDStreamDecodeToBuffer(char * contextBuffer,uint32_t bufferLen,char ** syscapSetBuf,uint32_t * syscapSetLength)98 int32_t RPCIDStreamDecodeToBuffer(
99 char *contextBuffer, uint32_t bufferLen, char **syscapSetBuf, uint32_t *syscapSetLength)
100 {
101 errno_t ret;
102 char *contextBufferTail = NULL;
103 char *syscapBuf = NULL;
104 uint32_t syscapBufLen;
105 uint16_t sysCaptype, sysCapLength;
106 RPCIDHead *headPtr = NULL;
107 char *sysCapArrayPtr = NULL;
108 *syscapSetBuf = NULL;
109 *syscapSetLength = 0;
110 if (contextBuffer == NULL) {
111 HILOG_ERROR(LOG_CORE, "input buffer is NULL\n");
112 return ERROR;
113 }
114
115 contextBufferTail = contextBuffer + bufferLen;
116 sysCapArrayPtr = contextBuffer + sizeof(RPCIDHead) + APP_SYSCAP_TYPE * sizeof(uint16_t);
117 if (contextBufferTail <= sysCapArrayPtr) {
118 HILOG_ERROR(LOG_CORE, "format error:sysCapArray head over to buffer\n");
119 return ERROR;
120 }
121
122 headPtr = (RPCIDHead *)contextBuffer;
123 if (headPtr->apiVersionType != API_VERSION_TYPE) {
124 HILOG_ERROR(LOG_CORE, "format error:apiVersionType is invaild\n");
125 return ERROR;
126 }
127
128 sysCaptype = ntohs(*(uint16_t *)(sysCapArrayPtr - APP_SYSCAP_TYPE * sizeof(uint16_t)));
129 if (sysCaptype != APP_SYSCAP_TYPE) {
130 HILOG_ERROR(LOG_CORE, "format error:sysCaptype is invaild\n");
131 return ERROR;
132 }
133
134 sysCapLength = ntohs(*(uint16_t *)(sysCapArrayPtr - sizeof(uint16_t)));
135 if (contextBufferTail < sysCapArrayPtr + sysCapLength) {
136 HILOG_ERROR(LOG_CORE, "format error:sysCapArray tail over to buffer\n");
137 return ERROR;
138 }
139
140 if ((sysCapLength % SINGLE_FEAT_LENGTH) != 0) {
141 HILOG_ERROR(LOG_CORE, "format error:sysCapLength is invalid\n");
142 return ERROR;
143 }
144
145 syscapBufLen = sysCapLength / SINGLE_FEAT_LENGTH * SINGLE_SYSCAP_LENGTH;
146 syscapBuf = (char *)malloc(syscapBufLen);
147 if (syscapBuf == NULL) {
148 HILOG_ERROR(LOG_CORE, "malloc syscapBuf failed, size = %u, errno = %d\n", syscapBufLen, errno);
149 return ERROR;
150 }
151
152 (void)memset_s(syscapBuf, syscapBufLen, 0, syscapBufLen);
153 char *bufferPtr = syscapBuf;
154 for (int32_t i = 0; i < ((int32_t)sysCapLength / SINGLE_FEAT_LENGTH); i++) {
155 if (*(sysCapArrayPtr + (i + 1) * SINGLE_FEAT_LENGTH - 1) != '\0') {
156 HILOG_ERROR(LOG_CORE, "prase failed, format is invaild, in line %d\n", __LINE__);
157 (void)free(syscapBuf);
158 return ERROR;
159 }
160
161 ret = memcpy_s(bufferPtr, SINGLE_SYSCAP_LENGTH, SYSCAP_PREFIX_NAME, SYSCAP_PREFIX_NAME_LEN);
162 if (ret != EOK) {
163 HILOG_ERROR(LOG_CORE, "context of \"os\" array is invaild\n");
164 (void)free(syscapBuf);
165 return ERROR;
166 }
167
168 ret = strncat_s(bufferPtr, SINGLE_SYSCAP_LENGTH, sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
169 if (ret != EOK) {
170 HILOG_ERROR(LOG_CORE, "strncat_s failed, (%s, %d, %s, %d)\n", bufferPtr, SINGLE_SYSCAP_LENGTH,
171 sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
172 (void)free(syscapBuf);
173 return ERROR;
174 }
175
176 bufferPtr += SINGLE_SYSCAP_LENGTH;
177 }
178
179 *syscapSetBuf = syscapBuf;
180 *syscapSetLength = syscapBufLen;
181 return OK;
182 }
183
RPCIDFileDecodeToBuffer(char * inputFile,char ** syscapSetBuf,uint32_t * syscapSetLength)184 int32_t RPCIDFileDecodeToBuffer(char *inputFile, char **syscapSetBuf, uint32_t *syscapSetLength)
185 {
186 int32_t ret;
187 char *contextBuffer = NULL;
188 uint32_t bufferLen;
189 ret = GetFileContext(inputFile, &contextBuffer, &bufferLen);
190 if (ret != 0) {
191 HILOG_ERROR(LOG_CORE, "GetFileContext failed, input file : %s\n", inputFile);
192 return ret;
193 }
194
195 ret = RPCIDStreamDecodeToBuffer(contextBuffer, bufferLen, syscapSetBuf, syscapSetLength);
196 FreeContextBuffer(contextBuffer);
197 return ret;
198 }
199
FreeDecodeBuffer(char * syscapSetBuf)200 void FreeDecodeBuffer(char *syscapSetBuf)
201 {
202 (void)free(syscapSetBuf);
203 }
204