From 01ff09c36da5c5627deb4fff461870dc910b131e Mon Sep 17 00:00:00 2001 From: cheng_jinsong Date: Fri, 26 May 2023 14:45:15 +0800 Subject: [PATCH] feature vendor init Signed-off-by: cheng_jinsong --- .../include/init_cmdexecutor.h | 5 +- .../init_module_engine/stub/libinit.stub.json | 5 +- services/include/param/init_param.h | 2 +- services/init/include/init_cmds.h | 26 +- services/init/include/init_jobs_internal.h | 2 +- services/init/include/init_service.h | 1 + services/init/include/init_service_manager.h | 3 +- services/init/init_common_cmds.c | 122 ++++----- services/init/init_common_service.c | 8 +- services/init/init_config.c | 21 +- services/init/init_service_manager.c | 13 +- services/init/lite/init_cmds.c | 11 +- services/init/lite/init_jobs.c | 4 +- services/init/standard/BUILD.gn | 1 + services/init/standard/init_cmdexecutor.c | 25 +- services/init/standard/init_cmds.c | 50 ++-- .../init/standard/init_control_fd_service.c | 1 + services/init/standard/init_jobs.c | 4 +- services/init/standard/init_signal_handler.c | 2 + services/modules/BUILD.gn | 2 + services/modules/init_context/BUILD.gn | 64 +++++ services/modules/init_context/init_context.c | 243 ++++++++++++++++++ services/modules/init_context/init_context.h | 64 +++++ .../init_context/init_context_static.c | 79 ++++++ services/modules/init_eng/init_eng.c | 6 +- services/param/include/trigger_manager.h | 4 +- services/param/manager/param_manager.c | 4 +- services/param/trigger/trigger_manager.c | 12 +- services/param/trigger/trigger_processor.c | 13 +- services/utils/init_hashmap.c | 4 +- services/utils/init_utils.c | 2 +- test/moduletest/param_test_module.c | 5 +- test/moduletest/vendor.init.test.cfg | 29 +++ test/unittest/BUILD.gn | 8 + test/unittest/init/cmds_unittest.cpp | 13 +- test/unittest/init/group_unittest.cpp | 16 +- test/unittest/init/service_unittest.cpp | 10 +- .../unittest/innerkits/modulemgr_unittest.cpp | 2 +- test/unittest/lite/cmd_func_test.cpp | 10 +- test/unittest/modules/context_unittest.cpp | 115 +++++++++ test/unittest/modules/trace_unittest.cpp | 5 +- test/unittest/param/trigger_unittest.cpp | 22 +- 42 files changed, 870 insertions(+), 168 deletions(-) create mode 100644 services/modules/init_context/BUILD.gn create mode 100644 services/modules/init_context/init_context.c create mode 100644 services/modules/init_context/init_context.h create mode 100644 services/modules/init_context/init_context_static.c create mode 100644 test/moduletest/vendor.init.test.cfg create mode 100755 test/unittest/modules/context_unittest.cpp diff --git a/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h index 0060a83a..89b18595 100644 --- a/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h +++ b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h @@ -28,6 +28,7 @@ extern "C" { typedef struct { ListNode cmdExecutor; int cmdId; + unsigned char careContext; char *name; } PluginCmd; @@ -39,10 +40,8 @@ typedef struct { } PluginCmdExecutor; void PluginExecCmdByName(const char *name, const char *cmdContent); -void PluginExecCmdByCmdIndex(int index, const char *cmdContent); +// only exec in current context int PluginExecCmd(const char *name, int argc, const char **argv); -const char *PluginGetCmdIndex(const char *cmdStr, int *index); -const char *GetPluginCmdNameByIndex(int index); int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd); diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json index 70ef9f28..efc74fbc 100644 --- a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json @@ -21,5 +21,8 @@ { "name": "AddRebootCmdExecutor" }, { "name": "GetBootEventList" }, { "name": "WaitForFile" }, - { "name": "DoCmdByName" } + { "name": "DoCmdByIndex" }, + { "name": "GetMatchCmd" }, + { "name": "AddCareContextCmdExecutor" }, + { "name": "InitSubInitContext" } ] diff --git a/services/include/param/init_param.h b/services/include/param/init_param.h index 3e7d4860..1845e06d 100644 --- a/services/include/param/init_param.h +++ b/services/include/param/init_param.h @@ -121,7 +121,7 @@ void PostTrigger(EventType type, const char *content, uint32_t contentLen); * 解析trigger文件。 * */ -int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName)); +int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context); /** * 对外接口 diff --git a/services/init/include/init_cmds.h b/services/init/include/init_cmds.h index ccf669e5..31074005 100644 --- a/services/init/include/init_cmds.h +++ b/services/init/include/init_cmds.h @@ -22,6 +22,7 @@ #include #include "cJSON.h" +#include "init_cmdexecutor.h" #ifdef __cplusplus #if __cplusplus extern "C" { @@ -68,6 +69,7 @@ struct CmdTable { char name[MAX_CMD_NAME_LEN]; unsigned char minArg; unsigned char maxArg; + unsigned char careContext; void (*DoFuncion)(const struct CmdArgs *ctx); }; @@ -76,11 +78,20 @@ typedef struct INIT_TIMING_STAT { struct timespec endTime; } INIT_TIMING_STAT; +typedef enum _initContextType { + INIT_CONTEXT_CHIPSET, + INIT_CONTEXT_MAIN, +} InitContextType; + +typedef struct { + InitContextType type; +} ConfigContext; + int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen); const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount); void FreeCmdArg(struct CmdArgs *cmd); -void DoCmdByName(const char *name, const char *cmdContent); -void DoCmdByIndex(int index, const char *cmdContent); +// exec in context, if context == null, exec in current context +void DoCmdByIndex(int index, const char *cmdContent, const ConfigContext *context); const char *GetMatchCmd(const char *cmdStr, int *index); const char *GetCmdKey(int index); const struct CmdTable *GetCmdTable(int *number); @@ -93,6 +104,17 @@ int SetFileCryptPolicy(const char *dir); void OpenHidebug(const char *name); long long InitDiffTime(INIT_TIMING_STAT *stat); + +void StopSubInit(pid_t pid); +int ExecuteCmdInSubInit(const ConfigContext *context, const char *name, const char *cmdContent); +int SetSubInitContext(const ConfigContext *context, const char *service); + +// exec in context, if context == null, exec in current context +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context); +const char *PluginGetCmdIndex(const char *cmdStr, int *index); +const char *GetPluginCmdNameByIndex(int index); +int AddCareContextCmdExecutor(const char *cmdName, CmdExecutor executor); + #ifdef __cplusplus #if __cplusplus } diff --git a/services/init/include/init_jobs_internal.h b/services/init/include/init_jobs_internal.h index 2b67e5cc..3dd50aee 100644 --- a/services/init/include/init_jobs_internal.h +++ b/services/init/include/init_jobs_internal.h @@ -31,7 +31,7 @@ typedef struct { CmdLines *cmdLines; } Job; -void ParseAllJobs(const cJSON *fileRoot); +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context); void DoJob(const char *jobName); void ReleaseAllJobs(void); void DumpAllJobs(void); diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index 353d1c4b..3c76e056 100644 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -160,6 +160,7 @@ typedef struct Service_ { ServiceJobs serviceJobs; cpu_set_t *cpuSet; struct ListNode extDataNode; + ConfigContext context; } Service; #pragma pack() diff --git a/services/init/include/init_service_manager.h b/services/init/include/init_service_manager.h index 89f2c4ae..ea170d3c 100644 --- a/services/init/include/init_service_manager.h +++ b/services/init/include/init_service_manager.h @@ -17,6 +17,7 @@ #include "init_service.h" #include "cJSON.h" +#include "init_cmds.h" #include "list.h" #ifdef __cplusplus @@ -57,7 +58,7 @@ void StartServiceByName(const char *serviceName); void StopServiceByName(const char *serviceName); void StopAllServices(int flags, const char **exclude, int size, int (*filter)(const Service *service, const char **exclude, int size)); -void ParseAllServices(const cJSON *fileRoot); +void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context); void ReleaseService(Service *service); void LoadAccessTokenId(void); Service *AddService(const char *name); diff --git a/services/init/init_common_cmds.c b/services/init/init_common_cmds.c index 0b8717e8..13ee44a9 100644 --- a/services/init/init_common_cmds.c +++ b/services/init/init_common_cmds.c @@ -310,9 +310,9 @@ static int SetOwner(const char *file, const char *ownerStr, const char *groupStr INIT_ERROR_CHECK(groupStr != NULL, return -1, "SetOwner invalid file."); uid_t owner = DecodeUid(ownerStr); - INIT_ERROR_CHECK(owner != (uid_t)-1, return -1, "SetOwner invalid uid :%s.", ownerStr); + INIT_ERROR_CHECK(owner != (uid_t)-1, return -1, "SetOwner invalid uid : %s.", ownerStr); gid_t group = DecodeGid(groupStr); - INIT_ERROR_CHECK(group != (gid_t)-1, return -1, "SetOwner invalid gid :%s.", groupStr); + INIT_ERROR_CHECK(group != (gid_t)-1, return -1, "SetOwner invalid gid : %s.", groupStr); return (chown(file, owner, group) != 0) ? -1 : 0; } @@ -567,24 +567,24 @@ static void DoExport(const struct CmdArgs *ctx) } static const struct CmdTable g_cmdTable[] = { - { "start ", 0, 1, DoStart }, - { "mkdir ", 1, 4, DoMkDir }, - { "chmod ", 2, 2, DoChmod }, - { "chown ", 3, 3, DoChown }, - { "mount ", 1, 10, DoMount }, - { "export ", 2, 2, DoExport }, - { "rm ", 1, 1, DoRm }, - { "rmdir ", 1, 1, DoRmdir }, - { "write ", 2, 10, DoWrite }, - { "stop ", 1, 1, DoStop }, - { "reset ", 1, 1, DoReset }, - { "copy ", 2, 2, DoCopy }, - { "reboot ", 0, 1, DoRebootCmd }, - { "setrlimit ", 3, 3, DoSetrlimit }, - { "sleep ", 1, 1, DoSleep }, - { "wait ", 1, 2, DoWait }, - { "hostname ", 1, 1, DoSetHostname }, - { "domainname ", 1, 1, DoSetDomainname } + { "start ", 0, 1, 0, DoStart }, + { "mkdir ", 1, 4, 1, DoMkDir }, + { "chmod ", 2, 2, 1, DoChmod }, + { "chown ", 3, 3, 1, DoChown }, + { "mount ", 1, 10, 0, DoMount }, + { "export ", 2, 2, 0, DoExport }, + { "rm ", 1, 1, 1, DoRm }, + { "rmdir ", 1, 1, 1, DoRmdir }, + { "write ", 2, 10, 1, DoWrite }, + { "stop ", 1, 1, 0, DoStop }, + { "reset ", 1, 1, 0, DoReset }, + { "copy ", 2, 2, 1, DoCopy }, + { "reboot ", 0, 1, 0, DoRebootCmd }, + { "setrlimit ", 3, 3, 0, DoSetrlimit }, + { "sleep ", 1, 1, 0, DoSleep }, + { "wait ", 1, 2, 1, DoWait }, + { "hostname ", 1, 1, 1, DoSetHostname }, + { "domainname ", 1, 1, 1, DoSetDomainname } }; static const struct CmdTable *GetCommCmdTable(int *number) @@ -656,19 +656,30 @@ const char *GetMatchCmd(const char *cmdStr, int *index) return PluginGetCmdIndex(startCmd, index); } -const char *GetCmdKey(int index) +static const struct CmdTable *GetCmdTableByIndex(int index) { int cmdCnt = 0; const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + const struct CmdTable *cmdTable = NULL; if (index < cmdCnt) { - return commCmds[index].name; + cmdTable = &commCmds[index]; + } else { + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + if (index < (cmdCnt + number)) { + cmdTable = &cmds[index - cmdCnt]; + } } - int number = 0; - const struct CmdTable *cmds = GetCmdTable(&number); - if (index < (cmdCnt + number)) { - return cmds[index - cmdCnt].name; + return cmdTable; +} + +const char *GetCmdKey(int index) +{ + const struct CmdTable *cmdTable = GetCmdTableByIndex(index); + if (cmdTable != NULL) { + return cmdTable->name; } - return NULL; + return GetPluginCmdNameByIndex(index); } int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines) @@ -726,58 +737,31 @@ long long InitDiffTime(INIT_TIMING_STAT *stat) return diff; } -void DoCmdByName(const char *name, const char *cmdContent) -{ - if (name == NULL || cmdContent == NULL) { - return; - } - INIT_TIMING_STAT cmdTimer; - (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); - const struct CmdTable *cmd = GetCmdByName(name); - if (cmd != NULL) { - ExecCmd(cmd, cmdContent); - } else { - PluginExecCmdByName(name, cmdContent); - } - (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); - long long diff = InitDiffTime(&cmdTimer); -#ifndef OHOS_LITE - InitCmdHookExecute(name, cmdContent, &cmdTimer); -#endif - if (diff > 200000) { // 200000 > 200ms - INIT_LOGI("Execute command \"%s %s\" took %lld ms", name, cmdContent, diff / BASE_MS_UNIT); - } else { - INIT_LOGV("Execute command \"%s %s\" took %lld ms", name, cmdContent, diff / BASE_MS_UNIT); - } -} - -void DoCmdByIndex(int index, const char *cmdContent) +void DoCmdByIndex(int index, const char *cmdContent, const ConfigContext *context) { if (cmdContent == NULL) { return; } - int cmdCnt = 0; INIT_TIMING_STAT cmdTimer; (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); - const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + const char *cmdName = NULL; - if (index < cmdCnt) { - cmdName = commCmds[index].name; - ExecCmd(&commCmds[index], cmdContent); - } else { - int number = 0; - const struct CmdTable *cmds = GetCmdTable(&number); - if (index < (cmdCnt + number)) { - cmdName = cmds[index - cmdCnt].name; - ExecCmd(&cmds[index - cmdCnt], cmdContent); + const struct CmdTable *cmdTable = GetCmdTableByIndex(index); + if (cmdTable != NULL) { + cmdName = cmdTable->name; + if (context == NULL || !cmdTable->careContext || context->type == INIT_CONTEXT_MAIN || getpid() != 1) { + ExecCmd(cmdTable, cmdContent); } else { - PluginExecCmdByCmdIndex(index, cmdContent); - cmdName = GetPluginCmdNameByIndex(index); - if (cmdName == NULL) { - cmdName = "Unknown"; - } + ExecuteCmdInSubInit(context, cmdTable->name, cmdContent); + } + } else { + PluginExecCmdByCmdIndex(index, cmdContent, context); + cmdName = GetPluginCmdNameByIndex(index); + if (cmdName == NULL) { + cmdName = "Unknown"; } } + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); long long diff = InitDiffTime(&cmdTimer); #ifndef OHOS_LITE diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index abe2ed84..bd29c657 100644 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -499,6 +499,11 @@ int ServiceStart(Service *service) #endif int pid = fork(); if (pid == 0) { + // set selinux label by context + if (service->context.type != INIT_CONTEXT_MAIN) { + SetSubInitContext(&service->context, service->name); + } + if (service->attribute & SERVICE_ATTR_MODULE_UPDATE) { CheckModuleUpdate(service->pathArgs.count, service->pathArgs.argv); } @@ -591,7 +596,7 @@ static int ExecRestartCmd(Service *service) } for (int i = 0; i < service->restartArg->cmdNum; i++) { INIT_LOGI("ExecRestartCmd cmdLine->cmdContent %s ", service->restartArg->cmds[i].cmdContent); - DoCmdByIndex(service->restartArg->cmds[i].cmdIndex, service->restartArg->cmds[i].cmdContent); + DoCmdByIndex(service->restartArg->cmds[i].cmdIndex, service->restartArg->cmds[i].cmdContent, NULL); } free(service->restartArg); service->restartArg = NULL; @@ -733,6 +738,7 @@ int UpdaterServiceFds(Service *service, int *fds, size_t fdCount) // case 1 CloseServiceFds(service, true); } + INIT_ERROR_CHECK(fdCount <= MAX_HOLD_FDS, return -1, "Invalid fdCount %d", fdCount); service->fds = calloc(fdCount + 1, sizeof(int)); if (service->fds == NULL) { INIT_LOGE("Service \' %s \' failed to allocate memory for fds", service->name); diff --git a/services/init/init_config.c b/services/init/init_config.c index a0fc3de5..73b67583 100644 --- a/services/init/init_config.c +++ b/services/init/init_config.c @@ -21,12 +21,29 @@ static void ParseAllImports(const cJSON *root); +InitContextType GetConfigContextType(const char *cfgName) +{ + static const char *vendorDir[] = { + "/vendor/etc/init/", "/chipset/etc/init/", "/chip_prod/etc/init/" + }; + + for (size_t j = 0; j < ARRAY_LENGTH(vendorDir); j++) { + if (strncmp(vendorDir[j], cfgName, strlen(vendorDir[j])) == 0) { + return INIT_CONTEXT_CHIPSET; + } + } + return INIT_CONTEXT_MAIN; +} + static void ParseInitCfgContents(const char *cfgName, const cJSON *root) { INIT_ERROR_CHECK(root != NULL, return, "Root is null"); - ParseAllServices(root); + ConfigContext context = { INIT_CONTEXT_MAIN }; + context.type = GetConfigContextType(cfgName); + INIT_LOGV("Parse %s configs in context %d", cfgName, context.type); + ParseAllServices(root, &context); // parse jobs - ParseAllJobs(root); + ParseAllJobs(root, &context); // parse imports ParseAllImports(root); } diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index 8afc39dc..cd4a540f 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -100,6 +100,8 @@ Service *AddService(const char *name) service->name = node->name; service->status = SERVICE_IDLE; service->cpuSet = NULL; + service->pid = -1; + service->context.type = INIT_CONTEXT_MAIN; OH_ListInit(&service->extDataNode); g_serviceSpace.serviceCount++; INIT_LOGV("AddService %s", node->name); @@ -988,16 +990,12 @@ int WatchConsoleDevice(Service *service) return 0; } -void ParseAllServices(const cJSON *fileRoot) +void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context) { int servArrSize = 0; cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON); INIT_CHECK(serviceArr != NULL, return); - INIT_ERROR_CHECK(servArrSize <= MAX_SERVICES_CNT_IN_FILE, return, - "Too many services[cnt %d] detected, should not exceed %d.", - servArrSize, MAX_SERVICES_CNT_IN_FILE); - size_t strLen = 0; for (int i = 0; i < servArrSize; ++i) { cJSON *curItem = cJSON_GetArrayItem(serviceArr, i); @@ -1020,11 +1018,12 @@ void ParseAllServices(const cJSON *fileRoot) #endif } - service->pid = -1; + if (context != NULL) { + service->context.type = context->type; + } int ret = ParseOneService(curItem, service); if (ret != SERVICE_SUCCESS) { ReleaseService(service); - service = NULL; continue; } ret = ParseServiceSocket(curItem, service); diff --git a/services/init/lite/init_cmds.c b/services/init/lite/init_cmds.c index 50a49f9a..fa4ddff1 100644 --- a/services/init/lite/init_cmds.c +++ b/services/init/lite/init_cmds.c @@ -108,8 +108,8 @@ static void DoLoadCfg(const struct CmdArgs *ctx) } static const struct CmdTable g_cmdTable[] = { - { "exec ", 1, 10, DoExec }, - { "loadcfg ", 1, 1, DoLoadCfg }, + { "exec ", 1, 10, 0, DoExec }, + { "loadcfg ", 1, 1, 0, DoLoadCfg }, }; const struct CmdTable *GetCmdTable(int *number) @@ -122,7 +122,7 @@ void PluginExecCmdByName(const char *name, const char *cmdContent) { } -void PluginExecCmdByCmdIndex(int index, const char *cmdContent) +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context) { } @@ -140,3 +140,8 @@ int SetFileCryptPolicy(const char *dir) { return 0; } + +int SetSubInitContext(const ConfigContext *context, const char *service) +{ + return 0; +} diff --git a/services/init/lite/init_jobs.c b/services/init/lite/init_jobs.c index 820c4c34..093eaee1 100644 --- a/services/init/lite/init_jobs.c +++ b/services/init/lite/init_jobs.c @@ -81,7 +81,7 @@ static void ParseJob(const cJSON *jobItem, Job *resJob) return; } -void ParseAllJobs(const cJSON *fileRoot) +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context) { if (fileRoot == NULL) { INIT_LOGE("ParseAllJobs, input fileRoot is NULL!"); @@ -138,7 +138,7 @@ void DoJob(const char *jobName) continue; } for (int j = 0; j < cmdLines->cmdNum; ++j) { - DoCmdByIndex(cmdLines->cmds[j].cmdIndex, cmdLines->cmds[j].cmdContent); + DoCmdByIndex(cmdLines->cmds[j].cmdIndex, cmdLines->cmds[j].cmdContent, NULL); } } } diff --git a/services/init/standard/BUILD.gn b/services/init/standard/BUILD.gn index 589b95ae..7ce75797 100644 --- a/services/init/standard/BUILD.gn +++ b/services/init/standard/BUILD.gn @@ -57,6 +57,7 @@ ohos_executable("init") { include_dirs = [ "//base/startup/init/services/init/include", "//base/startup/init/services/modules/reboot", + "//base/startup/init/services/modules/init_context", "${FSCRYPT_PATH}/include/libfscrypt", ] diff --git a/services/init/standard/init_cmdexecutor.c b/services/init/standard/init_cmdexecutor.c index aca4c681..d5e53929 100644 --- a/services/init/standard/init_cmdexecutor.c +++ b/services/init/standard/init_cmdexecutor.c @@ -26,7 +26,7 @@ #define MAX_CMD_ARGC 10 static int g_cmdExecutorId = 0; static int g_cmdId = 0; -int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) +int AddCmdExecutor_(const char *cmdName, CmdExecutor execCmd, int careContext) { INIT_ERROR_CHECK(cmdName != NULL, return -1, "Invalid input param"); INIT_LOGV("Add command '%s' executor.", cmdName); @@ -43,6 +43,7 @@ int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) groupNode->data.cmd = cmd; cmd->cmdId = g_cmdId++; cmd->name = groupNode->name; + cmd->careContext = careContext; OH_ListInit(&cmd->cmdExecutor); } if (execCmd == NULL) { @@ -57,6 +58,16 @@ int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) return cmdExec->id; } +int AddCareContextCmdExecutor(const char *cmdName, CmdExecutor execCmd) +{ + return AddCmdExecutor_(cmdName, execCmd, 1); +} + +int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) +{ + return AddCmdExecutor_(cmdName, execCmd, 0); +} + void RemoveCmdExecutor(const char *cmdName, int id) { INIT_ERROR_CHECK(cmdName != NULL, return, "Invalid input param"); @@ -82,7 +93,7 @@ void RemoveCmdExecutor(const char *cmdName, int id) free(cmd); } -void PluginExecCmd_(PluginCmd *cmd, const char *cmdContent) +static void PluginExecCmd_(PluginCmd *cmd, const char *cmdContent) { const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", MAX_CMD_ARGC); if (ctx == NULL) { @@ -169,15 +180,19 @@ const char *GetPluginCmdNameByIndex(int index) return cmd->name; } -void PluginExecCmdByCmdIndex(int index, const char *cmdContent) +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context) { PluginCmd *cmd = GetPluginCmdByIndex(index); if (cmd == NULL) { INIT_LOGW("Cannot find plugin command with index %d", index); return; } - INIT_LOGV("Command: %s cmdContent: %s", cmd->name, cmdContent); - PluginExecCmd_(cmd, cmdContent); + INIT_LOGV("Command: %s cmdContent: %s %d", cmd->name, cmdContent, cmd->careContext); + if (context == NULL || !cmd->careContext || context->type == INIT_CONTEXT_MAIN || getpid() != 1) { + PluginExecCmd_(cmd, cmdContent); + } else { + ExecuteCmdInSubInit(context, cmd->name, cmdContent); + } } const char *PluginGetCmdIndex(const char *cmdStr, int *index) diff --git a/services/init/standard/init_cmds.c b/services/init/standard/init_cmds.c index 254035de..6d160a2c 100755 --- a/services/init/standard/init_cmds.c +++ b/services/init/standard/init_cmds.c @@ -494,31 +494,31 @@ static void DoMkSandbox(const struct CmdArgs *ctx) } static const struct CmdTable g_cmdTable[] = { - { "syncexec ", 1, 10, DoSyncExec }, - { "exec ", 1, 10, DoExec }, - { "mknode ", 5, 5, DoMakeNode }, - { "makedev ", 2, 2, DoMakeDevice }, - { "symlink ", 2, 2, DoSymlink }, - { "trigger ", 0, 1, DoTriggerCmd }, - { "insmod ", 1, 10, DoInsmod }, - { "setparam ", 2, 2, DoSetParam }, - { "load_persist_params ", 0, 1, DoLoadPersistParams }, - { "load_param ", 1, 2, DoLoadDefaultParams }, - { "load_access_token_id ", 0, 1, DoLoadAccessTokenId }, - { "ifup ", 1, 1, DoIfup }, - { "mount_fstab ", 1, 1, DoMountFstabFile }, - { "umount_fstab ", 1, 1, DoUmountFstabFile }, - { "restorecon ", 1, 1, DoRestorecon }, - { "stopAllServices ", 0, 10, DoStopAllServices }, - { "umount ", 1, 1, DoUmount }, - { "sync ", 0, 1, DoSync }, - { "timer_start", 1, 1, DoTimerStart }, - { "timer_stop", 1, 1, DoTimerStop }, - { "init_global_key ", 1, 1, DoInitGlobalKey }, - { "init_main_user ", 0, 1, DoInitMainUser }, - { "mkswap", 1, 1, DoMkswap}, - { "swapon", 1, 1, DoSwapon}, - { "mksandbox", 1, 1, DoMkSandbox}, + { "syncexec ", 1, 10, 0, DoSyncExec }, + { "exec ", 1, 10, 0, DoExec }, + { "mknode ", 5, 5, 0, DoMakeNode }, + { "makedev ", 2, 2, 0, DoMakeDevice }, + { "symlink ", 2, 2, 1, DoSymlink }, + { "trigger ", 0, 1, 0, DoTriggerCmd }, + { "insmod ", 1, 10, 1, DoInsmod }, + { "setparam ", 2, 2, 0, DoSetParam }, + { "load_persist_params ", 0, 1, 0, DoLoadPersistParams }, + { "load_param ", 1, 2, 0, DoLoadDefaultParams }, + { "load_access_token_id ", 0, 1, 0, DoLoadAccessTokenId }, + { "ifup ", 1, 1, 1, DoIfup }, + { "mount_fstab ", 1, 1, 0, DoMountFstabFile }, + { "umount_fstab ", 1, 1, 0, DoUmountFstabFile }, + { "restorecon ", 1, 1, 1, DoRestorecon }, + { "stopAllServices ", 0, 10, 0, DoStopAllServices }, + { "umount ", 1, 1, 0, DoUmount }, + { "sync ", 0, 1, 0, DoSync }, + { "timer_start", 1, 1, 0, DoTimerStart }, + { "timer_stop", 1, 1, 0, DoTimerStop }, + { "init_global_key ", 1, 1, 0, DoInitGlobalKey }, + { "init_main_user ", 0, 1, 0, DoInitMainUser }, + { "mkswap", 1, 1, 0, DoMkswap}, + { "swapon", 1, 1, 0, DoSwapon}, + { "mksandbox", 1, 1, 0, DoMkSandbox}, }; const struct CmdTable *GetCmdTable(int *number) diff --git a/services/init/standard/init_control_fd_service.c b/services/init/standard/init_control_fd_service.c index 6b87dc69..836eb3b1 100755 --- a/services/init/standard/init_control_fd_service.c +++ b/services/init/standard/init_control_fd_service.c @@ -92,6 +92,7 @@ static void DumpOneService(const Service *service) printf("\tservice name: [%s] \n", service->name); printf("\tservice pid: [%d] \n", service->pid); + printf("\tservice context : [%s] \n", (service->context.type == INIT_CONTEXT_CHIPSET) ? "vendor" : "system"); printf("\tservice crashCnt: [%d] \n", service->crashCnt); printf("\tservice attribute: [%u] \n", service->attribute); printf("\tservice importance: [%d] \n", service->importance); diff --git a/services/init/standard/init_jobs.c b/services/init/standard/init_jobs.c index 6190cfad..3086f6e8 100644 --- a/services/init/standard/init_jobs.c +++ b/services/init/standard/init_jobs.c @@ -23,9 +23,9 @@ static int CheckJobValid(const char *jobName) return CheckNodeValid(NODE_TYPE_JOBS, jobName); } -void ParseAllJobs(const cJSON *fileRoot) +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context) { - ParseTriggerConfig(fileRoot, CheckJobValid); + ParseTriggerConfig(fileRoot, CheckJobValid, (void *)context); } int DoJobNow(const char *jobName) diff --git a/services/init/standard/init_signal_handler.c b/services/init/standard/init_signal_handler.c index 3e8fe9bc..68b869e9 100644 --- a/services/init/standard/init_signal_handler.c +++ b/services/init/standard/init_signal_handler.c @@ -20,6 +20,7 @@ #include "init_adapter.h" #include "init_log.h" #include "init_param.h" +#include "init_context.h" #include "init_service_manager.h" #include "loop_event.h" @@ -49,6 +50,7 @@ INIT_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo) service == NULL ? "Unknown" : service->name, sigPID, procStat); } CmdServiceProcessDelClient(sigPID); + StopSubInit(sigPID); INIT_LOGI("SigHandler, SIGCHLD received, Service:%s pid:%d uid:%d status:%d.", service == NULL ? "Unknown" : service->name, sigPID, siginfo->ssi_uid, procStat); diff --git a/services/modules/BUILD.gn b/services/modules/BUILD.gn index e2b9e2e2..e60cdcb9 100755 --- a/services/modules/BUILD.gn +++ b/services/modules/BUILD.gn @@ -17,6 +17,7 @@ group("static_modules") { deps = [ "bootchart:libbootchart_static", "bootevent:libbootevent_static", + "init_context:initcontext_static", "init_eng:libiniteng_static", "init_hook:inithook", "reboot:libreboot_static", @@ -39,6 +40,7 @@ group("modulesgroup") { if (!defined(ohos_lite)) { deps = [ "bootchart:bootchart", + "init_context:init_context", "init_eng:init_eng", "reboot:rebootmodule", "sysevent:eventmodule", diff --git a/services/modules/init_context/BUILD.gn b/services/modules/init_context/BUILD.gn new file mode 100644 index 00000000..d434176c --- /dev/null +++ b/services/modules/init_context/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2023 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. + +import("//base/startup/init/begetd.gni") +import("//build/ohos.gni") + +comm_include = [ + ".", + "..", + "../../init/include", + "../../include", + "../../include/param", +] + +ohos_shared_library("init_context") { + sources = [ "init_context.c" ] + + include_dirs = comm_include + + include_dirs += [ "../../init/include" ] + + external_deps = [ + "init:libinit_module_engine", + "selinux:libload_policy", + "selinux:librestorecon", + ] + + deps = [ + "//third_party/bounds_checking_function:libsec_shared", + "//third_party/selinux:libselinux", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("initcontext_static_config") { + include_dirs = comm_include +} + +ohos_source_set("initcontext_static") { + sources = [ "init_context_static.c" ] + include_dirs = comm_include + public_configs = [ ":initcontext_static_config" ] + public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + deps = [ "//third_party/bounds_checking_function:libsec_shared" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/modules/init_context/init_context.c b/services/modules/init_context/init_context.c new file mode 100644 index 00000000..c138a41e --- /dev/null +++ b/services/modules/init_context/init_context.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2023 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_context.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "init_module_engine.h" +#include "plugin_adapter.h" +#include "init_cmds.h" +#include "init_utils.h" +#include "securec.h" + +#ifdef STARTUP_INIT_TEST +#define TIMEOUT_DEF 2 +#else +#define TIMEOUT_DEF 5 +#endif + +static SubInitInfo g_subInitInfo[INIT_CONTEXT_MAIN] = {}; +static const char *g_subContext[INIT_CONTEXT_MAIN] = { + "u:r:vendor_init:s0" +}; + +static void SubInitMain(InitContextType type, int readFd, int writeFd); +static void HandleRecvMessage(SubInitInfo *subInfo, char *buffer, uint32_t size); +static int CreateSocketPair(int socket[2]); +static int SubInitSetSelinuxContext(InitContextType type); + +static int SubInitStart(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + SubInitInfo *subInfo = &g_subInitInfo[type]; + if (subInfo->state != SUB_INIT_STATE_IDLE) { + return 0; + } + int socket[2] = {0}; + int ret = CreateSocketPair(socket); + PLUGIN_CHECK(ret == 0, return -1, "Failed to create socket for %d", type); + + subInfo->state = SUB_INIT_STATE_STARTING; + pid_t pid = fork(); + if (pid < 0) { + close(socket[0]); + close(socket[1]); + subInfo->state = SUB_INIT_STATE_IDLE; + return -1; + } + if (pid == 0) { + SubInitSetSelinuxContext(type); + int fd = dup(socket[1]); + close(socket[0]); + close(socket[1]); + SubInitMain(type, fd, fd); + close(fd); + _exit(PROCESS_EXIT_CODE); + } + close(socket[1]); + subInfo->sendFd = socket[0]; + subInfo->recvFd = socket[0]; + subInfo->state = SUB_INIT_STATE_RUNNING; + subInfo->subPid = pid; + return 0; +} + +static void SubInitStop(pid_t pid) +{ + for (size_t i = 0; i < ARRAY_LENGTH(g_subInitInfo); i++) { + if (g_subInitInfo[i].subPid == pid) { + close(g_subInitInfo[i].sendFd); + close(g_subInitInfo[i].recvFd); + g_subInitInfo[i].subPid = 0; + g_subInitInfo[i].state = SUB_INIT_STATE_IDLE; + } + } +} + +static int SubInitExecuteCmd(InitContextType type, const char *name, const char *cmdContent) +{ + static char buffer[MAX_CMD_LEN] = {0}; + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + PLUGIN_CHECK(name != NULL, return -1, "Invalid cmd name"); + SubInitInfo *subInfo = &g_subInitInfo[type]; + if (subInfo->state != SUB_INIT_STATE_RUNNING) { + PLUGIN_LOGW("Sub init %d is not running ", type); + return -1; + } + int len = 0; + if (cmdContent != NULL) { + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%s %s", name, cmdContent); + } else { + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%s ", name); + } + PLUGIN_CHECK(len > 0, return -1, "Failed to format cmd %s", name); + buffer[len] = '\0'; + PLUGIN_LOGV("send cmd '%s'", buffer); + int ret = send(subInfo->sendFd, buffer, len, 0); + PLUGIN_CHECK(ret > 0, return errno, "Failed to send cmd %s to %d errno %d", name, subInfo->type, errno); + + // block and wait result + ssize_t rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, sizeof(buffer))); + while ((rLen < 0) && (errno == EAGAIN)) { + rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, sizeof(buffer))); + } + PLUGIN_CHECK(rLen >= 0 && rLen < sizeof(buffer), return errno, + "Failed to read result from %d for cmd %s errno %d", subInfo->type, name, errno); + // change to result + buffer[rLen] = '\0'; + PLUGIN_LOGV("recv cmd result %s", buffer); + errno = 0; + ret = atoi(buffer); + if (errno != 0) { + return errno; + } + return ret; +} + +static int CreateSocketPair(int socket[2]) +{ + int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socket); + PLUGIN_CHECK(ret == 0, return -1, "Create socket fail errno %d", errno); + + int opt = 1; + struct timeval timeout = {TIMEOUT_DEF, 0}; + do { + ret = setsockopt(socket[0], SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[0], errno); + ret = setsockopt(socket[1], SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[1], errno); + ret = setsockopt(socket[0], SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[0], errno); + } while (0); + if (ret != 0) { + close(socket[0]); + close(socket[1]); + } + return ret; +} + +static int HandleRecvMessage_(SubInitInfo *subInfo, char *buffer, uint32_t size) +{ + ssize_t rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, size)); + while ((rLen < 0) && (errno == EAGAIN)) { + rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, size)); + } + PLUGIN_CHECK(rLen >= 0, return errno, "Read message for %d fail errno %d", subInfo->type, errno); + buffer[rLen] = '\0'; + PLUGIN_LOGI("Exec cmd '%s' in sub init %s", buffer, g_subContext[subInfo->type]); + int index = 0; + const char *cmd = GetMatchCmd(buffer, &index); + PLUGIN_CHECK(cmd != NULL, return -1, "Can not find cmd %s", buffer); + DoCmdByIndex(index, buffer + strlen(cmd) + 1, NULL); + return 0; +} + +static void HandleRecvMessage(SubInitInfo *subInfo, char *buffer, uint32_t size) +{ + int ret = HandleRecvMessage_(subInfo, buffer, size); + int len = snprintf_s(buffer, size, size - 1, "%d", ret); + PLUGIN_CHECK(len > 0, return, "Failed to format result %d", ret); + buffer[len] = '\0'; + ret = send(subInfo->sendFd, buffer, len, 0); + PLUGIN_CHECK(ret > 0, return, "Failed to send result to %d errno %d", subInfo->type, errno); +} + +static void SubInitMain(InitContextType type, int readFd, int writeFd) +{ + PLUGIN_LOGI("SubInitMain, sub init %s[%d] enter", g_subContext[type], getpid()); + char buffer[MAX_CMD_LEN] = {0}; + (void)prctl(PR_SET_NAME, "vendor_init"); + struct pollfd pfd = {}; + pfd.events = POLLIN; + pfd.fd = readFd; +#ifndef STARTUP_INIT_TEST + const int timeout = 30000; // 30000 30s +#else + const int timeout = 1000; // 1000 1s +#endif + SubInitInfo subInfo = {}; + subInfo.type = type; + subInfo.recvFd = readFd; + subInfo.sendFd = writeFd; + while (1) { + pfd.revents = 0; + int ret = poll(&pfd, 1, timeout); + if (ret == 0) { + PLUGIN_LOGI("Poll sub init timeout, sub init %d exit", type); + return; + } else if (ret < 0) { + PLUGIN_LOGE("Failed to poll sub init socket!"); + return; + } + if (pfd.revents & POLLIN) { + HandleRecvMessage(&subInfo, buffer, sizeof(buffer)); + } + } +} + +static int SubInitSetSelinuxContext(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + setcon(g_subContext[type]); + return 0; +} + +#ifdef STARTUP_INIT_TEST +SubInitInfo *GetSubInitInfo(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return NULL, "Invalid type %d", type); + return &g_subInitInfo[type]; +} +#endif + +MODULE_CONSTRUCTOR(void) +{ + for (size_t i = 0; i < ARRAY_LENGTH(g_subContext); i++) { + SubInitContext context = { + (InitContextType)i, + SubInitStart, + SubInitStop, + SubInitExecuteCmd, + SubInitSetSelinuxContext + }; + InitSubInitContext((InitContextType)i, &context); + } +} diff --git a/services/modules/init_context/init_context.h b/services/modules/init_context/init_context.h new file mode 100644 index 00000000..65959302 --- /dev/null +++ b/services/modules/init_context/init_context.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef STARTUP_INIT_CONTEXT +#define STARTUP_INIT_CONTEXT +#include +#include +#include + +#include "init_cmds.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MAX_CMD_LEN 512 + +typedef enum { + SUB_INIT_STATE_IDLE, + SUB_INIT_STATE_STARTING, + SUB_INIT_STATE_RUNNING +} SubInitState; + +typedef struct { + InitContextType type; + int sendFd; + int recvFd; + pid_t subPid; + SubInitState state; +} SubInitInfo; + +typedef struct { + InitContextType type; + int (*startSubInit)(InitContextType type); + void (*stopSubInit)(pid_t pid); + int (*executeCmdInSubInit)(InitContextType type, const char *, const char *); + int (*setSubInitContext)(InitContextType type); +} SubInitContext; + +int StartSubInit(InitContextType type); +int InitSubInitContext(InitContextType type, const SubInitContext *context); +#ifdef STARTUP_INIT_TEST +SubInitInfo *GetSubInitInfo(InitContextType type); +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/modules/init_context/init_context_static.c b/services/modules/init_context/init_context_static.c new file mode 100644 index 00000000..b248adbd --- /dev/null +++ b/services/modules/init_context/init_context_static.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 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_context.h" + +#include "init_module_engine.h" +#include "plugin_adapter.h" +#include "securec.h" + +static SubInitContext g_subInitContext[INIT_CONTEXT_MAIN] = {}; +static int g_subInitRunning = 0; + +int InitSubInitContext(InitContextType type, const SubInitContext *context) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + PLUGIN_CHECK(context != NULL, return -1, "Invalid context %d", type); + g_subInitContext[type].type = type; + g_subInitContext[type].startSubInit = context->startSubInit; + g_subInitContext[type].stopSubInit = context->stopSubInit; + g_subInitContext[type].executeCmdInSubInit = context->executeCmdInSubInit; + g_subInitContext[type].setSubInitContext = context->setSubInitContext; + return 0; +} + +void StopSubInit(pid_t pid) +{ + if (g_subInitContext[0].stopSubInit != NULL) { + g_subInitContext[0].stopSubInit(pid); + } +} + +int StartSubInit(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + if (!g_subInitRunning) { + // install init context +#ifndef STARTUP_INIT_TEST + InitModuleMgrInstall("init_context"); +#endif + } + PLUGIN_CHECK(g_subInitContext[type].startSubInit != NULL, return -1, "Invalid context %d", type); + g_subInitRunning = 1; + return g_subInitContext[type].startSubInit(type); +} + +int ExecuteCmdInSubInit(const ConfigContext *context, const char *name, const char *cmdContent) +{ + PLUGIN_CHECK(context != NULL, return -1, "Invalid context"); + PLUGIN_CHECK(name != NULL, return -1, "Invalid name"); + PLUGIN_CHECK(context->type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", context->type); + PLUGIN_LOGV("Execute command '%s %s' in context %d", name, cmdContent, context->type); + StartSubInit(context->type); + PLUGIN_CHECK(g_subInitContext[context->type].executeCmdInSubInit != NULL, + return -1, "Invalid context %d", context->type); + return g_subInitContext[context->type].executeCmdInSubInit(context->type, name, cmdContent); +} + +int SetSubInitContext(const ConfigContext*context, const char *service) +{ + PLUGIN_CHECK(context != NULL, return -1, "Invalid context"); + if (context->type >=INIT_CONTEXT_MAIN) { + return 0; + } + PLUGIN_CHECK(g_subInitContext[context->type].setSubInitContext != NULL, + return -1, "Invalid context %d", context->type); + PLUGIN_LOGI("Set selinux context %d for %s", context->type, service); + return g_subInitContext[context->type].setSubInitContext(context->type); +} diff --git a/services/modules/init_eng/init_eng.c b/services/modules/init_eng/init_eng.c index f7144cc0..d7f97ffe 100644 --- a/services/modules/init_eng/init_eng.c +++ b/services/modules/init_eng/init_eng.c @@ -86,13 +86,15 @@ ENG_STATIC void MountEngPartitions(void) BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng_system", "/dev/block/by-name/eng_system", "ext4"); WaitForFile(ENG_SYSTEM_DEVICE_PATH, WAIT_MAX_SECOND); - DoCmdByName("mount ", mountCmd); + int cmdIndex = 0; + (void)GetMatchCmd("mount ", &cmdIndex); + DoCmdByIndex(cmdIndex, mountCmd, NULL); // Mount eng_chipset BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng_chipset", "/dev/block/by-name/eng_chipset", "ext4"); WaitForFile(ENG_CHIPSET_DEVICE_PATH, WAIT_MAX_SECOND); - DoCmdByName("mount ", mountCmd); + DoCmdByIndex(cmdIndex, mountCmd, NULL); } ENG_STATIC void BindMountFile(const char *source, const char *target) diff --git a/services/param/include/trigger_manager.h b/services/param/include/trigger_manager.h index c0dbdeae..0121a67a 100644 --- a/services/param/include/trigger_manager.h +++ b/services/param/include/trigger_manager.h @@ -18,6 +18,7 @@ #include #include "cJSON.h" +#include "init_cmds.h" #include "init_hashmap.h" #include "list.h" #include "param_message.h" @@ -107,6 +108,7 @@ typedef struct TriggerHeader_ { typedef struct CommandNode_ { struct CommandNode_ *next; + ConfigContext cfgContext; uint32_t cmdKeyIndex; char content[0]; } CommandNode; @@ -183,7 +185,7 @@ JobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace, JobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName); void FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger); void ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type); -int AddCommand(JobNode *trigger, uint32_t cmdIndex, const char *content); +int AddCommand(JobNode *trigger, uint32_t cmdIndex, const char *content, const ConfigContext *cfgContext); CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr); void PostParamTrigger(int type, const char *name, const char *value); diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c index 4c379957..9528bc5d 100644 --- a/services/param/manager/param_manager.c +++ b/services/param/manager/param_manager.c @@ -370,7 +370,9 @@ INIT_LOCAL_API int CheckParameterSet(const char *name, // do hook cmd PARAM_LOGV("Check parameter settings realKey %s cmd: '%s' value: %s", serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); - DoCmdByName(serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); + int cmdIndex = 0; + (void)GetMatchCmd(serviceInfo->cmdName, &cmdIndex); + DoCmdByIndex(cmdIndex, (char *)serviceInfo->realKey + serviceInfo->valueOffset, NULL); #endif } if (serviceInfo != NULL) { diff --git a/services/param/trigger/trigger_manager.c b/services/param/trigger/trigger_manager.c index 997b250d..c54b8066 100644 --- a/services/param/trigger/trigger_manager.c +++ b/services/param/trigger/trigger_manager.c @@ -25,7 +25,7 @@ static DUMP_PRINTF g_printf = printf; -int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content) +int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content, const ConfigContext *cfgContext) { PARAM_CHECK(trigger != NULL, return -1, "trigger is null"); uint32_t size = sizeof(CommandNode); @@ -43,7 +43,10 @@ int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content) PARAM_CHECK(ret == EOK, free(node); return 0, "Failed to copy command"); } - + node->cfgContext.type = INIT_CONTEXT_MAIN; + if (cfgContext != NULL) { + node->cfgContext.type = cfgContext->type; + } if (trigger->firstCmd == NULL) { trigger->firstCmd = node; trigger->lastCmd = node; @@ -488,8 +491,9 @@ static void DumpJobTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode int count = 0; CommandNode *cmd = GetNextCmdNode(node, NULL); while (cmd != NULL && count < maxCmd) { - PARAM_DUMP(" command name: %s \n", GetCmdKey(cmd->cmdKeyIndex)); - PARAM_DUMP(" command args: %s \n", cmd->content); + PARAM_DUMP(" command name: %s (%s) \n", GetCmdKey(cmd->cmdKeyIndex), + (cmd->cfgContext.type == INIT_CONTEXT_CHIPSET) ? "vendor" : "system"); + PARAM_DUMP(" command args : %s \n", cmd->content); cmd = GetNextCmdNode(node, cmd); count++; } diff --git a/services/param/trigger/trigger_processor.c b/services/param/trigger/trigger_processor.c index 13810ad5..20875e42 100644 --- a/services/param/trigger/trigger_processor.c +++ b/services/param/trigger/trigger_processor.c @@ -37,7 +37,7 @@ static int DoTriggerExecute_(const TriggerNode *trigger, const char *content, ui CommandNode *cmd = GetNextCmdNode((JobNode *)trigger, NULL); while (cmd != NULL) { #ifndef STARTUP_INIT_TEST - DoCmdByIndex(cmd->cmdKeyIndex, cmd->content); + DoCmdByIndex(cmd->cmdKeyIndex, cmd->content, &cmd->cfgContext); #endif cmd = GetNextCmdNode((JobNode *)trigger, cmd); } @@ -225,7 +225,7 @@ static void ParseJobHookExecute(const char *name, const cJSON *jobNode) } static int ParseTrigger_(const TriggerWorkSpace *workSpace, - const cJSON *triggerItem, int (*checkJobValid)(const char *jobName)) + const cJSON *triggerItem, int (*checkJobValid)(const char *jobName), const ConfigContext *cfgContext) { PARAM_CHECK(triggerItem != NULL, return -1, "Invalid file"); PARAM_CHECK(workSpace != NULL, return -1, "Failed to create trigger list"); @@ -260,16 +260,17 @@ static int ParseTrigger_(const TriggerWorkSpace *workSpace, char *content = NULL; ret = GetCommandInfo(cmdLineStr, &cmdKeyIndex, &content); PARAM_CHECK(ret == 0, continue, "Command not support %s", cmdLineStr); - ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, cfgContext); PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr); header->cmdNodeCount++; } return 0; } -int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName)) +int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context) { PARAM_CHECK(fileRoot != NULL, return -1, "Invalid file"); + ConfigContext *cfgContext = (ConfigContext *)context; cJSON *triggers = cJSON_GetObjectItemCaseSensitive(fileRoot, TRIGGER_ARR_NAME_IN_JSON); if (triggers == NULL || !cJSON_IsArray(triggers)) { return 0; @@ -279,7 +280,7 @@ int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *j for (int i = 0; i < size && i < TRIGGER_MAX_CMD; ++i) { cJSON *item = cJSON_GetArrayItem(triggers, i); - ParseTrigger_(&g_triggerWorkSpace, item, checkJobValid); + ParseTrigger_(&g_triggerWorkSpace, item, checkJobValid, cfgContext); /* * execute job parsing hooks */ @@ -385,7 +386,7 @@ int AddCompleteJob(const char *name, const char *condition, const char *cmdConte int cmdKeyIndex = 0; int ret = GetCommandInfo(cmdContent, &cmdKeyIndex, &content); PARAM_CHECK(ret == 0, return -1, "Command not support %s", cmdContent); - ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, NULL); // use default context PARAM_CHECK(ret == 0, return -1, "Failed to add command %s", cmdContent); header->cmdNodeCount++; PARAM_LOGV("AddCompleteJob %s type %d count %d", name, type, header->triggerCount); diff --git a/services/utils/init_hashmap.c b/services/utils/init_hashmap.c index fc67e7b2..2e744e59 100644 --- a/services/utils/init_hashmap.c +++ b/services/utils/init_hashmap.c @@ -163,8 +163,8 @@ HashNode *OH_HashMapFind(HashMapHandle handle, INIT_ERROR_CHECK(handle != NULL, return NULL, "Invalid hash handle"); INIT_ERROR_CHECK(key != NULL && keyCompare != NULL, return NULL, "Invalid hash key"); HashTab *tab = (HashTab *)handle; - INIT_ERROR_CHECK(hashCode < tab->maxBucket, return NULL, - "Invalid hashcode %d %d", tab->maxBucket, hashCode); + INIT_ERROR_CHECK((hashCode < tab->maxBucket) && (hashCode >= 0), return NULL, + "Invalid hash code %d %d", tab->maxBucket, hashCode); return GetHashNodeByKey(tab, tab->buckets[hashCode], key, keyCompare); } diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c index 314396d0..d87e9e48 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -187,7 +187,7 @@ char *ReadFileData(const char *fileName) char *buffer = NULL; int fd = -1; fd = open(fileName, O_RDONLY); - INIT_ERROR_CHECK(fd >= 0, return NULL, "Failed to read file %s", fileName); + INIT_ERROR_CHECK(fd >= 0, return NULL, "Failed to read file %s errno:%d", fileName, errno); buffer = (char *)calloc(1, MAX_SMALL_BUFFER); // fsmanager not create, can not get fileStat st_size INIT_ERROR_CHECK(buffer != NULL, close(fd); return NULL, "Failed to allocate memory for %s", fileName); diff --git a/test/moduletest/param_test_module.c b/test/moduletest/param_test_module.c index 37993b1e..f25c2d97 100644 --- a/test/moduletest/param_test_module.c +++ b/test/moduletest/param_test_module.c @@ -20,9 +20,10 @@ #include "init_param.h" #include "modulemgr.h" #include "init_module_engine.h" +#include "init_cmds.h" #include "securec.h" -#define MAX_COUNT 1000 +#define MAX_COUNT 1 #define TEST_CMD_NAME "param_randrom_write" #define READ_DURATION 100000 @@ -54,7 +55,7 @@ static int PluginParamCmdWriteParam(int id, const char *name, int argc, const ch MODULE_CONSTRUCTOR(void) { - g_testCmdIndex = AddCmdExecutor(TEST_CMD_NAME, PluginParamCmdWriteParam); + g_testCmdIndex = AddCareContextCmdExecutor(TEST_CMD_NAME, PluginParamCmdWriteParam); } MODULE_DESTRUCTOR(void) diff --git a/test/moduletest/vendor.init.test.cfg b/test/moduletest/vendor.init.test.cfg new file mode 100644 index 00000000..f415afc5 --- /dev/null +++ b/test/moduletest/vendor.init.test.cfg @@ -0,0 +1,29 @@ +{ + "jobs" : [{ + "name" : "param:test.randrom.read.start=1", + "condition" : "test.randrom.read.start=1", + "cmds" : [ + "param_randrom_write test.randrom.read 100", + "mkdir /data/test_verdor_init 0711 root root", + "start group-test-stage1" + ] + }, + { + "name" : "test_verdor_init_job", + "cmds" : [ + "param_randrom_write test.randrom.read 200", + "mkdir /data/test_verdor_init_2 0711 root root" + ] + } + ], + "services" : [{ + "name" : "group-test-stage1", + "start-mode" : "normal", + "path" : ["/system/bin/begetctl", "init", "group", "test", "group-test-stage1"], + "once" : 1, + "jobs" : { + "on-start" : "test_verdor_init_job" + } + } + ] +} diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index cf9e76d6..eb1979f5 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -393,8 +393,16 @@ ohos_unittest("init_unittest") { include_dirs += [ "//base/startup/init/services/modules/bootevent", + "//base/startup/init/services/modules/init_context", "//base/startup/init/services/modules/sysevent", ] + # test for init sub init_context + sources += [ + "//base/startup/init/services/modules/init_context/init_context_static.c", + "//base/startup/init/services/modules/init_context/init_context.c", + "//base/startup/init/test/unittest/modules/context_unittest.cpp", + ] + cflags_cc = [ "-fexceptions" ] } diff --git a/test/unittest/init/cmds_unittest.cpp b/test/unittest/init/cmds_unittest.cpp index 1b2d28b2..cc3c91f1 100644 --- a/test/unittest/init/cmds_unittest.cpp +++ b/test/unittest/init/cmds_unittest.cpp @@ -24,6 +24,13 @@ using namespace testing::ext; using namespace std; +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, NULL); +} + namespace init_ut { class CmdsUnitTest : public testing::Test { public: @@ -203,13 +210,13 @@ HWTEST_F(CmdsUnitTest, TestGetCmdKey, TestSize.Level1) HWTEST_F(CmdsUnitTest, TestDoCmdByIndex, TestSize.Level1) { - DoCmdByIndex(1, "/data/init_ut/test_cmd_dir0"); + DoCmdByIndex(1, "/data/init_ut/test_cmd_dir0", nullptr); int ret = access("/data/init_ut/test_cmd_dir0", F_OK); EXPECT_EQ(ret, 0); const int execPos = 17; - DoCmdByIndex(execPos, "sleep 1"); - DoCmdByIndex(23, "test"); // 23 is cmd index + DoCmdByIndex(execPos, "sleep 1", nullptr); + DoCmdByIndex(23, "test", nullptr); // 23 is cmd index } HWTEST_F(CmdsUnitTest, TestGetCmdLinesFromJson, TestSize.Level1) diff --git a/test/unittest/init/group_unittest.cpp b/test/unittest/init/group_unittest.cpp index 0896e338..16c5f8b3 100644 --- a/test/unittest/init/group_unittest.cpp +++ b/test/unittest/init/group_unittest.cpp @@ -90,6 +90,13 @@ static TestHashNode *TestCreateHashNode(const char *value) return node; } +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, NULL); +} + namespace init_ut { class InitGroupManagerUnitTest : public testing::Test { public: @@ -217,7 +224,8 @@ HWTEST_F(InitGroupManagerUnitTest, TestAddService, TestSize.Level1) cJSON *fileRoot = cJSON_Parse(serviceStr); ASSERT_NE(nullptr, fileRoot); - ParseAllServices(fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); cJSON_Delete(fileRoot); Service *service = GetServiceByName("test-service"); @@ -276,7 +284,8 @@ HWTEST_F(InitGroupManagerUnitTest, TestAddServiceDeny, TestSize.Level1) cJSON *fileRoot = cJSON_Parse(serviceStr); ASSERT_NE(nullptr, fileRoot); - ParseAllServices(fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); cJSON_Delete(fileRoot); Service *service = GetServiceByName("test-service5"); @@ -309,7 +318,8 @@ HWTEST_F(InitGroupManagerUnitTest, TestAddService2, TestSize.Level1) cJSON *fileRoot = cJSON_Parse(serviceStr); ASSERT_NE(nullptr, fileRoot); - ParseAllServices(fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); cJSON_Delete(fileRoot); char cmdStr[] = "all#bootevent"; char cmdStr1[] = "parameter_service"; diff --git a/test/unittest/init/service_unittest.cpp b/test/unittest/init/service_unittest.cpp index d6f0d4e5..c89c194e 100644 --- a/test/unittest/init/service_unittest.cpp +++ b/test/unittest/init/service_unittest.cpp @@ -30,6 +30,13 @@ #include "init_hook.h" #include "plugin_adapter.h" +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, NULL); +} + using namespace testing::ext; using namespace std; namespace init_ut { @@ -313,7 +320,8 @@ HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1) cJSON *fileRoot = cJSON_Parse(serviceStr); ASSERT_NE(nullptr, fileRoot); PluginExecCmd("clear", 0, nullptr); - ParseAllServices(fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), NULL); serviceInfoContext.reserved = NULL; (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), NULL); diff --git a/test/unittest/innerkits/modulemgr_unittest.cpp b/test/unittest/innerkits/modulemgr_unittest.cpp index bf88ea54..ae4542b8 100644 --- a/test/unittest/innerkits/modulemgr_unittest.cpp +++ b/test/unittest/innerkits/modulemgr_unittest.cpp @@ -72,7 +72,7 @@ HWTEST_F(ModuleMgrUnitTest, PluginAddCmd, TestSize.Level1) PluginExecCmdByName(cmdName, nullptr); PluginExecCmdByName(cmdName, cmdContentNotValid); g_cmdExecId = -1; - PluginExecCmdByCmdIndex(cmdIndex, cmdContent); + PluginExecCmdByCmdIndex(cmdIndex, cmdContent, nullptr); ASSERT_EQ(cmdExecId1, g_cmdExecId); const char *argv[] = {"test.value"}; PluginExecCmd("install", 1, argv); diff --git a/test/unittest/lite/cmd_func_test.cpp b/test/unittest/lite/cmd_func_test.cpp index f1f16c28..f1fecd81 100644 --- a/test/unittest/lite/cmd_func_test.cpp +++ b/test/unittest/lite/cmd_func_test.cpp @@ -157,8 +157,9 @@ void DoCmd(const TestCmdLine *resCmd) if (resCmd == nullptr) { return; } - - DoCmdByName(resCmd->name, resCmd->cmdContent); + int cmdIndex = 0; + (void)GetMatchCmd(resCmd->name, &cmdIndex); + DoCmdByIndex(cmdIndex, resCmd->cmdContent, NULL); } /* @@ -927,7 +928,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level0) HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level0) { // functions do not crash - ParseAllJobs(nullptr); + ParseAllJobs(nullptr, nullptr); DoJob(nullptr); DoJob("job name does not exist"); ReleaseAllJobs(); @@ -953,7 +954,8 @@ HWTEST_F(StartupInitUTest, cmdJobTest_002, TestSize.Level0) if (jobItem == nullptr) { return; } - ParseAllJobs(jobItem); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllJobs(jobItem, &context); DoJob("pre-init"); DoJob("init"); DoJob("post-init"); diff --git a/test/unittest/modules/context_unittest.cpp b/test/unittest/modules/context_unittest.cpp new file mode 100755 index 00000000..b941cc6f --- /dev/null +++ b/test/unittest/modules/context_unittest.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 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_context.h" + +#include "param_stub.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +class InitContextUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(InitContextUnitTest, InitSubContextTest_01, TestSize.Level1) +{ + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_EQ(ret, 0); + ret = StartSubInit(INIT_CONTEXT_MAIN); + EXPECT_NE(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_02, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, 0); + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext1"); + EXPECT_EQ(ret, 0); + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext2"); + EXPECT_EQ(ret, 0); + context.type = INIT_CONTEXT_MAIN; + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_NE(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_03, TestSize.Level1) +{ + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_EQ(ret, 0); + SubInitInfo *subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo == NULL) { + EXPECT_EQ(1, 0); + } else { + EXPECT_EQ(2, subInfo->state); + StopSubInit(subInfo->subPid); + } +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_04, TestSize.Level1) +{ + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_EQ(ret, 0); + SubInitInfo *subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo != NULL) { + EXPECT_EQ(2, subInfo->state); + StopSubInit(subInfo->subPid); + } else { + EXPECT_EQ(1, 0); + } + // close + subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo != NULL) { + EXPECT_EQ(0, subInfo->state); + } +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_05, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int ret = ExecuteCmdInSubInit(&context, "mkdir-2", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_06, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int index = 0; + const char *cmd = GetMatchCmd("mkdir ", &index); + if (cmd == nullptr || strstr(cmd, "mkdir ") == nullptr) { + EXPECT_EQ(1, 0); + return; + } + DoCmdByIndex(index, STARTUP_INIT_UT_PATH"/testsubcontext", &context); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_07, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_MAIN }; + int index = 0; + const char *cmd = GetMatchCmd("mkdir ", &index); + if (cmd == nullptr || strstr(cmd, "mkdir ") == nullptr) { + EXPECT_EQ(1, 0); + return; + } + DoCmdByIndex(index, STARTUP_INIT_UT_PATH"/testsubcontext", &context); +} +} // namespace init_ut diff --git a/test/unittest/modules/trace_unittest.cpp b/test/unittest/modules/trace_unittest.cpp index 5c7eb4c2..4ad8deab 100644 --- a/test/unittest/modules/trace_unittest.cpp +++ b/test/unittest/modules/trace_unittest.cpp @@ -139,7 +139,10 @@ HWTEST_F(TraceUnitTest, TraceTest_004, TestSize.Level1) { std::string cmdArgs = "/system/etc/init_trace.cfg "; cmdArgs += STARTUP_INIT_UT_PATH"/system/etc/init_trace.cfg"; - DoCmdByName("copy ", cmdArgs.c_str()); + int cmdIndex = 0; + (void)GetMatchCmd("copy ", &cmdIndex); + DoCmdByIndex(cmdIndex, cmdArgs.c_str(), NULL); + // start trace PluginExecCmdByName("init_trace", "start"); // for run 1 s diff --git a/test/unittest/param/trigger_unittest.cpp b/test/unittest/param/trigger_unittest.cpp index 2b8005c6..20779a47 100644 --- a/test/unittest/param/trigger_unittest.cpp +++ b/test/unittest/param/trigger_unittest.cpp @@ -87,7 +87,7 @@ public: INIT_ERROR_CHECK(fileBuf != nullptr, return -1, "Failed to read file content %s", configFile); cJSON *fileRoot = cJSON_Parse(fileBuf); INIT_ERROR_CHECK(fileRoot != nullptr, return -1, "Failed to parse json file %s", configFile); - ParseTriggerConfig(fileRoot, nullptr); + ParseTriggerConfig(fileRoot, nullptr, nullptr); cJSON_Delete(fileRoot); free(fileBuf); fileBuf = nullptr; @@ -137,9 +137,9 @@ public: // add command int cmdIndex = 0; GetMatchCmd("reboot ", &cmdIndex); - int ret = AddCommand(trigger, cmdIndex, nullptr); + int ret = AddCommand(trigger, cmdIndex, nullptr, nullptr); EXPECT_EQ(ret, 0); - ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa"); + ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa", nullptr); EXPECT_EQ(ret, 0); return 0; } @@ -160,9 +160,9 @@ public: // add command int cmdIndex = 0; GetMatchCmd("reboot ", &cmdIndex); - int ret = AddCommand(trigger, cmdIndex, nullptr); + int ret = AddCommand(trigger, cmdIndex, nullptr, nullptr); EXPECT_EQ(ret, 0); - ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa"); + ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa", nullptr); EXPECT_EQ(ret, 0); return 0; } @@ -361,7 +361,7 @@ public: EXPECT_EQ(trigger, node); const uint32_t cmdIndex = 100; - ret = AddCommand(trigger, cmdIndex, value); + ret = AddCommand(trigger, cmdIndex, value, nullptr); EXPECT_EQ(ret, 0); // 修改命令为测试执行 RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); @@ -383,7 +383,7 @@ public: JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); EXPECT_EQ(trigger, node); const uint32_t cmdIndex = 102; - ret = AddCommand(trigger, cmdIndex, value); + ret = AddCommand(trigger, cmdIndex, value, nullptr); EXPECT_EQ(ret, 0); RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); SystemWriteParam(param, value); @@ -408,7 +408,7 @@ public: return -1; } const uint32_t cmdIndex = 103; - ret = AddCommand(trigger, cmdIndex, value); + ret = AddCommand(trigger, cmdIndex, value, nullptr); EXPECT_EQ(ret, 0); TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_ONCE); SystemWriteParam(param, value); @@ -439,7 +439,7 @@ public: return -1; } const uint32_t cmdIndex = 105; - ret = AddCommand(trigger, cmdIndex, value); + ret = AddCommand(trigger, cmdIndex, value, nullptr); EXPECT_EQ(ret, 0); TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_ONCE); SystemWriteParam(param, value); @@ -464,7 +464,7 @@ public: const char *value = "5555"; JobNode *trigger = AddTrigger(TRIGGER_BOOT, boot, nullptr, 0); const int testCmdIndex = 1105; - int ret = AddCommand(trigger, testCmdIndex, value); + int ret = AddCommand(trigger, testCmdIndex, value, nullptr); EXPECT_EQ(ret, 0); if (trigger == nullptr) { return -1; @@ -476,7 +476,7 @@ public: EXPECT_GE(ret, 0); trigger = AddTrigger(TRIGGER_UNKNOW, triggerName, buffer, 0); const int testCmdIndex2 = 105; - ret = AddCommand(trigger, testCmdIndex2, value); + ret = AddCommand(trigger, testCmdIndex2, value, nullptr); RegisterTriggerExec(TRIGGER_UNKNOW, TestCmdExec); SystemWriteParam(param, value); -- GitLab