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