mirror of
https://gitee.com/openharmony/startup_init
synced 2024-11-24 00:30:12 +00:00
e18e0d7f07
Signed-off-by: cheng_jinsong <chengjinsong2@huawei.com>
361 lines
11 KiB
C
361 lines
11 KiB
C
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "init_group_manager.h"
|
|
|
|
#include "init_jobs_internal.h"
|
|
#include "init_log.h"
|
|
#include "init_utils.h"
|
|
#include "securec.h"
|
|
#include "init_service_manager.h"
|
|
|
|
static InitWorkspace g_initWorkspace = {0, 0, {0}, {0}, {0}};
|
|
int GenerateHashCode(const char *key)
|
|
{
|
|
int code = 0;
|
|
size_t keyLen = strlen(key);
|
|
for (size_t i = 0; i < keyLen; i++) {
|
|
code += key[i] - 'A';
|
|
}
|
|
return code;
|
|
}
|
|
|
|
static int GetBootGroupMode(void)
|
|
{
|
|
static const char *groupModes[] = {
|
|
"device.boot.group",
|
|
"device.charge.group"
|
|
};
|
|
for (size_t i = 0; i < ARRAY_LENGTH(groupModes); i++) {
|
|
if (strcmp(g_initWorkspace.groupModeStr, groupModes[i]) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
return (int)GROUP_UNKNOW;
|
|
}
|
|
|
|
static int ParseGroupCfgItem(cJSON *root, int type, const char *itemName)
|
|
{
|
|
int itemNumber = 0;
|
|
cJSON *json = GetArrayItem(root, &itemNumber, itemName);
|
|
if (json == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
for (int i = 0; i < itemNumber; ++i) {
|
|
cJSON *item = cJSON_GetArrayItem(json, i);
|
|
char *strValue = cJSON_GetStringValue(item);
|
|
if (strValue != NULL) {
|
|
AddGroupNode(type, strValue);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int InitParseGroupCfg_(const char *groupCfg)
|
|
{
|
|
INIT_LOGI("Parse group config %s", groupCfg);
|
|
char *fileBuf = ReadFileData(groupCfg);
|
|
INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", groupCfg);
|
|
cJSON *fileRoot = cJSON_Parse(fileBuf);
|
|
INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
|
|
return -1, "Failed to parse json file %s", groupCfg);
|
|
|
|
ParseGroupCfgItem(fileRoot, NODE_TYPE_JOBS, "jobs");
|
|
ParseGroupCfgItem(fileRoot, NODE_TYPE_SERVICES, "services");
|
|
ParseGroupCfgItem(fileRoot, NODE_TYPE_GROUPS, "groups");
|
|
cJSON_Delete(fileRoot);
|
|
free(fileBuf);
|
|
return 0;
|
|
}
|
|
|
|
static int InitImportGroupCfg_(InitGroupNode *groupRoot)
|
|
{
|
|
InitGroupNode *groupNode = groupRoot;
|
|
while (groupNode != NULL) {
|
|
groupRoot = groupNode->next;
|
|
InitParseGroupCfg_(groupNode->name);
|
|
free(groupNode);
|
|
groupNode = groupRoot;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int InitFreeGroupNodes_(InitGroupNode *groupRoot)
|
|
{
|
|
InitGroupNode *groupNode = groupRoot;
|
|
while (groupNode != NULL) {
|
|
groupRoot = groupNode->next;
|
|
if (groupNode->type < NODE_TYPE_GROUPS) { // remove from hashmap
|
|
OH_HashMapRemove(g_initWorkspace.hashMap[groupNode->type], groupNode->name);
|
|
}
|
|
free(groupNode);
|
|
groupNode = groupRoot;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static char *GetAbsolutePath(const char *path, const char *cfgName, char *buffer, uint32_t buffSize)
|
|
{
|
|
int len = 0;
|
|
size_t cfgNameLen = strlen(cfgName);
|
|
int ext = 0;
|
|
if (cfgNameLen > strlen(".cfg")) {
|
|
ext = strcmp(cfgName + cfgNameLen - strlen(".cfg"), ".cfg") == 0;
|
|
}
|
|
if (cfgName[0] != '/') {
|
|
const char *format = ((ext != 0) ? "%s/%s" : "%s/%s.cfg");
|
|
len = sprintf_s(buffer, buffSize, format, path, cfgName);
|
|
} else {
|
|
const char *format = ((ext != 0) ? "%s" : "%s.cfg");
|
|
len = sprintf_s(buffer, buffSize, format, cfgName);
|
|
}
|
|
if (len <= 0) {
|
|
return NULL;
|
|
}
|
|
buffer[len] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
static int GroupNodeNodeCompare(const HashNode *node1, const HashNode *node2)
|
|
{
|
|
InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode);
|
|
InitGroupNode *groupNode2 = HASHMAP_ENTRY(node2, InitGroupNode, hashNode);
|
|
return strcmp(groupNode1->name, groupNode2->name);
|
|
}
|
|
|
|
static int GroupNodeKeyCompare(const HashNode *node1, const void *key)
|
|
{
|
|
InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode);
|
|
return strcmp(groupNode1->name, (char *)key);
|
|
}
|
|
|
|
static int GroupNodeGetKeyHashCode(const void *key)
|
|
{
|
|
return GenerateHashCode((const char *)key);
|
|
}
|
|
|
|
static int GroupNodeGetNodeHashCode(const HashNode *node)
|
|
{
|
|
InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
|
|
return GenerateHashCode((const char *)groupNode->name);
|
|
}
|
|
|
|
static void GroupNodeFree(const HashNode *node, void *context)
|
|
{
|
|
InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
|
|
if (groupNode->type == NODE_TYPE_SERVICES) {
|
|
ReleaseService(groupNode->data.service);
|
|
groupNode->data.service = NULL;
|
|
} else if (groupNode->type == NODE_TYPE_CMDS) {
|
|
ReleaseCmd(groupNode->data.cmd);
|
|
groupNode->data.cmd = NULL;
|
|
}
|
|
free(groupNode);
|
|
}
|
|
|
|
void InitServiceSpace(void)
|
|
{
|
|
if (g_initWorkspace.initFlags != 0) {
|
|
return;
|
|
}
|
|
HashInfo info = {
|
|
GroupNodeNodeCompare,
|
|
GroupNodeKeyCompare,
|
|
GroupNodeGetNodeHashCode,
|
|
GroupNodeGetKeyHashCode,
|
|
GroupNodeFree,
|
|
GROUP_HASHMAP_BUCKET
|
|
};
|
|
for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
|
|
int ret = OH_HashMapCreate(&g_initWorkspace.hashMap[i], &info);
|
|
if (ret != 0) {
|
|
INIT_LOGE("%s", "Failed to create hash map");
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < NODE_TYPE_MAX; i++) {
|
|
g_initWorkspace.groupNodes[i] = NULL;
|
|
}
|
|
// get boot mode, set default mode
|
|
strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), BOOT_GROUP_DEFAULT);
|
|
int ret = GetParameterFromCmdLine(BOOT_GROUP_NAME,
|
|
g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr));
|
|
if (ret != 0) {
|
|
INIT_LOGV("Failed to get boot group");
|
|
if (GetBootModeFromMisc() == GROUP_CHARGE) {
|
|
strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), "device.charge.group");
|
|
}
|
|
}
|
|
INIT_LOGI("boot start %s", g_initWorkspace.groupModeStr);
|
|
g_initWorkspace.groupMode = GetBootGroupMode();
|
|
g_initWorkspace.initFlags = 1;
|
|
}
|
|
|
|
int InitParseGroupCfg(void)
|
|
{
|
|
char buffer[128] = {0}; // 128 buffer size
|
|
char *realPath = GetAbsolutePath(GROUP_DEFAULT_PATH,
|
|
g_initWorkspace.groupModeStr, buffer, sizeof(buffer));
|
|
INIT_ERROR_CHECK(realPath != NULL, return -1,
|
|
"Failed to get path for %s", g_initWorkspace.groupModeStr);
|
|
InitParseGroupCfg_(realPath);
|
|
InitGroupNode *groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
|
|
int level = 0;
|
|
while ((groupRoot != NULL) && (level < GROUP_IMPORT_MAX_LEVEL)) { // for more import
|
|
g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
|
|
InitImportGroupCfg_(groupRoot);
|
|
groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS];
|
|
level++;
|
|
}
|
|
InitFreeGroupNodes_(g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]);
|
|
g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL;
|
|
return 0;
|
|
}
|
|
|
|
InitGroupNode *AddGroupNode(int type, const char *name)
|
|
{
|
|
INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
|
|
INIT_ERROR_CHECK(name != NULL, return NULL, "Invalid name");
|
|
InitGroupNode *groupNode = GetGroupNode(type, name);
|
|
if (groupNode != NULL) {
|
|
return groupNode;
|
|
}
|
|
INIT_LOGV("AddGroupNode type %d name %s", type, name);
|
|
uint32_t nameLen = (uint32_t)strlen(name);
|
|
groupNode = (InitGroupNode *)calloc(1, sizeof(InitGroupNode) + nameLen + 1);
|
|
INIT_ERROR_CHECK(groupNode != NULL, return NULL, "Failed to alloc for group %s", name);
|
|
int ret = memcpy_s(groupNode->name, nameLen + 1, name, nameLen + 1);
|
|
INIT_ERROR_CHECK(ret == 0, free(groupNode);
|
|
return NULL, "Failed to alloc for group %s", name);
|
|
groupNode->type = type;
|
|
groupNode->next = g_initWorkspace.groupNodes[type];
|
|
g_initWorkspace.groupNodes[type] = groupNode;
|
|
|
|
if (type < NODE_TYPE_GROUPS) { // add hashmap
|
|
OH_HashMapAdd(g_initWorkspace.hashMap[type], &groupNode->hashNode);
|
|
}
|
|
return groupNode;
|
|
}
|
|
|
|
InitGroupNode *GetGroupNode(int type, const char *name)
|
|
{
|
|
if (type >= NODE_TYPE_GROUPS) {
|
|
return NULL;
|
|
}
|
|
HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
|
|
if (node == NULL) {
|
|
return NULL;
|
|
}
|
|
return HASHMAP_ENTRY(node, InitGroupNode, hashNode);
|
|
}
|
|
|
|
InitGroupNode *GetNextGroupNode(int type, const InitGroupNode *curr)
|
|
{
|
|
INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type");
|
|
if (curr == NULL) {
|
|
return g_initWorkspace.groupNodes[type];
|
|
}
|
|
return curr->next;
|
|
}
|
|
|
|
void DelGroupNode(int type, const char *name)
|
|
{
|
|
if (type >= NODE_TYPE_GROUPS) {
|
|
return;
|
|
}
|
|
INIT_LOGV("DelGroupNode type %d name %s", type, name);
|
|
OH_HashMapRemove(g_initWorkspace.hashMap[type], name);
|
|
InitGroupNode *groupNode = g_initWorkspace.groupNodes[type];
|
|
InitGroupNode *preNode = groupNode;
|
|
while (groupNode != NULL) {
|
|
if (strcmp(groupNode->name, name) != 0) {
|
|
preNode = groupNode;
|
|
groupNode = groupNode->next;
|
|
continue;
|
|
}
|
|
if (groupNode == g_initWorkspace.groupNodes[type]) {
|
|
g_initWorkspace.groupNodes[type] = groupNode->next;
|
|
} else {
|
|
preNode->next = groupNode->next;
|
|
}
|
|
free(groupNode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int CheckNodeValid(int type, const char *name)
|
|
{
|
|
if (type >= NODE_TYPE_GROUPS) {
|
|
return -1;
|
|
}
|
|
HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name);
|
|
if (node != NULL) {
|
|
INIT_LOGV("Found %s in %s group", name, type == NODE_TYPE_JOBS ? "job" : "service");
|
|
return 0;
|
|
}
|
|
if (g_initWorkspace.groupMode == GROUP_BOOT) {
|
|
// for boot start, can not start charger service
|
|
if (strcmp(name, "charger") == 0) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
HashMapHandle GetGroupHashMap(int type)
|
|
{
|
|
if (type >= NODE_TYPE_GROUPS) {
|
|
return NULL;
|
|
}
|
|
return g_initWorkspace.hashMap[type];
|
|
}
|
|
|
|
void CloseServiceSpace(void)
|
|
{
|
|
if (g_initWorkspace.initFlags == 0) {
|
|
return;
|
|
}
|
|
for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) {
|
|
if (g_initWorkspace.hashMap[i] != NULL) {
|
|
HashMapHandle handle = g_initWorkspace.hashMap[i];
|
|
g_initWorkspace.hashMap[i] = NULL;
|
|
OH_HashMapDestory(handle, NULL);
|
|
}
|
|
}
|
|
g_initWorkspace.initFlags = 0;
|
|
}
|
|
|
|
void ReleaseCmd(PluginCmd *cmd)
|
|
{
|
|
if (cmd == NULL) {
|
|
return;
|
|
}
|
|
ListNode *node = cmd->cmdExecutor.next;
|
|
while (node != &cmd->cmdExecutor) {
|
|
PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
|
|
OH_ListRemove(&cmdExec->node);
|
|
free(cmdExec);
|
|
node = cmd->cmdExecutor.next;
|
|
}
|
|
free(cmd);
|
|
}
|
|
|
|
#ifdef STARTUP_INIT_TEST
|
|
InitWorkspace *GetInitWorkspace(void)
|
|
{
|
|
return &g_initWorkspace;
|
|
}
|
|
#endif |