• 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)155 static void GroupNodeFree(const HashNode *node)
156 {
157     InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
158     free(groupNode);
159 }
160 
InitServiceSpace(void)161 void InitServiceSpace(void)
162 {
163     if (g_initWorkspace.initFlags != 0) {
164         return;
165     }
166     HashInfo info = {
167         GroupNodeNodeCompare,
168         GroupNodeKeyCompare,
169         GroupNodeGetNodeHashCode,
170         GroupNodeGetKeyHashCode,
171         GroupNodeFree,
172         GROUP_HASHMAP_BUCKET
173     };
174     for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
175         int ret = OH_HashMapCreate(&g_initWorkspace.hashMap[i], &info);
176         if (ret != 0) {
177             INIT_LOGE("%s", "Failed to create hash map");
178         }
179     }
180 
181     for (int i = 0; i < NODE_TYPE_MAX; i++) {
182         g_initWorkspace.groupNodes[i] = NULL;
183     }
184     // get boot mode, set default mode
185     strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), BOOT_GROUP_DEFAULT);
186     char *data = ReadFileData(BOOT_CMD_LINE);
187     if (data != NULL) {
188         int ret = GetProcCmdlineValue(BOOT_GROUP_NAME, data,
189             g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr));
190         if (ret != 0) {
191             INIT_LOGV("Failed to get boot group");
192             if (GetBootModeFromMisc() == GROUP_CHARGE) {
193                 strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), "device.charge.group");
194             }
195         }
196         free(data);
197     }
198     INIT_LOGI("boot start %s", g_initWorkspace.groupModeStr);
199     g_initWorkspace.groupMode = GetBootGroupMode();
200     g_initWorkspace.initFlags = 1;
201 }
202 
InitParseGroupCfg(void)203 int InitParseGroupCfg(void)
204 {
205     char buffer[128] = {0}; // 128 buffer size
206     char *realPath = GetAbsolutePath(GROUP_DEFAULT_PATH,
207         g_initWorkspace.groupModeStr, buffer, sizeof(buffer));
208     INIT_ERROR_CHECK(realPath != NULL, return -1,
209         "Failed to get path for %s", g_initWorkspace.groupModeStr);
210     InitParseGroupCfg_(realPath);
211     InitGroupNode *groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
212     int level = 0;
213     while ((groupRoot != NULL) && (level < GROUP_IMPORT_MAX_LEVEL)) { // for more import
214         g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
215         InitImportGroupCfg_(groupRoot);
216         groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
217         level++;
218     }
219     InitFreeGroupNodes_(g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]);
220     g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
221     return 0;
222 }
223 
AddGroupNode(int type,const char * name)224 InitGroupNode *AddGroupNode(int type, const char *name)
225 {
226     INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
227     INIT_ERROR_CHECK(name != NULL, return NULL, "Invalid name");
228     InitGroupNode *groupNode = GetGroupNode(type, name);
229     if (groupNode != NULL) {
230         return groupNode;
231     }
232     INIT_LOGV("AddGroupNode type %d name %s", type, name);
233     uint32_t nameLen = (uint32_t)strlen(name);
234     groupNode = (InitGroupNode *)calloc(1, sizeof(InitGroupNode) + nameLen + 1);
235     INIT_ERROR_CHECK(groupNode != NULL, return NULL, "Failed to alloc for group %s", name);
236     int ret = memcpy_s(groupNode->name, nameLen + 1, name, nameLen + 1);
237     INIT_ERROR_CHECK(ret == 0, free(groupNode);
238         return NULL, "Failed to alloc for group %s", name);
239     groupNode->type = type;
240     groupNode->next = g_initWorkspace.groupNodes[type];
241     g_initWorkspace.groupNodes[type] = groupNode;
242 
243     if (type < NODE_TYPE_GROUPS) { // add hashmap
244         OH_HashMapAdd(g_initWorkspace.hashMap[type], &groupNode->hashNode);
245     }
246     return groupNode;
247 }
248 
GetGroupNode(int type,const char * name)249 InitGroupNode *GetGroupNode(int type, const char *name)
250 {
251     if (type >= NODE_TYPE_GROUPS) {
252         return NULL;
253     }
254     INIT_LOGV("GetGroupNode type %d name %s", type, name);
255     HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
256     if (node == NULL) {
257         return NULL;
258     }
259     return HASHMAP_ENTRY(node, InitGroupNode, hashNode);
260 }
261 
GetNextGroupNode(int type,const InitGroupNode * curr)262 InitGroupNode *GetNextGroupNode(int type, const InitGroupNode *curr)
263 {
264     INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
265     if (curr == NULL) {
266         return g_initWorkspace.groupNodes[type];
267     }
268     return curr->next;
269 }
270 
DelGroupNode(int type,const char * name)271 void DelGroupNode(int type, const char *name)
272 {
273     if (type >= NODE_TYPE_GROUPS) {
274         return;
275     }
276     INIT_LOGV("DelGroupNode type %d name %s", type, name);
277     OH_HashMapRemove(g_initWorkspace.hashMap[type], name);
278     InitGroupNode *groupNode = g_initWorkspace.groupNodes[type];
279     InitGroupNode *preNode = groupNode;
280     while (groupNode != NULL) {
281         if (strcmp(groupNode->name, name) != 0) {
282             preNode = groupNode;
283             groupNode = groupNode->next;
284             continue;
285         }
286         if (groupNode == g_initWorkspace.groupNodes[type]) {
287             g_initWorkspace.groupNodes[type] = groupNode->next;
288         } else {
289             preNode->next = groupNode->next;
290         }
291         free(groupNode);
292         break;
293     }
294 }
295 
CheckNodeValid(int type,const char * name)296 int CheckNodeValid(int type, const char *name)
297 {
298     if (type >= NODE_TYPE_GROUPS) {
299         return -1;
300     }
301     HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
302     if (node != NULL) {
303         INIT_LOGI("Found %s in %s group", name, type == NODE_TYPE_JOBS ? "job" : "service");
304         return 0;
305     }
306     if (g_initWorkspace.groupMode == GROUP_BOOT) {
307         // for boot start, can not start charger service
308         if (strcmp(name, "charger") == 0) {
309             return -1;
310         }
311         return 0;
312     }
313     return -1;
314 }
315 
GetGroupHashMap(int type)316 HashMapHandle GetGroupHashMap(int type)
317 {
318     if (type >= NODE_TYPE_GROUPS) {
319         return NULL;
320     }
321     return g_initWorkspace.hashMap[type];
322 }
323 
324 #ifdef STARTUP_INIT_TEST
GetInitWorkspace(void)325 InitWorkspace *GetInitWorkspace(void)
326 {
327     return &g_initWorkspace;
328 }
329 #endif