1 /*
2 * Copyright (C) 2022-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 <cstdint>
17 #include <cstring>
18 #include <cstdlib>
19 #include <securec.h>
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 #include "syscap_interface.h"
23
24 namespace OHOS {
25 EXTERN_C_START
26 constexpr size_t OS_SYSCAP_U32_NUM = 30;
27 constexpr size_t PCID_MAIN_U32 = OS_SYSCAP_U32_NUM + 2;
28 constexpr size_t U32_TO_STR_MAX_LEN = 11;
29 constexpr size_t KEY_BUFFER_SIZE = 32;
30
31 #define PRINT_ERR(...) \
32 do { \
33 printf("ERROR: [%s: %d] -> ", __FILE__, __LINE__); \
34 printf(__VA_ARGS__); \
35 } while (0)
36
37 #define GET_PARAMS(env, info, num) \
38 size_t argc = num; \
39 napi_value argv[num] = {0}; \
40 napi_value thisVar = nullptr; \
41 void *data; \
42 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
43
44 // Async Function Set
45 struct SystemCapabilityAsyncContext {
46 napi_env env = nullptr;
47 napi_async_work work = nullptr;
48 char key[KEY_BUFFER_SIZE] = { 0 };
49 size_t keyLen = 0;
50 char *value = nullptr;
51 size_t valueLen = 0;
52 napi_deferred deferred = nullptr;
53 napi_ref callbackRef = nullptr;
54
55 int status = 0;
56 };
57
GetSystemCapability()58 static char* GetSystemCapability()
59 {
60 bool retBool;
61 int retError, priOutputLen, priCapArrayCnt, sumLen;
62 char osOutput[SINGLE_SYSCAP_LEN] = {};
63 errno_t err = EOK;
64 uint32_t *osCapU32 = nullptr;
65 char *priOutput = nullptr;
66 char *temp = nullptr;
67 char *allSyscapBuffer = nullptr;
68 char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN] = {};
69 char (*priCapArray)[SINGLE_SYSCAP_LEN] = nullptr;
70
71 retBool = EncodeOsSyscap(osOutput, PCID_MAIN_BYTES);
72 if (!retBool) {
73 PRINT_ERR("get encoded os syscap failed.");
74 return nullptr;
75 }
76 retBool = EncodePrivateSyscap(&priOutput, &priOutputLen);
77 if (!retBool) {
78 PRINT_ERR("get encoded private syscap failed.");
79 goto FREE_PRIOUTPUT;
80 }
81
82 osCapU32 = reinterpret_cast<uint32_t *>(osOutput);
83 for (size_t i = 0; i < PCID_MAIN_U32; i++) { // 2, header of pcid.sc
84 retError = sprintf_s(osCapArray[i], U32_TO_STR_MAX_LEN, "%u", osCapU32[i]);
85 if (retError == -1) {
86 PRINT_ERR("get uint32_t syscap string failed.");
87 goto FREE_PRIOUTPUT;
88 }
89 }
90
91 retBool = DecodePrivateSyscap(priOutput, &priCapArray, &priCapArrayCnt);
92 if (!retBool) {
93 PRINT_ERR("get encoded private syscap failed.");
94 goto FREE_PRICAP_ARRAY;
95 }
96
97 // calculate all string length
98 sumLen = 0;
99 for (size_t i = 0; i < PCID_MAIN_U32; i++) {
100 sumLen += strlen(osCapArray[i]);
101 }
102 for (int i = 0; i < priCapArrayCnt; i++) {
103 sumLen += strlen(*(priCapArray + i));
104 }
105 sumLen += (PCID_MAIN_U32 + priCapArrayCnt + 1); // split with ','
106
107 // splicing string
108 allSyscapBuffer = (char *)malloc(sumLen);
109 if (allSyscapBuffer == nullptr) {
110 PRINT_ERR("malloc failed!");
111 goto FREE_PRICAP_ARRAY;
112 }
113 err = memset_s(allSyscapBuffer, sumLen, 0, sumLen);
114 if (err != EOK) {
115 PRINT_ERR("memset failed!");
116 free(allSyscapBuffer);
117 allSyscapBuffer = nullptr;
118 goto FREE_PRICAP_ARRAY;
119 }
120 temp = *osCapArray;
121
122 for (size_t i = 1; i < PCID_MAIN_U32; i++) {
123 retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, osCapArray[i]);
124 if (retError == -1) {
125 PRINT_ERR("splicing os syscap string failed.");
126 free(allSyscapBuffer);
127 allSyscapBuffer = nullptr;
128 goto FREE_PRICAP_ARRAY;
129 }
130 temp = allSyscapBuffer;
131 }
132 for (int i = 0; i < priCapArrayCnt; i++) {
133 retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, *(priCapArray + i));
134 if (retError == -1) {
135 PRINT_ERR("splicing pri syscap string failed.");
136 free(allSyscapBuffer);
137 allSyscapBuffer = nullptr;
138 goto FREE_PRICAP_ARRAY;
139 }
140 temp = allSyscapBuffer;
141 }
142
143 FREE_PRICAP_ARRAY:
144 free(priCapArray);
145 FREE_PRIOUTPUT:
146 free(priOutput);
147
148 return allSyscapBuffer;
149 }
150
QuerySystemCapability(napi_env env,napi_callback_info info)151 napi_value QuerySystemCapability(napi_env env, napi_callback_info info)
152 {
153 GET_PARAMS(env, info, 1);
154 NAPI_ASSERT(env, argc <= 1, "too many parameters");
155 napi_value result = nullptr;
156
157 SystemCapabilityAsyncContext* asyncContext = new SystemCapabilityAsyncContext();
158
159 asyncContext->env = env;
160
161 napi_valuetype valueType = napi_undefined;
162 if (argc == 1) {
163 napi_typeof(env, argv[0], &valueType);
164 }
165 if (valueType == napi_function) {
166 napi_create_reference(env, argv[0], 1, &asyncContext->callbackRef);
167 }
168
169 if (asyncContext->callbackRef == nullptr) {
170 napi_create_promise(env, &asyncContext->deferred, &result);
171 } else {
172 napi_get_undefined(env, &result);
173 }
174
175 napi_value resource = nullptr;
176 napi_create_string_utf8(env, "napi_value QuerySystemCapability", NAPI_AUTO_LENGTH, &resource);
177
178 napi_create_async_work(
179 env, nullptr, resource,
180 [](napi_env env, void* data) {
181 SystemCapabilityAsyncContext *asyncContext = (SystemCapabilityAsyncContext *)data;
182 char *syscapStr = GetSystemCapability();
183 if (syscapStr != nullptr) {
184 asyncContext->value = syscapStr;
185 asyncContext->status = 0;
186 } else {
187 asyncContext->status = 1;
188 }
189 },
190 [](napi_env env, napi_status status, void* data) {
191 SystemCapabilityAsyncContext *asyncContext = (SystemCapabilityAsyncContext *)data;
192 napi_value result[2] = {nullptr, nullptr};
193 if (!asyncContext->status) {
194 napi_get_undefined(env, &result[0]);
195 napi_create_string_utf8(env, asyncContext->value, strlen(asyncContext->value), &result[1]); // ?
196 } else {
197 napi_value message = nullptr;
198 napi_create_string_utf8(env, "key does not exist", NAPI_AUTO_LENGTH, &message);
199 napi_create_error(env, nullptr, message, &result[0]);
200 napi_get_undefined(env, &result[1]);
201 }
202 if (asyncContext->deferred) {
203 if (!asyncContext->status) {
204 napi_resolve_deferred(env, asyncContext->deferred, result[1]);
205 } else {
206 napi_reject_deferred(env, asyncContext->deferred, result[0]);
207 }
208 } else {
209 napi_value callback = nullptr;
210 napi_value returnVal;
211 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
212 napi_call_function(env, nullptr, callback, 2, result, &returnVal); // 2, count of result
213 napi_delete_reference(env, asyncContext->callbackRef);
214 }
215 napi_delete_async_work(env, asyncContext->work);
216 delete asyncContext;
217 },
218 (void*)asyncContext, &asyncContext->work);
219 napi_queue_async_work(env, asyncContext->work);
220
221 return result;
222 }
223
QuerryExport(napi_env env,napi_value exports)224 napi_value QuerryExport(napi_env env, napi_value exports)
225 {
226 napi_property_descriptor desc[] = {
227 DECLARE_NAPI_FUNCTION("querySystemCapabilities", QuerySystemCapability),
228 };
229
230 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
231 return exports;
232 }
233 EXTERN_C_END
234
235 /*
236 * Module define
237 */
238 static napi_module g_systemCapabilityModule = {
239 .nm_version = 1,
240 .nm_flags = 0,
241 .nm_filename = nullptr,
242 .nm_register_func = QuerryExport,
243 .nm_modname = "systemCapability",
244 .nm_priv = nullptr,
245 .reserved = {nullptr},
246 };
247
248 /*
249 * Module register function
250 */
SystemCapabilityRegisterModule(void)251 extern "C" __attribute__((constructor)) void SystemCapabilityRegisterModule(void)
252 {
253 napi_module_register(&g_systemCapabilityModule);
254 }
255 }