• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "init_group_manager.h"
16 
17 #include "init_jobs_internal.h"
18 #include "init_log.h"
19 #include "init_utils.h"
20 #include "securec.h"
21 #include "init_service_manager.h"
22 
23 static InitWorkspace g_initWorkspace = {0, 0, {0}, {0}, {0}};
GenerateHashCode(const char * key)24 int GenerateHashCode(const char *key)
25 {
26     int code = 0;
27     size_t keyLen = strlen(key);
28     for (size_t i = 0; i < keyLen; i++) {
29         code += key[i] - 'A';
30     }
31     return code;
32 }
33 
GetBootGroupMode(void)34 static int GetBootGroupMode(void)
35 {
36     static const char *groupModes[] = {
37         "device.boot.group",
38         "device.charge.group"
39     };
40     for (size_t i = 0; i < ARRAY_LENGTH(groupModes); i++) {
41         if (strcmp(g_initWorkspace.groupModeStr, groupModes[i]) == 0) {
42             return i;
43         }
44     }
45     return (int)GROUP_UNKNOW;
46 }
47 
ParseGroupCfgItem(cJSON * root,int type,const char * itemName)48 static int ParseGroupCfgItem(cJSON *root, int type, const char *itemName)
49 {
50     int itemNumber = 0;
51     cJSON *json = GetArrayItem(root, &itemNumber, itemName);
52     if (json == NULL) {
53         return 0;
54     }
55 
56     for (int i = 0; i < itemNumber; ++i) {
57         cJSON *item = cJSON_GetArrayItem(json, i);
58         char *strValue = cJSON_GetStringValue(item);
59         if (strValue != NULL) {
60             AddGroupNode(type, strValue);
61         }
62     }
63     return 0;
64 }
65 
InitParseGroupCfg_(const char * groupCfg)66 static int InitParseGroupCfg_(const char *groupCfg)
67 {
68     INIT_LOGI("Parse group config %s", groupCfg);
69     char *fileBuf = ReadFileData(groupCfg);
70     INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", groupCfg);
71     cJSON *fileRoot = cJSON_Parse(fileBuf);
72     INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
73         return -1, "Failed to parse json file %s", groupCfg);
74 
75     ParseGroupCfgItem(fileRoot, NODE_TYPE_JOBS, "jobs");
76     ParseGroupCfgItem(fileRoot, NODE_TYPE_SERVICES, "services");
77     ParseGroupCfgItem(fileRoot, NODE_TYPE_GROUPS, "groups");
78     cJSON_Delete(fileRoot);
79     free(fileBuf);
80     return 0;
81 }
82 
InitImportGroupCfg_(InitGroupNode * groupRoot)83 static int InitImportGroupCfg_(InitGroupNode *groupRoot)
84 {
85     InitGroupNode *groupNode = groupRoot;
86     while (groupNode != NULL) {
87         groupRoot = groupNode->next;
88         InitParseGroupCfg_(groupNode->name);
89         free(groupNode);
90         groupNode = groupRoot;
91     }
92     return 0;
93 }
94 
InitFreeGroupNodes_(InitGroupNode * groupRoot)95 static int InitFreeGroupNodes_(InitGroupNode *groupRoot)
96 {
97     InitGroupNode *groupNode = groupRoot;
98     while (groupNode != NULL) {
99         groupRoot = groupNode->next;
100         if (groupNode->type < NODE_TYPE_GROUPS) { // remove from hashmap
101             OH_HashMapRemove(g_initWorkspace.hashMap[groupNode->type], groupNode->name);
102         }
103         free(groupNode);
104         groupNode = groupRoot;
105     }
106     return 0;
107 }
108 
GetAbsolutePath(const char * path,const char * cfgName,char * buffer,uint32_t buffSize)109 static char *GetAbsolutePath(const char *path, const char *cfgName, char *buffer, uint32_t buffSize)
110 {
111     int len = 0;
112     size_t cfgNameLen = strlen(cfgName);
113     int ext = 0;
114     if (cfgNameLen > strlen(".cfg")) {
115         ext = strcmp(cfgName + cfgNameLen - strlen(".cfg"), ".cfg") == 0;
116     }
117     if (cfgName[0] != '/') {
118         const char *format = ((ext != 0) ? "%s/%s" : "%s/%s.cfg");
119         len = sprintf_s(buffer, buffSize, format, path, cfgName);
120     } else {
121         const char *format = ((ext != 0) ? "%s" : "%s.cfg");
122         len = sprintf_s(buffer, buffSize, format, cfgName);
123     }
124     if (len <= 0) {
125         return NULL;
126     }
127     buffer[len] = '\0';
128     return buffer;
129 }
130 
GroupNodeNodeCompare(const HashNode * node1,const HashNode * node2)131 static int GroupNodeNodeCompare(const HashNode *node1, const HashNode *node2)
132 {
133     InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode);
134     InitGroupNode *groupNode2 = HASHMAP_ENTRY(node2, InitGroupNode, hashNode);
135     return strcmp(groupNode1->name, groupNode2->name);
136 }
137 
GroupNodeKeyCompare(const HashNode * node1,const void * key)138 static int GroupNodeKeyCompare(const HashNode *node1, const void *key)
139 {
140     InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode);
141     return strcmp(groupNode1->name, (char *)key);
142 }
143 
GroupNodeGetKeyHashCode(const void * key)144 static int GroupNodeGetKeyHashCode(const void *key)
145 {
146     return GenerateHashCode((const char *)key);
147 }
148 
GroupNodeGetNodeHashCode(const HashNode * node)149 static int GroupNodeGetNodeHashCode(const HashNode *node)
150 {
151     InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
152     return GenerateHashCode((const char *)groupNode->name);
153 }
154 
GroupNodeFree(const HashNode * node,void * context)155 static void GroupNodeFree(const HashNode *node, void *context)
156 {
157     InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
158     if (groupNode->type == NODE_TYPE_SERVICES) {
159         ReleaseService(groupNode->data.service);
160         groupNode->data.service = NULL;
161     } else if (groupNode->type == NODE_TYPE_CMDS) {
162         ReleaseCmd(groupNode->data.cmd);
163         groupNode->data.cmd = NULL;
164     }
165     free(groupNode);
166 }
167 
InitServiceSpace(void)168 void InitServiceSpace(void)
169 {
170     if (g_initWorkspace.initFlags != 0) {
171         return;
172     }
173     HashInfo info = {
174         GroupNodeNodeCompare,
175         GroupNodeKeyCompare,
176         GroupNodeGetNodeHashCode,
177         GroupNodeGetKeyHashCode,
178         GroupNodeFree,
179         GROUP_HASHMAP_BUCKET
180     };
181     for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
182         int ret = OH_HashMapCreate(&g_initWorkspace.hashMap[i], &info);
183         if (ret != 0) {
184             INIT_LOGE("%s", "Failed to create hash map");
185         }
186     }
187 
188     for (int i = 0; i < NODE_TYPE_MAX; i++) {
189         g_initWorkspace.groupNodes[i] = NULL;
190     }
191     // get boot mode, set default mode
192     strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), BOOT_GROUP_DEFAULT);
193     int ret = GetParameterFromCmdLine(BOOT_GROUP_NAME,
194         g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr));
195     if (ret != 0) {
196         INIT_LOGV("Failed to get boot group");
197         if (GetBootModeFromMisc() == GROUP_CHARGE) {
198             strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), "device.charge.group");
199         }
200     }
201     INIT_LOGI("boot start %s", g_initWorkspace.groupModeStr);
202     g_initWorkspace.groupMode = GetBootGroupMode();
203     g_initWorkspace.initFlags = 1;
204 }
205 
InitParseGroupCfg(void)206 int InitParseGroupCfg(void)
207 {
208     char buffer[128] = {0}; // 128 buffer size
209     char *realPath = GetAbsolutePath(GROUP_DEFAULT_PATH,
210         g_initWorkspace.groupModeStr, buffer, sizeof(buffer));
211     INIT_ERROR_CHECK(realPath != NULL, return -1,
212         "Failed to get path for %s", g_initWorkspace.groupModeStr);
213     InitParseGroupCfg_(realPath);
214     InitGroupNode *groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
215     int level = 0;
216     while ((groupRoot != NULL) && (level < GROUP_IMPORT_MAX_LEVEL)) { // for more import
217         g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
218         InitImportGroupCfg_(groupRoot);
219         groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
220         level++;
221     }
222     InitFreeGroupNodes_(g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]);
223     g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
224     return 0;
225 }
226 
AddGroupNode(int type,const char * name)227 InitGroupNode *AddGroupNode(int type, const char *name)
228 {
229     INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
230     INIT_ERROR_CHECK(name != NULL, return NULL, "Invalid name");
231     InitGroupNode *groupNode = GetGroupNode(type, name);
232     if (groupNode != NULL) {
233         return groupNode;
234     }
235     INIT_LOGV("AddGroupNode type %d name %s", type, name);
236     uint32_t nameLen = (uint32_t)strlen(name);
237     groupNode = (InitGroupNode *)calloc(1, sizeof(InitGroupNode) + nameLen + 1);
238     INIT_ERROR_CHECK(groupNode != NULL, return NULL, "Failed to alloc for group %s", name);
239     int ret = memcpy_s(groupNode->name, nameLen + 1, name, nameLen + 1);
240     INIT_ERROR_CHECK(ret == 0, free(groupNode);
241         return NULL, "Failed to alloc for group %s", name);
242     groupNode->type = type;
243     groupNode->next = g_initWorkspace.groupNodes[type];
244     g_initWorkspace.groupNodes[type] = groupNode;
245 
246     if (type < NODE_TYPE_GROUPS) { // add hashmap
247         OH_HashMapAdd(g_initWorkspace.hashMap[type], &groupNode->hashNode);
248     }
249     return groupNode;
250 }
251 
GetGroupNode(int type,const char * name)252 InitGroupNode *GetGroupNode(int type, const char *name)
253 {
254     if (type >= NODE_TYPE_GROUPS) {
255         return NULL;
256     }
257     HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
258     if (node == NULL) {
259         return NULL;
260     }
261     return HASHMAP_ENTRY(node, InitGroupNode, hashNode);
262 }
263 
GetNextGroupNode(int type,const InitGroupNode * curr)264 InitGroupNode *GetNextGroupNode(int type, const InitGroupNode *curr)
265 {
266     INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
267     if (curr == NULL) {
268         return g_initWorkspace.groupNodes[type];
269     }
270     return curr->next;
271 }
272 
DelGroupNode(int type,const char * name)273 void DelGroupNode(int type, const char *name)
274 {
275     if (type >= NODE_TYPE_GROUPS) {
276         return;
277     }
278     INIT_LOGV("DelGroupNode type %d name %s", type, name);
279     OH_HashMapRemove(g_initWorkspace.hashMap[type], name);
280     InitGroupNode *groupNode = g_initWorkspace.groupNodes[type];
281     InitGroupNode *preNode = groupNode;
282     while (groupNode != NULL) {
283         if (strcmp(groupNode->name, name) != 0) {
284             preNode = groupNode;
285             groupNode = groupNode->next;
286             continue;
287         }
288         if (groupNode == g_initWorkspace.groupNodes[type]) {
289             g_initWorkspace.groupNodes[type] = groupNode->next;
290         } else {
291             preNode->next = groupNode->next;
292         }
293         free(groupNode);
294         break;
295     }
296 }
297 
CheckNodeValid(int type,const char * name)298 int CheckNodeValid(int type, const char *name)
299 {
300     if (type >= NODE_TYPE_GROUPS) {
301         return -1;
302     }
303     HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
304     if (node != NULL) {
305         INIT_LOGV("Found %s in %s group", name, type == NODE_TYPE_JOBS ? "job" : "service");
306         return 0;
307     }
308     if (g_initWorkspace.groupMode == GROUP_BOOT) {
309         // for boot start, can not start charger service
310         if (strcmp(name, "charger") == 0) {
311             return -1;
312         }
313         return 0;
314     }
315     return -1;
316 }
317 
GetGroupHashMap(int type)318 HashMapHandle GetGroupHashMap(int type)
319 {
320     if (type >= NODE_TYPE_GROUPS) {
321         return NULL;
322     }
323     return g_initWorkspace.hashMap[type];
324 }
325 
CloseServiceSpace(void)326 void CloseServiceSpace(void)
327 {
328     if (g_initWorkspace.initFlags == 0) {
329         return;
330     }
331     for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
332         if (g_initWorkspace.hashMap[i] != NULL) {
333             HashMapHandle handle = g_initWorkspace.hashMap[i];
334             g_initWorkspace.hashMap[i] = NULL;
335             OH_HashMapDestory(handle, NULL);
336         }
337     }
338     g_initWorkspace.initFlags = 0;
339 }
340 
ReleaseCmd(PluginCmd * cmd)341 void ReleaseCmd(PluginCmd *cmd)
342 {
343     if (cmd == NULL) {
344         return;
345     }
346     ListNode *node = cmd->cmdExecutor.next;
347     while (node != &cmd->cmdExecutor) {
348         PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
349         OH_ListRemove(&cmdExec->node);
350         free(cmdExec);
351         node = cmd->cmdExecutor.next;
352     }
353     free(cmd);
354 }
355 
356 #ifdef STARTUP_INIT_TEST
GetInitWorkspace(void)357 InitWorkspace *GetInitWorkspace(void)
358 {
359     return &g_initWorkspace;
360 }
361 #endif