• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }