1 /*
2 * Copyright (c) 2025 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 #include "ohos.systemCapability.proj.hpp"
16 #include "ohos.systemCapability.impl.hpp"
17 #include "taihe/runtime.hpp"
18 #include "stdexcept"
19 #include <cstdint>
20 #include <cstring>
21 #include <cstdlib>
22 #include <securec.h>
23 #include "syscap_interface.h"
24 #include "context_tool.h"
25
26 using namespace taihe;
27
28 namespace {
29 // To be implemented.
30 constexpr size_t OS_SYSCAP_U32_NUM = 30;
31 constexpr size_t PCID_MAIN_U32 = OS_SYSCAP_U32_NUM + 2;
32 constexpr size_t U32_TO_STR_MAX_LEN = 11;
33 constexpr size_t KEY_BUFFER_SIZE = 32;
34
35 struct SystemCapabilityAsyncContext {
36 char key[KEY_BUFFER_SIZE] = { 0 };
37 size_t keyLen = 0;
38 char *value = nullptr;
39 size_t valueLen = 0;
40 int status = 0;
41 };
42
CalculateAllStringLength(char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN],char (* priCapArray)[SINGLE_SYSCAP_LEN],bool retBool,int priCapArrayCnt)43 static char* CalculateAllStringLength(char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN],
44 char (*priCapArray)[SINGLE_SYSCAP_LEN], bool retBool, int priCapArrayCnt)
45 {
46 errno_t err = EOK;
47 char *temp = nullptr;
48 int retError;
49 int sumLen = 0;
50 char *allSyscapBuffer = nullptr;
51
52 if (!retBool) {
53 PRINT_ERR("get encoded private syscap failed.");
54 return allSyscapBuffer;
55 }
56
57 for (size_t i = 0; i < PCID_MAIN_U32; i++) {
58 sumLen += strlen(osCapArray[i]);
59 }
60 for (int i = 0; i < priCapArrayCnt; i++) {
61 sumLen += strlen(*(priCapArray + i));
62 }
63 sumLen += (PCID_MAIN_U32 + priCapArrayCnt + 1); // split with ','
64
65 // splicing string
66 allSyscapBuffer = (char *)malloc(sumLen);
67 if (allSyscapBuffer == nullptr) {
68 PRINT_ERR("malloc failed!");
69 return allSyscapBuffer;
70 }
71 err = memset_s(allSyscapBuffer, sumLen, 0, sumLen);
72 if (err != EOK) {
73 PRINT_ERR("memset failed!");
74 free(allSyscapBuffer);
75 return nullptr;
76 }
77 temp = *osCapArray;
78
79 for (size_t i = 1; i < PCID_MAIN_U32; i++) {
80 retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, osCapArray[i]);
81 if (retError == -1) {
82 PRINT_ERR("splicing os syscap string failed.");
83 free(allSyscapBuffer);
84 return nullptr;
85 }
86 temp = allSyscapBuffer;
87 }
88 for (int i = 0; i < priCapArrayCnt; i++) {
89 retError = sprintf_s(allSyscapBuffer, sumLen, "%s,%s", temp, *(priCapArray + i));
90 if (retError == -1) {
91 PRINT_ERR("splicing pri syscap string failed.");
92 free(allSyscapBuffer);
93 return nullptr;
94 }
95 temp = allSyscapBuffer;
96 }
97 return allSyscapBuffer;
98 }
99
GetSystemCapability()100 static char* GetSystemCapability()
101 {
102 bool retBool;
103 int retError;
104 int priOutputLen;
105 int priCapArrayCnt;
106 char osOutput[SINGLE_SYSCAP_LEN] = {};
107
108 uint32_t *osCapU32 = nullptr;
109 char *priOutput = nullptr;
110
111 char *allSyscapBuffer = nullptr;
112 char osCapArray[PCID_MAIN_U32][U32_TO_STR_MAX_LEN] = {};
113 char (*priCapArray)[SINGLE_SYSCAP_LEN] = nullptr;
114
115 retBool = EncodeOsSyscap(osOutput, PCID_MAIN_BYTES);
116 if (!retBool) {
117 PRINT_ERR("get encoded os syscap failed.");
118 return nullptr;
119 }
120 retBool = EncodePrivateSyscap(&priOutput, &priOutputLen);
121 if (!retBool) {
122 PRINT_ERR("get encoded private syscap failed.");
123 goto FREE_PRIOUTPUT;
124 }
125
126 osCapU32 = reinterpret_cast<uint32_t *>(osOutput);
127 for (size_t i = 0; i < PCID_MAIN_U32; i++) { // 2, header of pcid.sc
128 retError = sprintf_s(osCapArray[i], U32_TO_STR_MAX_LEN, "%u", osCapU32[i]);
129 if (retError == -1) {
130 PRINT_ERR("get uint32_t syscap string failed.");
131 goto FREE_PRIOUTPUT;
132 }
133 }
134 retBool = DecodePrivateSyscap(priOutput, &priCapArray, &priCapArrayCnt);
135 allSyscapBuffer = CalculateAllStringLength(osCapArray, priCapArray, retBool, priCapArrayCnt);
136 free(priCapArray);
137
138 FREE_PRIOUTPUT:
139 free(priOutput);
140
141 return allSyscapBuffer;
142 }
143
querySystemCapabilitie()144 string querySystemCapabilitie()
145 {
146 SystemCapabilityAsyncContext *asyncContext = new SystemCapabilityAsyncContext();
147 char *syscapStr = GetSystemCapability();
148 if (syscapStr != nullptr) {
149 asyncContext->value = syscapStr;
150 asyncContext->status = 0;
151 } else {
152 asyncContext->status = 1;
153 }
154 string value = "";
155 if (!asyncContext->status) {
156 value = asyncContext->value;
157 } else {
158 taihe::set_business_error(-1, "key does not exist");
159 }
160 delete asyncContext;
161 return value;
162 }
163 } // namespace
164
165 // Since these macros are auto-generate, lint will cause false positive.
166 // NOLINTBEGIN
167 TH_EXPORT_CPP_API_querySystemCapabilitie(querySystemCapabilitie);
168 // NOLINTEND
169