提交 01ff09c3 编写于 作者: C cheng_jinsong

feature vendor init

Signed-off-by: Ncheng_jinsong <chengjinsong2@huawei.com>
上级 b392a484
......@@ -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);
......
......@@ -21,5 +21,8 @@
{ "name": "AddRebootCmdExecutor" },
{ "name": "GetBootEventList" },
{ "name": "WaitForFile" },
{ "name": "DoCmdByName" }
{ "name": "DoCmdByIndex" },
{ "name": "GetMatchCmd" },
{ "name": "AddCareContextCmdExecutor" },
{ "name": "InitSubInitContext" }
]
......@@ -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);
/**
* 对外接口
......
......@@ -22,6 +22,7 @@
#include <time.h>
#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
}
......
......@@ -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);
......
......@@ -160,6 +160,7 @@ typedef struct Service_ {
ServiceJobs serviceJobs;
cpu_set_t *cpuSet;
struct ListNode extDataNode;
ConfigContext context;
} Service;
#pragma pack()
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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;
}
......@@ -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);
}
}
}
......
......@@ -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",
]
......
......@@ -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)
......
......@@ -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)
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
......@@ -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",
......
# 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"
}
/*
* 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 <poll.h>
#include <policycoreutils.h>
#include <selinux/selinux.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#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);
}
}
/*
* 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 <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#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
/*
* 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);
}
......@@ -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)
......
......@@ -18,6 +18,7 @@
#include <stdint.h>
#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);
......
......@@ -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) {
......
......@@ -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++;
}
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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)
......
{
"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"
}
}
]
}
......@@ -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" ]
}
......@@ -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)
......
......@@ -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";
......
......@@ -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);
......
......@@ -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);
......
......@@ -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");
......
/*
* 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
......@@ -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
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册