1bae44755Sopenharmony_ci/* 2bae44755Sopenharmony_ci * Copyright (C) 2022-2022 Huawei Device Co., Ltd. 3bae44755Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4bae44755Sopenharmony_ci * you may not use this file except in compliance with the License. 5bae44755Sopenharmony_ci * You may obtain a copy of the License at 6bae44755Sopenharmony_ci * 7bae44755Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8bae44755Sopenharmony_ci * 9bae44755Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10bae44755Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11bae44755Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12bae44755Sopenharmony_ci * See the License for the specific language governing permissions and 13bae44755Sopenharmony_ci * limitations under the License. 14bae44755Sopenharmony_ci */ 15bae44755Sopenharmony_ci 16bae44755Sopenharmony_ci#include <cstdint> 17bae44755Sopenharmony_ci#include <cstring> 18bae44755Sopenharmony_ci#include <cstdlib> 19bae44755Sopenharmony_ci#include <securec.h> 20bae44755Sopenharmony_ci#include "napi/native_api.h" 21bae44755Sopenharmony_ci#include "napi/native_node_api.h" 22bae44755Sopenharmony_ci#include "syscap_interface.h" 23bae44755Sopenharmony_ci#include "context_tool.h" 24bae44755Sopenharmony_ci 25bae44755Sopenharmony_cinamespace OHOS { 26bae44755Sopenharmony_ciEXTERN_C_START 27bae44755Sopenharmony_ciconstexpr size_t OS_SYSCAP_U32_NUM = 30; 28bae44755Sopenharmony_ciconstexpr size_t PCID_MAIN_U32 = OS_SYSCAP_U32_NUM + 2; 29bae44755Sopenharmony_ciconstexpr size_t U32_TO_STR_MAX_LEN = 11; 30bae44755Sopenharmony_ciconstexpr size_t KEY_BUFFER_SIZE = 32; 31bae44755Sopenharmony_ci 32bae44755Sopenharmony_ci#define GET_PARAMS(env, info, num) \ 33bae44755Sopenharmony_ci size_t argc = num; \ 34bae44755Sopenharmony_ci napi_value argv[num] = {0}; \ 35bae44755Sopenharmony_ci napi_value thisVar = nullptr; \ 36bae44755Sopenharmony_ci void *data; \ 37bae44755Sopenharmony_ci napi_get_cb_info(env, info, &argc, argv, &thisVar, &data) 38bae44755Sopenharmony_ci 39bae44755Sopenharmony_ci// Async Function Set 40bae44755Sopenharmony_cistruct SystemCapabilityAsyncContext { 41bae44755Sopenharmony_ci napi_env env = nullptr; 42bae44755Sopenharmony_ci napi_async_work work = nullptr; 43bae44755Sopenharmony_ci char key[KEY_BUFFER_SIZE] = { 0 }; 44bae44755Sopenharmony_ci size_t keyLen = 0; 45bae44755Sopenharmony_ci char *value = nullptr; 46bae44755Sopenharmony_ci size_t valueLen = 0; 47bae44755Sopenharmony_ci napi_deferred deferred = nullptr; 48bae44755Sopenharmony_ci napi_ref callbackRef = nullptr; 49bae44755Sopenharmony_ci 50bae44755Sopenharmony_ci int status = 0; 51bae44755Sopenharmony_ci}; 52bae44755Sopenharmony_ci 53bae44755Sopenharmony_cistatic char* CalculateAllStringLength(char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN], 54bae44755Sopenharmony_ci char (*priCapArray)[SINGLE_SYSCAP_LEN], bool retBool, int priCapArrayCnt) 55bae44755Sopenharmony_ci{ 56bae44755Sopenharmony_ci errno_t err = EOK; 57bae44755Sopenharmony_ci char *temp = nullptr; 58bae44755Sopenharmony_ci int retError; 59bae44755Sopenharmony_ci int sumLen = 0; 60bae44755Sopenharmony_ci char *allSyscapBuffer = nullptr; 61bae44755Sopenharmony_ci 62bae44755Sopenharmony_ci if (!retBool) { 63bae44755Sopenharmony_ci PRINT_ERR("get encoded private syscap failed."); 64bae44755Sopenharmony_ci return allSyscapBuffer; 65bae44755Sopenharmony_ci } 66bae44755Sopenharmony_ci 67bae44755Sopenharmony_ci for (size_t i = 0; i < PCID_MAIN_U32; i++) { 68bae44755Sopenharmony_ci sumLen += strlen(osCapArray[i]); 69bae44755Sopenharmony_ci } 70bae44755Sopenharmony_ci for (int i = 0; i < priCapArrayCnt; i++) { 71bae44755Sopenharmony_ci sumLen += strlen(*(priCapArray + i)); 72bae44755Sopenharmony_ci } 73bae44755Sopenharmony_ci sumLen += (PCID_MAIN_U32 + priCapArrayCnt + 1); // split with ',' 74bae44755Sopenharmony_ci 75bae44755Sopenharmony_ci // splicing string 76bae44755Sopenharmony_ci allSyscapBuffer = (char *)malloc(sumLen); 77bae44755Sopenharmony_ci if (allSyscapBuffer == nullptr) { 78bae44755Sopenharmony_ci PRINT_ERR("malloc failed!"); 79bae44755Sopenharmony_ci return allSyscapBuffer; 80bae44755Sopenharmony_ci } 81bae44755Sopenharmony_ci err = memset_s(allSyscapBuffer, sumLen, 0, sumLen); 82bae44755Sopenharmony_ci if (err != EOK) { 83bae44755Sopenharmony_ci PRINT_ERR("memset failed!"); 84bae44755Sopenharmony_ci free(allSyscapBuffer); 85bae44755Sopenharmony_ci return nullptr; 86bae44755Sopenharmony_ci } 87bae44755Sopenharmony_ci temp = *osCapArray; 88bae44755Sopenharmony_ci 89bae44755Sopenharmony_ci for (size_t i = 1; i < PCID_MAIN_U32; i++) { 90bae44755Sopenharmony_ci retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, osCapArray[i]); 91bae44755Sopenharmony_ci if (retError == -1) { 92bae44755Sopenharmony_ci PRINT_ERR("splicing os syscap string failed."); 93bae44755Sopenharmony_ci free(allSyscapBuffer); 94bae44755Sopenharmony_ci return nullptr; 95bae44755Sopenharmony_ci } 96bae44755Sopenharmony_ci temp = allSyscapBuffer; 97bae44755Sopenharmony_ci } 98bae44755Sopenharmony_ci for (int i = 0; i < priCapArrayCnt; i++) { 99bae44755Sopenharmony_ci retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, *(priCapArray + i)); 100bae44755Sopenharmony_ci if (retError == -1) { 101bae44755Sopenharmony_ci PRINT_ERR("splicing pri syscap string failed."); 102bae44755Sopenharmony_ci free(allSyscapBuffer); 103bae44755Sopenharmony_ci return nullptr; 104bae44755Sopenharmony_ci } 105bae44755Sopenharmony_ci temp = allSyscapBuffer; 106bae44755Sopenharmony_ci } 107bae44755Sopenharmony_ci return allSyscapBuffer; 108bae44755Sopenharmony_ci} 109bae44755Sopenharmony_ci 110bae44755Sopenharmony_cistatic char* GetSystemCapability() 111bae44755Sopenharmony_ci{ 112bae44755Sopenharmony_ci bool retBool; 113bae44755Sopenharmony_ci int retError, priOutputLen, priCapArrayCnt; 114bae44755Sopenharmony_ci char osOutput[SINGLE_SYSCAP_LEN] = {}; 115bae44755Sopenharmony_ci 116bae44755Sopenharmony_ci uint32_t *osCapU32 = nullptr; 117bae44755Sopenharmony_ci char *priOutput = nullptr; 118bae44755Sopenharmony_ci 119bae44755Sopenharmony_ci char *allSyscapBuffer = nullptr; 120bae44755Sopenharmony_ci char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN] = {}; 121bae44755Sopenharmony_ci char (*priCapArray)[SINGLE_SYSCAP_LEN] = nullptr; 122bae44755Sopenharmony_ci 123bae44755Sopenharmony_ci retBool = EncodeOsSyscap(osOutput, PCID_MAIN_BYTES); 124bae44755Sopenharmony_ci if (!retBool) { 125bae44755Sopenharmony_ci PRINT_ERR("get encoded os syscap failed."); 126bae44755Sopenharmony_ci return nullptr; 127bae44755Sopenharmony_ci } 128bae44755Sopenharmony_ci retBool = EncodePrivateSyscap(&priOutput, &priOutputLen); 129bae44755Sopenharmony_ci if (!retBool) { 130bae44755Sopenharmony_ci PRINT_ERR("get encoded private syscap failed."); 131bae44755Sopenharmony_ci goto FREE_PRIOUTPUT; 132bae44755Sopenharmony_ci } 133bae44755Sopenharmony_ci 134bae44755Sopenharmony_ci osCapU32 = reinterpret_cast<uint32_t *>(osOutput); 135bae44755Sopenharmony_ci for (size_t i = 0; i < PCID_MAIN_U32; i++) { // 2, header of pcid.sc 136bae44755Sopenharmony_ci retError = sprintf_s(osCapArray[i], U32_TO_STR_MAX_LEN, "%u", osCapU32[i]); 137bae44755Sopenharmony_ci if (retError == -1) { 138bae44755Sopenharmony_ci PRINT_ERR("get uint32_t syscap string failed."); 139bae44755Sopenharmony_ci goto FREE_PRIOUTPUT; 140bae44755Sopenharmony_ci } 141bae44755Sopenharmony_ci } 142bae44755Sopenharmony_ci retBool = DecodePrivateSyscap(priOutput, &priCapArray, &priCapArrayCnt); 143bae44755Sopenharmony_ci allSyscapBuffer = CalculateAllStringLength(osCapArray, priCapArray, retBool, priCapArrayCnt); 144bae44755Sopenharmony_ci free(priCapArray); 145bae44755Sopenharmony_ci 146bae44755Sopenharmony_ciFREE_PRIOUTPUT: 147bae44755Sopenharmony_ci free(priOutput); 148bae44755Sopenharmony_ci 149bae44755Sopenharmony_ci return allSyscapBuffer; 150bae44755Sopenharmony_ci} 151bae44755Sopenharmony_ci 152bae44755Sopenharmony_cinapi_value PreHandleSystemCapability( 153bae44755Sopenharmony_ci napi_env env, napi_callback_info info, SystemCapabilityAsyncContext *asyncContext) 154bae44755Sopenharmony_ci{ 155bae44755Sopenharmony_ci GET_PARAMS(env, info, 1); 156bae44755Sopenharmony_ci NAPI_ASSERT(env, argc <= 1, "too many parameters"); 157bae44755Sopenharmony_ci napi_value result = nullptr; 158bae44755Sopenharmony_ci 159bae44755Sopenharmony_ci asyncContext->env = env; 160bae44755Sopenharmony_ci 161bae44755Sopenharmony_ci napi_valuetype valueType = napi_undefined; 162bae44755Sopenharmony_ci if (argc == 1) { 163bae44755Sopenharmony_ci napi_typeof(env, argv[0], &valueType); 164bae44755Sopenharmony_ci } 165bae44755Sopenharmony_ci if (valueType == napi_function) { 166bae44755Sopenharmony_ci napi_create_reference(env, argv[0], 1, &asyncContext->callbackRef); 167bae44755Sopenharmony_ci } 168bae44755Sopenharmony_ci 169bae44755Sopenharmony_ci if (asyncContext->callbackRef == nullptr) { 170bae44755Sopenharmony_ci napi_create_promise(env, &asyncContext->deferred, &result); 171bae44755Sopenharmony_ci } else { 172bae44755Sopenharmony_ci napi_get_undefined(env, &result); 173bae44755Sopenharmony_ci } 174bae44755Sopenharmony_ci return result; 175bae44755Sopenharmony_ci} 176bae44755Sopenharmony_ci 177bae44755Sopenharmony_cinapi_value QuerySystemCapability(napi_env env, napi_callback_info info) 178bae44755Sopenharmony_ci{ 179bae44755Sopenharmony_ci SystemCapabilityAsyncContext *asyncContext = new SystemCapabilityAsyncContext(); 180bae44755Sopenharmony_ci napi_value result = PreHandleSystemCapability(env, info, asyncContext); 181bae44755Sopenharmony_ci napi_value resource = nullptr; 182bae44755Sopenharmony_ci napi_create_string_utf8(env, "napi_value QuerySystemCapability", NAPI_AUTO_LENGTH, &resource); 183bae44755Sopenharmony_ci 184bae44755Sopenharmony_ci napi_create_async_work( 185bae44755Sopenharmony_ci env, nullptr, resource, 186bae44755Sopenharmony_ci [](napi_env env, void* data) { 187bae44755Sopenharmony_ci SystemCapabilityAsyncContext *asyncContext = (SystemCapabilityAsyncContext *)data; 188bae44755Sopenharmony_ci char *syscapStr = GetSystemCapability(); 189bae44755Sopenharmony_ci if (syscapStr != nullptr) { 190bae44755Sopenharmony_ci asyncContext->value = syscapStr; 191bae44755Sopenharmony_ci asyncContext->status = 0; 192bae44755Sopenharmony_ci } else { 193bae44755Sopenharmony_ci asyncContext->status = 1; 194bae44755Sopenharmony_ci } 195bae44755Sopenharmony_ci }, 196bae44755Sopenharmony_ci [](napi_env env, napi_status status, void* data) { 197bae44755Sopenharmony_ci SystemCapabilityAsyncContext *asyncContext = (SystemCapabilityAsyncContext *)data; 198bae44755Sopenharmony_ci napi_value result[2] = {nullptr, nullptr}; 199bae44755Sopenharmony_ci if (!asyncContext->status) { 200bae44755Sopenharmony_ci napi_get_undefined(env, &result[0]); 201bae44755Sopenharmony_ci napi_create_string_utf8(env, asyncContext->value, strlen(asyncContext->value), &result[1]); // ? 202bae44755Sopenharmony_ci } else { 203bae44755Sopenharmony_ci napi_value message = nullptr; 204bae44755Sopenharmony_ci napi_create_string_utf8(env, "key does not exist", NAPI_AUTO_LENGTH, &message); 205bae44755Sopenharmony_ci napi_create_error(env, nullptr, message, &result[0]); 206bae44755Sopenharmony_ci napi_get_undefined(env, &result[1]); 207bae44755Sopenharmony_ci } 208bae44755Sopenharmony_ci if (asyncContext->deferred) { 209bae44755Sopenharmony_ci if (!asyncContext->status) { 210bae44755Sopenharmony_ci napi_resolve_deferred(env, asyncContext->deferred, result[1]); 211bae44755Sopenharmony_ci } else { 212bae44755Sopenharmony_ci napi_reject_deferred(env, asyncContext->deferred, result[0]); 213bae44755Sopenharmony_ci } 214bae44755Sopenharmony_ci } else { 215bae44755Sopenharmony_ci napi_value callback = nullptr; 216bae44755Sopenharmony_ci napi_value returnVal; 217bae44755Sopenharmony_ci napi_get_reference_value(env, asyncContext->callbackRef, &callback); 218bae44755Sopenharmony_ci napi_call_function(env, nullptr, callback, 2, result, &returnVal); // 2, count of result 219bae44755Sopenharmony_ci napi_delete_reference(env, asyncContext->callbackRef); 220bae44755Sopenharmony_ci } 221bae44755Sopenharmony_ci napi_delete_async_work(env, asyncContext->work); 222bae44755Sopenharmony_ci delete asyncContext; 223bae44755Sopenharmony_ci }, 224bae44755Sopenharmony_ci (void*)asyncContext, &asyncContext->work); 225bae44755Sopenharmony_ci napi_queue_async_work(env, asyncContext->work); 226bae44755Sopenharmony_ci 227bae44755Sopenharmony_ci return result; 228bae44755Sopenharmony_ci} 229bae44755Sopenharmony_ci 230bae44755Sopenharmony_cinapi_value QuerryExport(napi_env env, napi_value exports) 231bae44755Sopenharmony_ci{ 232bae44755Sopenharmony_ci napi_property_descriptor desc[] = { 233bae44755Sopenharmony_ci DECLARE_NAPI_FUNCTION("querySystemCapabilities", QuerySystemCapability), 234bae44755Sopenharmony_ci }; 235bae44755Sopenharmony_ci 236bae44755Sopenharmony_ci NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 237bae44755Sopenharmony_ci return exports; 238bae44755Sopenharmony_ci} 239bae44755Sopenharmony_ciEXTERN_C_END 240bae44755Sopenharmony_ci 241bae44755Sopenharmony_ci/* 242bae44755Sopenharmony_ci * Module define 243bae44755Sopenharmony_ci */ 244bae44755Sopenharmony_cistatic napi_module g_systemCapabilityModule = { 245bae44755Sopenharmony_ci .nm_version = 1, 246bae44755Sopenharmony_ci .nm_flags = 0, 247bae44755Sopenharmony_ci .nm_filename = nullptr, 248bae44755Sopenharmony_ci .nm_register_func = QuerryExport, 249bae44755Sopenharmony_ci .nm_modname = "systemCapability", 250bae44755Sopenharmony_ci .nm_priv = nullptr, 251bae44755Sopenharmony_ci .reserved = {nullptr}, 252bae44755Sopenharmony_ci}; 253bae44755Sopenharmony_ci 254bae44755Sopenharmony_ci/* 255bae44755Sopenharmony_ci * Module register function 256bae44755Sopenharmony_ci */ 257bae44755Sopenharmony_ciextern "C" __attribute__((constructor)) void SystemCapabilityRegisterModule(void) 258bae44755Sopenharmony_ci{ 259bae44755Sopenharmony_ci napi_module_register(&g_systemCapabilityModule); 260bae44755Sopenharmony_ci} 261bae44755Sopenharmony_ci}