diff --git a/interfaces/innerkits/reboot/init_reboot.c b/interfaces/innerkits/reboot/init_reboot.c index e2e3fb4ba795e139465e14c05975b3b54325a9f2..6e6df19934c8d6c38e40cac8034fc50ec9131976 100644 --- a/interfaces/innerkits/reboot/init_reboot.c +++ b/interfaces/innerkits/reboot/init_reboot.c @@ -14,49 +14,49 @@ */ #include "init_reboot.h" -#include #include #include #include + #include "init_log.h" +#include "param.h" #include "securec.h" #include "sys_param.h" -#define SYS_POWER_CTRL "sys.powerctrl=" -#define MAX_REBOOT_NAME_SIZE 100 -#define MAX_REBOOT_VAUE_SIZE 500 +// Refer to parameter limit, value size should not bigger than 96 +#define MAX_REBOOT_OPTION_SIZE PARAM_VALUE_LEN_MAX -int DoReboot(const char *cmdContent) +int DoReboot(const char *option) { - uid_t uid1 = getuid(); - uid_t uid2 = geteuid(); - if (uid1 != 0 || uid2 != 0) { - INIT_LOGE("uid1=%d, uid2=%d, user MUST be root, error!", uid1, uid2); + uid_t uid = getuid(); + uid_t euid = geteuid(); + if (uid != 0 || euid != 0) { + INIT_LOGE("User or effective user MUST be root, abort!"); return -1; } - char value[MAX_REBOOT_VAUE_SIZE]; - if (cmdContent == NULL || strlen(cmdContent) == 0) { - if (snprintf_s(value, MAX_REBOOT_NAME_SIZE, strlen("reboot") + 1, "%s", "reboot") < 0) { - INIT_LOGE("DoReboot api error, MAX_REBOOT_NAME_SIZE is not enough"); + char value[MAX_REBOOT_OPTION_SIZE]; + if (option == NULL || strlen(option) == 0) { + if (snprintf_s(value, MAX_REBOOT_OPTION_SIZE, strlen("reboot") + 1, "%s", "reboot") < 0) { + INIT_LOGE("reboot options too large, overflow"); return -1; } if (SystemSetParameter("sys.powerctrl", value) != 0) { - INIT_LOGE("DoReboot Api SystemSetParameter error"); + INIT_LOGE("Set parameter to trigger reboot command \" %s \" failed", value); return -1; } return 0; } - size_t length = strlen(cmdContent); - if (length > MAX_REBOOT_VAUE_SIZE) { - INIT_LOGE("DoReboot api error, cmdContent = %s, length = %d.", cmdContent, length); + int length = strlen(option); + if (length > MAX_REBOOT_OPTION_SIZE) { + INIT_LOGE("Reboot option \" %s \" is too large, overflow", option); return -1; } - if (snprintf_s(value, MAX_REBOOT_NAME_SIZE, MAX_REBOOT_NAME_SIZE - 1, "%s%s", "reboot,", cmdContent) < 0) { - INIT_LOGE("DoReboot api error, MAX_REBOOT_NAME_SIZE is not enough"); + if (snprintf_s(value, MAX_REBOOT_OPTION_SIZE, MAX_REBOOT_OPTION_SIZE - 1, "%s%s", "reboot,", option) < 0) { + INIT_LOGE("Failed to copy boot option \" %s \"", option); return -1; } if (SystemSetParameter("sys.powerctrl", value) != 0) { - INIT_LOGE("DoReboot Api SystemSetParameter error"); + INIT_LOGE("Set parameter to trigger reboot command \" %s \" failed", value); return -1; } return 0; diff --git a/services/BUILD.gn b/services/BUILD.gn index 9b8bb8603a66b864f0a5e2bc950515f3616b2836..80ce41238df4ebfa18e36e84540f401a63155d55 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -10,6 +10,20 @@ # 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. + +init_common_sources = [ + "init/init_cmds.c", + "init/init_config.c", + "init/init_service.c", + "init/init_service_manager.c", + "init/init_service_socket.c", + "init/init_capability.c", + "init/main.c", + "log/init_log.c", + "utils/init_utils.c", + "utils/list.c", +] + if (defined(ohos_lite)) { # feature: init executable("init_lite") { @@ -19,25 +33,20 @@ if (defined(ohos_lite)) { "OHOS_LITE", ] sources = [ - "log/init_log.c", - "src/init_adapter.c", - "src/init_capability.c", - "src/init_cmds.c", - "src/init_import.c", - "src/init_jobs.c", - "src/init_read_cfg.c", - "src/init_reboot.c", - "src/init_service.c", - "src/init_service_manager.c", - "src/init_service_socket.c", - "src/init_signal_handler.c", - "src/init_utils.c", - "src/main.c", + "init/adapter/init_adapter.c", + "init/lite/init.c", + "init/lite/init_cmds.c", + "init/lite/init_jobs.c", + "init/lite/init_reboot.c", + "init/lite/init_service.c", + "init/lite/init_signal_handler.c", ] + sources += init_common_sources + include_dirs = [ "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/param/include", + "//base/startup/init_lite/services/init/include", "//base/startup/init_lite/services/log", "//third_party/cJSON", "//third_party/bounds_checking_function/include", @@ -87,30 +96,30 @@ if (defined(ohos_lite)) { ohos_executable("init") { sources = [ - "src/device.c", - "src/init_adapter.c", - "src/init_capability.c", - "src/init_cmds.c", - "src/init_import.c", - "src/init_jobs.c", - "src/init_read_cfg.c", - "src/init_reboot.c", - "src/init_service.c", - "src/init_service_manager.c", - "src/init_service_socket.c", - "src/init_signal_handler.c", - "src/init_utils.c", - "src/main.c", + "init/adapter/init_adapter.c", + "init/standard/init.c", + "init/standard/init_cmds.c", + "init/standard/init_jobs.c", + "init/standard/init_reboot.c", + "init/standard/init_service.c", + "init/standard/init_signal_handler.c", + "init/standard/device.c", ] + + sources += init_common_sources + include_dirs = [ "//base/startup/init_lite/services/include/param", "//base/startup/init_lite/services/include", + "//base/startup/init_lite/services/init/include", "//base/startup/init_lite/services/log", + "//base/startup/init_lite/interfaces/innerkits/include", "//third_party/cJSON", "//third_party/bounds_checking_function/include", "//third_party/libuv/include", ] deps = [ + "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfs_manager", "//base/startup/init_lite/services/log:init_log", "//base/startup/init_lite/services/param:param_service", "//third_party/bounds_checking_function:libsec_static", @@ -135,6 +144,7 @@ if (defined(ohos_lite)) { ":init", ":init_etc", "//base/startup/init_lite/interfaces/innerkits/dynamic_service:dynamic_service", + "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfs_manager", "//base/startup/init_lite/interfaces/innerkits/socket:libsocket", "//base/startup/init_lite/services/cmds/reboot:reboot", "//base/startup/init_lite/services/cmds/service_control:service_control", diff --git a/services/etc/init.cfg b/services/etc/init.cfg index e0e54bea5dad413423b8e87cbe06653b28cb6eec..552ad42e21ae3051f29c659a42b05998deaf0610 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -386,8 +386,8 @@ "write /proc/sys/kernel/perf_event_paranoid 3" ] }, { - "name" : "boot && param:ro.debuggable=1", - "condition" : "boot && ro.debuggable=1", + "name" : "boot && param:const.debuggable=1", + "condition" : "boot && const.debuggable=1", "cmds" : [ "chmod 0773 /data/misc/trace", "chmod 0775 /data/misc/wmtrace", diff --git a/services/etc/param/ohos.para b/services/etc/param/ohos.para index f53e55ad3588c8a2cb9cd2054a60bae68ebb52b6..8c910abe86de563bbfe64f5917e2ebfe2d50a859 100755 --- a/services/etc/param/ohos.para +++ b/services/etc/param/ohos.para @@ -27,13 +27,13 @@ hw_sc.build.os.version=2.2.0 # ohos release type hw_sc.build.os.releasetype=Canary1 -ro.actionable_compatible_property.enabled=false -ro.postinstall.fstab.prefix=/system -ro.secure=1 +const.actionable_compatible_property.enabled=false +const.postinstall.fstab.prefix=/system +const.secure=1 security.perf_harden=1 -ro.allow.mock.location=0 -ro.debuggable=1 -ro.build.characteristics="default" -ro.product.model="ohos" -ro.product.name="OpenHarmony 2.0 Canary" +const.allow.mock.location=0 +const.debuggable=1 +const.build.characteristics="default" +const.product.model="ohos" +const.product.name="OpenHarmony 2.0 Canary" persist.sys.usb.config=hdc diff --git a/services/include/init_capability.h b/services/include/init_capability.h deleted file mode 100644 index 842959e73e0cc043949640656e435d7aa01e8d26..0000000000000000000000000000000000000000 --- a/services/include/init_capability.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef INIT_CAPABILITY_H -#define INIT_CAPABILITY_H - -#include "cJSON.h" -#include "init_service.h" - -int GetServiceCaps(const cJSON* curArrItem, Service* curServ); - -#endif - diff --git a/services/include/init_import.h b/services/include/init_import.h deleted file mode 100644 index 5def1efa8c212517ea3f09afeb04729deccdfd8d..0000000000000000000000000000000000000000 --- a/services/include/init_import.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef BASE_STARTUP_INITLITE_IMPORT_H -#define BASE_STARTUP_INITLITE_IMPORT_H - -#include "cJSON.h" -void ParseAllImports(const cJSON *root); - -#endif diff --git a/services/include/init_utils.h b/services/include/init_utils.h index 17fe242393445c3df804033e98f5b46d8b024dca..e0ffdfa8aa9e011105fdad28f9412d433d0062a2 100644 --- a/services/include/init_utils.h +++ b/services/include/init_utils.h @@ -15,7 +15,8 @@ #ifndef INIT_UTILS_H #define INIT_UTILS_H - +#include +#include #include #ifdef __cplusplus @@ -27,13 +28,21 @@ extern "C" { #define BINARY_BASE 2 #define OCTAL_BASE 8 #define DECIMAL_BASE 10 +#define WAIT_MAX_COUNT 10 #define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0])) + uid_t DecodeUid(const char *name); -char* ReadFileToBuf(const char *configFile); +char *ReadFileToBuf(const char *configFile); int SplitString(char *srcPtr, char **dstPtr, int maxNum); void WaitForFile(const char *source, unsigned int maxCount); size_t WriteAll(int fd, char *buffer, size_t size); +char *Realpath(const char *source, char *resolvedPath, size_t resolvedPathSize); +int StringToInt(const char *str, int defaultValue); +int MakeDirRecursive(const char *dir, mode_t mode); +int MakeDir(const char *dir, mode_t mode); +int ReadFileInDir(const char *dirPath, const char *includeExt, + int (*processFile)(const char *fileName, void *context), void *context); #ifdef __cplusplus #if __cplusplus } diff --git a/services/src/init_adapter.c b/services/init/adapter/init_adapter.c old mode 100644 new mode 100755 similarity index 73% rename from services/src/init_adapter.c rename to services/init/adapter/init_adapter.c index 2788e646fba3d7f7daeb4b980d9f6c9c78456e92..20521101a7f7fb9944add78ceb2bfa233dc04af4 --- a/services/src/init_adapter.c +++ b/services/init/adapter/init_adapter.c @@ -12,23 +12,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "init_adapter.h" - #include +#include #include -#include #include #include +#include +#if defined OHOS_LITE && !defined __LINUX__ +#include +#else +#include +#endif + #if ((defined __LINUX__) || (!defined OHOS_LITE)) #include #endif -#ifdef __LINUX__ -#include "init_signal_handler.h" -#endif #include "init_log.h" -void RebootSystem() +void RebootSystem(void) { int ret = reboot(RB_AUTOBOOT); if (ret != 0) { @@ -36,7 +38,7 @@ void RebootSystem() } } -int KeepCapability() +int KeepCapability(void) { #if ((defined __LINUX__) || (!defined OHOS_LITE)) if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) { @@ -58,7 +60,33 @@ int SetAmbientCapability(int cap) return 0; } -void ExecuteRcs() +#ifdef __LINUX__ +static pid_t g_waitPid = -1; +static sem_t *g_waitSem = NULL; +static void SignalRegWaitSem(pid_t waitPid, sem_t *waitSem) +{ + g_waitPid = waitPid; + g_waitSem = waitSem; +} + +void CheckWaitPid(pid_t sigPID) +{ + if (g_waitPid == sigPID && g_waitSem != NULL) { + if (sem_post(g_waitSem) != 0) { + INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno); + } + g_waitPid = -1; + g_waitSem = NULL; + } +} +#else +void CheckWaitPid(pid_t sigPID) +{ + UNUSED(sigPID) +} +#endif + +void SystemExecuteRcs(void) { #if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX) pid_t retPid = fork(); @@ -90,4 +118,3 @@ void ExecuteRcs() } #endif } - diff --git a/services/include/device.h b/services/init/include/device.h old mode 100644 new mode 100755 similarity index 95% rename from services/include/device.h rename to services/init/include/device.h index beef68ff448588e6cd95ddfec04ecc422d830d43..1526ecdf6aa96b6b750e55dfe449472185a391f4 --- a/services/include/device.h +++ b/services/init/include/device.h @@ -30,7 +30,7 @@ extern "C" { void MountBasicFs(void); void CreateDeviceNode(void); -int MakeSocketDir(const char *path, mode_t mode); +int MakeSocketDir(mode_t mode); void CloseStdio(void); #ifdef __cplusplus diff --git a/services/include/init_read_cfg.h b/services/init/include/init.h old mode 100644 new mode 100755 similarity index 52% rename from services/include/init_read_cfg.h rename to services/init/include/init.h index 4cb57e130f98b570e9bb792492d3026ad04b1f93..1b63e40dc26255ef38b3d2e1ed83d21508f38f71 --- a/services/include/init_read_cfg.h +++ b/services/init/include/init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,25 +13,39 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_READ_CFG_H -#define BASE_STARTUP_INITLITE_READ_CFG_H +#ifndef BASE_STARTUP_INIT_H +#define BASE_STARTUP_INIT_H #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -#define INIT_CONFIGURATION_FILE "/etc/init.cfg" -#define MAX_PATH_ARGS_CNT 20 -#define MAX_ONE_ARG_LEN 200 // max length of one param/path -void InitReadCfg(); -void ParseInitCfg(const char *configFile); +#ifndef PARAM_VALUE_LEN_MAX +#define PARAM_VALUE_LEN_MAX 96 +#endif + +#define PROCESS_EXIT_CODE 0x7f // 0x7f: user specified +// kit framework +#define DEFAULT_UID_KIT_FRAMEWORK 3 +// max length of one param/path +#define MAX_ONE_ARG_LEN 200 + +#define UNUSED(x) (void)(x) + +void SystemInit(void); +void SystemPrepare(void); +void SystemConfig(void); +void SystemRun(void); +void SystemExecuteRcs(void); + +void ReadConfig(void); +void SignalInit(void); #ifdef __cplusplus #if __cplusplus } #endif #endif - -#endif // BASE_STARTUP_INITLITE_READ_CFG_H +#endif // BASE_STARTUP_INIT_H diff --git a/services/include/init_adapter.h b/services/init/include/init_adapter.h old mode 100644 new mode 100755 similarity index 68% rename from services/include/init_adapter.h rename to services/init/include/init_adapter.h index ea02c1e06b7fd1ef97c7f649080263cc3e079e13..28ca72b0ebe48d6850ae03181a08e04f4f52e046 --- a/services/include/init_adapter.h +++ b/services/init/include/init_adapter.h @@ -15,13 +15,7 @@ #ifndef BASE_STARTUP_INITLITE_ADAPTER_H #define BASE_STARTUP_INITLITE_ADAPTER_H - -#if defined OHOS_LITE && !defined __LINUX__ -#include -#else -#include -#endif - +#include #ifdef __cplusplus #if __cplusplus extern "C" { @@ -31,27 +25,27 @@ extern "C" { #ifndef OHOS_LITE /* Control the ambient capability set */ #ifndef PR_CAP_AMBIENT -#define PR_CAP_AMBIENT 47 +#define PR_CAP_AMBIENT 47 #endif #ifndef PR_CAP_AMBIENT_IS_SET -#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_IS_SET 1 #endif #ifndef PR_CAP_AMBIENT_RAISE -#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_RAISE 2 #endif #ifndef PR_CAP_AMBIENT_LOWER -#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT_LOWER 3 #endif #ifndef PR_CAP_AMBIENT_CLEAR_ALL -#define PR_CAP_AMBIENT_CLEAR_ALL 4 +#define PR_CAP_AMBIENT_CLEAR_ALL 4 #endif -extern int capset(void *a, void *b); #endif -void RebootSystem(); -int KeepCapability(); +void RebootSystem(void); +int KeepCapability(void); int SetAmbientCapability(int cap); -void ExecuteRcs(); +void ExecuteRcs(void); +void CheckWaitPid(pid_t sigPID); #ifdef __cplusplus #if __cplusplus @@ -59,4 +53,4 @@ void ExecuteRcs(); #endif #endif -#endif // BASE_STARTUP_INITLITE_ADAPTER_H \ No newline at end of file +#endif // BASE_STARTUP_INITLITE_ADAPTER_H \ No newline at end of file diff --git a/services/include/init_cmds.h b/services/init/include/init_cmds.h old mode 100644 new mode 100755 similarity index 37% rename from services/include/init_cmds.h rename to services/init/include/init_cmds.h index 343ec32d5980ddb2beae8ff91e68a275baa7f5d0..71c6f18c218b2ed2fd33e0f76c5c943c853ede70 --- a/services/include/init_cmds.h +++ b/services/init/include/init_cmds.h @@ -13,54 +13,71 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_CMDS_H -#define BASE_STARTUP_INITLITE_CMDS_H - +#ifndef BASE_STARTUP_INIT_CMDS_H +#define BASE_STARTUP_INIT_CMDS_H +#include +#include +#include +#include +#include "cJSON.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif +#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode +#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline +#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline + +#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline +#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K +#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop +#define OCTAL_TYPE 8 // 8 means octal to decimal +#define MAX_BUFFER 256UL +#define AUTHORITY_MAX_SIZE 128 + #define MAX_CMD_NAME_LEN 32 #define MAX_CMD_CONTENT_LEN 256 #define MAX_CMD_CNT_IN_ONE_JOB 200 #define MAX_COPY_BUF_SIZE 256 #define DEFAULT_COPY_ARGS_CNT 2 -#ifndef OHOS_LITE -// Limit max length of parameter value to 96 -#define MAX_PARAM_VALUE_LEN 96 -// Limit max length of parameter name to 96 -#define MAX_PARAM_NAME_LEN 96 -#else -// For lite ohos, do not support parameter operation -#define MAX_PARAM_VALUE_LEN 0 -#define MAX_PARAM_NAME_LEN 0 -#endif - +#define SUPPORT_MAX_ARG_FOR_EXEC 10 // one cmd line typedef struct { - char name[MAX_CMD_NAME_LEN + 1]; + int cmdIndex; char cmdContent[MAX_CMD_CONTENT_LEN + 1]; } CmdLine; +typedef struct { + int cmdNum; + CmdLine cmds[0]; +} CmdLines; + struct CmdArgs { int argc; - char **argv; + char *argv[0]; }; -int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen); -struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount); -void FreeCmd(struct CmdArgs *cmd); - -void ParseCmdLine(const char* cmdStr, CmdLine* resCmd); -void DoCmd(const CmdLine* curCmd); +struct CmdTable { + char name[MAX_CMD_NAME_LEN]; + unsigned char minArg; + unsigned char maxArg; + void (*DoFuncion)(const struct CmdArgs *ctx, const char *cmdContent); +}; +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); -const char *GetMatchCmd(const char *cmdStr, unsigned int *index); -const char *GetCmdKey(unsigned int index); - +void DoCmdByIndex(int index, const char *cmdContent); +const char *GetMatchCmd(const char *cmdStr, int *index); +const char *GetCmdKey(int index); +const struct CmdTable *GetCmdTable(int *number); +int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines); +const struct CmdTable *GetCmdByName(const char *name); +void ExecReboot(const char *value); #ifdef __cplusplus #if __cplusplus } diff --git a/services/include/init_jobs.h b/services/init/include/init_jobs.h old mode 100644 new mode 100755 similarity index 78% rename from services/include/init_jobs.h rename to services/init/include/init_jobs.h index 47937a77e3196a8c646df06521442684ffdaad5e..fbf57f4cc024b0835d9cb2d3f06b46d8596052d7 --- a/services/include/init_jobs.h +++ b/services/init/include/init_jobs.h @@ -15,9 +15,8 @@ #ifndef BASE_STARTUP_INITLITE_JOBS_H #define BASE_STARTUP_INITLITE_JOBS_H - -#include "init_cmds.h" #include "cJSON.h" +#include "init_cmds.h" #ifdef __cplusplus #if __cplusplus @@ -30,14 +29,20 @@ extern "C" { // one job, could have many cmd lines typedef struct { char name[MAX_JOB_NAME_LEN + 1]; - int cmdLinesCnt; - CmdLine* cmdLines; + CmdLines *cmdLines; } Job; -void ParseAllJobs(const cJSON* fileRoot); -void DoJob(const char* jobName); +void ParseAllJobs(const cJSON *fileRoot); +void DoJob(const char *jobName); void ReleaseAllJobs(void); void DumpAllJobs(void); + +#define INIT_CONFIGURATION_FILE "/etc/init.cfg" +#define OTHER_CFG_PATH "/system/etc/init" +#define MAX_PATH_ARGS_CNT 20 + +void ReadConfig(void); + #ifdef __cplusplus #if __cplusplus } diff --git a/services/include/init_service.h b/services/init/include/init_service.h old mode 100644 new mode 100755 similarity index 50% rename from services/include/init_service.h rename to services/init/include/init_service.h index 69d5e643a2bc9070b23e3ecbefec8f10ac219a45..bf5ccea5d5b04f1782f16da57fa582ade0f4894b --- a/services/include/init_service.h +++ b/services/init/include/init_service.h @@ -15,11 +15,12 @@ #ifndef BASE_STARTUP_INITLITE_SERVICE_H #define BASE_STARTUP_INITLITE_SERVICE_H - #include + +#include "cJSON.h" #include "init_cmds.h" #include "init_service_socket.h" - +#include "list.h" #ifdef __cplusplus #if __cplusplus extern "C" { @@ -31,19 +32,23 @@ extern "C" { #define SERVICE_SUCCESS 0 // service attributes -#define SERVICE_ATTR_INVALID 0x001 // option invalid -#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits -#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future -#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap -#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash -#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes -#define SERVICE_ATTR_DISABLED 0x040 // disabled -#define SERVICE_ATTR_CONSOLE 0x080 // console -#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service +#define SERVICE_ATTR_INVALID 0x001 // option invalid +#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits +#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future +#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap +#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash +#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes +#define SERVICE_ATTR_DISABLED 0x040 // disabled +#define SERVICE_ATTR_CONSOLE 0x080 // console +#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service #define MAX_SERVICE_NAME 32 #define MAX_WRITEPID_FILES 100 +#define FULL_CAP 0xFFFFFFFF +// init +#define DEFAULT_UMASK_INIT 022 + #define CAP_NUM 2 #define SERVICES_ARR_NAME_IN_JSON "services" @@ -56,31 +61,36 @@ typedef struct { unsigned int capsCnt; } Perms; -struct OnRestartCmd { - CmdLine *cmdLine; - int cmdNum; -}; +typedef struct { + int count; + char **argv; +} ServiceArgs; typedef struct { - char name[MAX_SERVICE_NAME + 1]; - char** pathArgs; - int pathArgsCnt; - int pid; - int crashCnt; + ListNode node; + char name[MAX_SERVICE_NAME + 1]; + int pid; + int crashCnt; time_t firstCrashTime; - int criticalCrashCnt; // count for critical - time_t firstCriticalCrashTime; // record for critical - char *writepidFiles[MAX_WRITEPID_FILES]; unsigned int attribute; - int importance; - Perms servPerm; - struct OnRestartCmd *onRestart; - struct ServiceSocket *socketCfg; + int importance; + Perms servPerm; + ServiceArgs pathArgs; + ServiceArgs writePidArgs; + CmdLines *restartArg; + ServiceSocket *socketCfg; } Service; int ServiceStart(Service *service); int ServiceStop(Service *service); void ServiceReap(Service *service); +void ReapService(Service *service); + +void NotifyServiceChange(const char *serviceName, const char *change); +int IsForbidden(const char *fieldStr); +int SetImportantValue(Service *curServ, const char *attrName, int value, int flag); +int GetServiceCaps(const cJSON *curArrItem, Service *curServ); +int ServiceExec(Service *service); #ifdef __cplusplus #if __cplusplus diff --git a/services/include/init_service_manager.h b/services/init/include/init_service_manager.h old mode 100644 new mode 100755 similarity index 60% rename from services/include/init_service_manager.h rename to services/init/include/init_service_manager.h index 1208307ab9e15ca96aae97fe5b4b998be28f27ea..d4161a9689c426accd29df7f41bdbf4d966e6e5a --- a/services/include/init_service_manager.h +++ b/services/init/include/init_service_manager.h @@ -18,6 +18,7 @@ #include "init_service.h" #include "cJSON.h" +#include "list.h" #ifdef __cplusplus #if __cplusplus @@ -25,26 +26,37 @@ extern "C" { #endif #endif -#define UID_STR_IN_CFG "uid" -#define GID_STR_IN_CFG "gid" -#define ONCE_STR_IN_CFG "once" -#define IMPORTANT_STR_IN_CFG "importance" -#define BIN_SH_NOT_ALLOWED "/bin/sh" -#define CRITICAL_STR_IN_CFG "critical" -#define DISABLED_STR_IN_CFG "disabled" -#define CONSOLE_STR_IN_CFG "console" +#define UID_STR_IN_CFG "uid" +#define GID_STR_IN_CFG "gid" +#define ONCE_STR_IN_CFG "once" +#define IMPORTANT_STR_IN_CFG "importance" +#define BIN_SH_NOT_ALLOWED "/bin/sh" +#define CRITICAL_STR_IN_CFG "critical" +#define DISABLED_STR_IN_CFG "disabled" +#define CONSOLE_STR_IN_CFG "console" #define MAX_SERVICES_CNT_IN_FILE 100 -void RegisterServices(Service *services, int servicesCnt); +typedef struct { + char *capStr; + int CapNum; +} CapStrCapNum; + +typedef struct { + ListNode services; + int serviceCount; +} ServiceSpace; + +Service *GetServiceByPid(pid_t pid); +Service *GetServiceByName(const char *servName); +cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName); + void StartServiceByName(const char *serviceName, bool checkDynamic); void StopServiceByName(const char *serviceName); -void StopAllServices(void); -void StopAllServicesBeforeReboot(void); -void ReapServiceByPID(int pid); +void StopAllServices(int flags); void ParseAllServices(const cJSON *fileRoot); #ifdef OHOS_SERVICE_DUMP -void DumpAllServices(void); +void DumpAllServices(); #endif #ifdef __cplusplus #if __cplusplus diff --git a/services/include/init_service_socket.h b/services/init/include/init_service_socket.h old mode 100644 new mode 100755 similarity index 66% rename from services/include/init_service_socket.h rename to services/init/include/init_service_socket.h index 6ff5ed5638f0697c198866a62418a82a7ea995d2..6304902aee2e4481910c0d3fc6d771653dcd9e79 --- a/services/include/init_service_socket.h +++ b/services/init/include/init_service_socket.h @@ -16,13 +16,18 @@ #ifndef INIT_SERVICE_SOCKET_ #define INIT_SERVICE_SOCKET_ #include -#include #include +#include #include #include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif -#define MAX_SOCK_NAME_LEN 16 -#define SOCK_OPT_NUMS 6 +#define MAX_SOCK_NAME_LEN 16 +#define SOCK_OPT_NUMS 6 enum SockOptionTab { SERVICE_SOCK_NAME = 0, SERVICE_SOCK_TYPE, @@ -32,18 +37,21 @@ enum SockOptionTab { SERVICE_SOCK_SETOPT }; -struct ServiceSocket; -struct ServiceSocket { - char *name; // service name - int type; // socket type - uid_t uid; // uid - gid_t gid; // gid - bool passcred; // setsocketopt - mode_t perm; // Setting permissions +typedef struct ServiceSocket_ { + struct ServiceSocket_ *next; + int type; // socket type + uid_t uid; // uid + gid_t gid; // gid + bool passcred; // setsocketopt + mode_t perm; // Setting permissions int sockFd; - struct ServiceSocket *next; -}; - -int DoCreateSocket(struct ServiceSocket *sockopt); + char name[0]; // service name +} ServiceSocket; +int DoCreateSocket(ServiceSocket *sockopt); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif #endif diff --git a/services/init/init_capability.c b/services/init/init_capability.c new file mode 100755 index 0000000000000000000000000000000000000000..50ef2ea421bbcdd21537a5da9102738bea2baa34 --- /dev/null +++ b/services/init/init_capability.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2020 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 +#include +#include +#include +#include +#if defined OHOS_LITE && !defined __LINUX__ +#include +#else +#include +#endif +#include +#include + +#include "init_log.h" +#include "init_service.h" +#include "init_service_manager.h" + +#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100 + +static const CapStrCapNum g_capStrCapNum[] = { + { "CHOWN", CAP_CHOWN }, + { "DAC_OVERRIDE", CAP_DAC_OVERRIDE }, + { "DAC_READ_SEARCH", CAP_DAC_READ_SEARCH }, + { "FOWNER", CAP_FOWNER }, + { "FSETID", CAP_FSETID }, + { "KILL", CAP_KILL }, + { "SETGID", CAP_SETGID }, + { "SETUID", CAP_SETUID }, + { "SETPCAP", CAP_SETPCAP }, + { "LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE }, + { "NET_BIND_SERVICE", CAP_NET_BIND_SERVICE }, + { "NET_BROADCAST", CAP_NET_BROADCAST }, + { "NET_ADMIN", CAP_NET_ADMIN }, + { "NET_RAW", CAP_NET_RAW }, + { "IPC_LOCK", CAP_IPC_LOCK }, + { "IPC_OWNER", CAP_IPC_OWNER }, + { "SYS_MODULE", CAP_SYS_MODULE }, + { "SYS_RAWIO", CAP_SYS_RAWIO }, + { "SYS_CHROOT", CAP_SYS_CHROOT }, + { "SYS_PTRACE", CAP_SYS_PTRACE }, + { "SYS_PACCT", CAP_SYS_PACCT }, + { "SYS_ADMIN", CAP_SYS_ADMIN }, + { "SYS_BOOT", CAP_SYS_BOOT }, + { "SYS_NICE", CAP_SYS_NICE }, + { "SYS_RESOURCE", CAP_SYS_RESOURCE }, + { "SYS_TIME", CAP_SYS_TIME }, + { "SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG }, + { "MKNOD", CAP_MKNOD }, + { "LEASE", CAP_LEASE }, + { "AUDIT_WRITE", CAP_AUDIT_WRITE }, + { "AUDIT_CONTROL", CAP_AUDIT_CONTROL }, + { "SETFCAP", CAP_SETFCAP }, + { "MAC_OVERRIDE", CAP_MAC_OVERRIDE }, + { "MAC_ADMIN", CAP_MAC_ADMIN }, + { "SYSLOG", CAP_SYSLOG }, + { "WAKE_ALARM", CAP_WAKE_ALARM }, + { "BLOCK_SUSPEND", CAP_BLOCK_SUSPEND }, + { "AUDIT_READ", CAP_AUDIT_READ }, +}; + +static int GetCapByString(const char *capStr) +{ + int mapSize = (int)(sizeof(g_capStrCapNum) / sizeof(g_capStrCapNum[0])); + for (int j = 0; j < mapSize; j++) { + if (strcmp(capStr, g_capStrCapNum[j].capStr) == 0) { + return g_capStrCapNum[j].CapNum; + } + } + return -1; +} + +int GetServiceCaps(const cJSON *curArrItem, Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null ptr."); + INIT_ERROR_CHECK(curArrItem != NULL, return SERVICE_FAILURE, "json is null ptr."); + service->servPerm.capsCnt = 0; + service->servPerm.caps = NULL; + int capsCnt = 0; + cJSON *filedJ = GetArrayItem(curArrItem, &capsCnt, "caps"); + if (filedJ == NULL) { + return SERVICE_SUCCESS; + } + if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) { + INIT_LOGE("service=%s, too many caps[cnt %d] for one service", service->name, capsCnt); + return SERVICE_FAILURE; + } + service->servPerm.caps = (unsigned int *)malloc(sizeof(unsigned int) * capsCnt); + if (service->servPerm.caps == NULL) { + INIT_LOGE("Failed to malloc for service %s", service->name); + return SERVICE_FAILURE; + } + service->servPerm.capsCnt = capsCnt; + int caps = -1; + for (int i = 0; i < capsCnt; ++i) { // number form + cJSON *capJson = cJSON_GetArrayItem(filedJ, i); + if (cJSON_IsNumber(capJson)) { // for number + caps = cJSON_GetNumberValue(capJson); + } else if (cJSON_IsString(capJson)) { + char *capStr = cJSON_GetStringValue(capJson); + if (capStr == NULL || strlen(capStr) <= 0) { // check all errors + INIT_LOGE("service=%s, parse item[%d] as string, error.", service->name, i); + break; + } + caps = GetCapByString(capStr); + } + if (caps < 0) { + return SERVICE_FAILURE; + } + if ((caps > CAP_LAST_CAP && caps != FULL_CAP)) { + INIT_LOGE("service=%s, caps = %d, error.", service->name, caps); + return SERVICE_FAILURE; + } + service->servPerm.caps[i] = (unsigned int)caps; + } + return 0; +} diff --git a/services/init/init_cmds.c b/services/init/init_cmds.c new file mode 100755 index 0000000000000000000000000000000000000000..17fbc25f2db56a1f56d35965c5c193c73f351f22 --- /dev/null +++ b/services/init/init_cmds.c @@ -0,0 +1,758 @@ +/* + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "init_cmds.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "init_jobs.h" +#include "init_log.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "securec.h" + +static char *AddOneArg(const char *param, size_t paramLen) +{ + size_t allocSize = paramLen + PARAM_VALUE_LEN_MAX + 1; + char *arg = calloc(sizeof(char), allocSize); + INIT_CHECK(arg != NULL, return NULL); + int ret = GetParamValue(param, paramLen, arg, allocSize); + INIT_ERROR_CHECK(ret == 0, free(arg); + return NULL, "Failed to get value for %s", param); + return arg; +} + +const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount) +{ + INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL); + if (argsCount > SPACES_CNT_IN_CMD_MAX) { + INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); + argsCount = SPACES_CNT_IN_CMD_MAX; + } + struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs) + sizeof(char *) * (argsCount + 1)); + INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to malloc memory for arg"); + ctx->argc = 0; + char *p = (char *)cmdContent; + char *end = (char *)cmdContent + strlen(cmdContent); + char *token = NULL; + do { + // Skip lead whitespaces + while (isspace(*p)) { + p++; + } + token = strstr(p, delim); + if (token == NULL) { + ctx->argv[ctx->argc] = AddOneArg(p, end - p); + INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx); + return NULL); + } else { + ctx->argv[ctx->argc] = AddOneArg(p, token - p); + INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx); + return NULL); + } + ctx->argc++; + ctx->argv[ctx->argc] = NULL; + if (ctx->argc == argsCount) { + break; + } + p = token; + } while (token != NULL); + return ctx; +} + +void FreeCmdArg(struct CmdArgs *cmd) +{ + INIT_CHECK_ONLY_RETURN(cmd != NULL); + for (int i = 0; i < cmd->argc; ++i) { + if (cmd->argv[i] != NULL) { + free(cmd->argv[i]); + } + } + free(cmd); + return; +} + +static void ExecCmd(const struct CmdTable *cmd, const char *cmdContent) +{ + if (cmd == NULL) { + INIT_LOGE("Invalid cmd for %s", cmdContent); + return; + } + + const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", cmd->maxArg); + if (ctx == NULL) { + INIT_LOGE("Invalid arguments %s %s", cmd->name, cmdContent); + } else if ((ctx->argc <= cmd->maxArg) && (ctx->argc >= cmd->minArg)) { + cmd->DoFuncion(ctx, cmdContent); + } else { + INIT_LOGE("Invalid arguments %s %s argc: %d %d", cmd->name, cmdContent, ctx->argc, cmd->maxArg); + } + FreeCmdArg((struct CmdArgs *)ctx); +} + +static void SetProcName(const struct CmdArgs *ctx, const char *procFile) +{ + int fd = open(procFile, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); + INIT_ERROR_CHECK(fd >= 0, return, "Failed to set %s errno: %d", procFile, errno); + + size_t size = strlen(ctx->argv[0]); + ssize_t n = write(fd, ctx->argv[0], size); + INIT_ERROR_CHECK(n == (ssize_t)size, close(fd); + return, "Failed to write domainname errno: %d", errno); + close(fd); +} + +static void DoSetDomainname(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + SetProcName(ctx, "/proc/sys/kernel/domainname"); +} + +static void DoSetHostname(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + SetProcName(ctx, "/proc/sys/kernel/hostname"); +} + +static void DoSleep(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + errno = 0; + unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); + if (errno != 0) { + INIT_LOGE("cannot covert sleep time in command \" sleep \""); + return; + } + + // Limit sleep time in 5 seconds + const unsigned long sleepTimeLimit = 5; + if (sleepTime > sleepTimeLimit) { + sleepTime = sleepTimeLimit; + } + INIT_LOGI("Sleeping %d second(s)", sleepTime); + sleep((unsigned int)sleepTime); +} + +static void DoStart(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + INIT_LOGD("DoStart %s", cmdContent); + StartServiceByName(cmdContent, true); +} + +static void DoStop(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + INIT_LOGD("DoStop %s", cmdContent); + StopServiceByName(cmdContent); + return; +} + +static void DoReset(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + INIT_LOGD("DoReset %s", cmdContent); + DoStop(ctx, cmdContent); + DoStart(ctx, cmdContent); +} + +static void DoCopy(const struct CmdArgs *ctx, const char *cmdContent) +{ + int srcFd = -1; + int dstFd = -1; + char buf[MAX_COPY_BUF_SIZE] = { 0 }; + char *realPath1 = NULL; + char *realPath2 = NULL; + if (ctx == NULL || ctx->argc != DEFAULT_COPY_ARGS_CNT || ctx->argv[0] == NULL || ctx->argv[1] == NULL) { + INIT_LOGE("DoCopy invalid arguments :%s", cmdContent); + return; + } + do { + realPath1 = realpath(ctx->argv[0], NULL); + realPath2 = realpath(ctx->argv[1], NULL); + if (realPath2 == NULL || realPath1 == NULL) { + INIT_LOGE("Failed to get real path %s", ctx->argv[1]); + break; + } + srcFd = open(realPath1, O_RDONLY); + if (srcFd < 0) { + INIT_LOGE("Failed to open source path %s %d", ctx->argv[0], errno); + break; + } + struct stat fileStat = { 0 }; + if (stat(ctx->argv[0], &fileStat) != 0) { + INIT_LOGE("Failed to state source path %s %d", ctx->argv[0], errno); + break; + } + mode_t mode = fileStat.st_mode; + + dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode); + if (srcFd < 0) { + INIT_LOGE("Failed to open dest path %s %d", ctx->argv[1], errno); + break; + } + int rdLen = 0; + while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) { + int rtLen = write(dstFd, buf, rdLen); + if (rtLen != rdLen) { + INIT_LOGE("Failed to write to dest path %s %d", ctx->argv[1], errno); + break; + } + } + fsync(dstFd); + } while (0); + INIT_CHECK(srcFd < 0, close(srcFd)); + INIT_CHECK(dstFd < 0, close(dstFd)); + INIT_CHECK(realPath1 == NULL, free(realPath1)); + INIT_CHECK(realPath2 == NULL, free(realPath2)); +} + +static void DoChown(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: chown owner group /xxx/xxx/xxx + uid_t owner = DecodeUid(ctx->argv[0]); + INIT_ERROR_CHECK(owner != (uid_t)-1, return, "DoChown invalid uid :%s.", ctx->argv[0]); + + gid_t group = DecodeUid(ctx->argv[1]); + INIT_ERROR_CHECK(group != (gid_t)-1, return, "DoChown invalid gid :%s.", ctx->argv[1]); + + const int pathPos = 2; + if (chown(ctx->argv[pathPos], owner, group) != 0) { + INIT_LOGE("DoChown, failed for %s, err %d.", cmdContent, errno); + } + return; +} + +static void DoMkDir(const struct CmdArgs *ctx, const char *cmdContent) +{ + // mkdir support format: + // 1.mkdir path + // 2.mkdir path mode + // 3.mkdir path mode owner group + UNUSED(cmdContent); + const int ownerPos = 2; + const int groupPos = 3; + if (ctx->argc != 1 && ctx->argc != (groupPos + 1) && ctx->argc != ownerPos) { + INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent); + return; + } + + mode_t mode = DEFAULT_DIR_MODE; + if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) { + INIT_LOGE("DoMkDir, failed for %s, err %d.", cmdContent, errno); + return; + } + + if (ctx->argc <= 1) { + return; + } + + mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE); + if (chmod(ctx->argv[0], mode) != 0) { + INIT_LOGE("DoMkDir failed for %s, err %d.", cmdContent, errno); + } + if (ctx->argc == ownerPos) { + return; + } + uid_t owner = DecodeUid(ctx->argv[ownerPos]); + INIT_ERROR_CHECK(owner != (uid_t)-1, return, "DoMkDir invalid uid :%s.", ctx->argv[ownerPos]); + gid_t group = DecodeUid(ctx->argv[groupPos]); + INIT_ERROR_CHECK(group != (gid_t)-1, return, "DoMkDir invalid gid :%s.", ctx->argv[groupPos]); + if (chown(ctx->argv[0], owner, group) != 0) { + INIT_LOGE("DoMkDir, chown failed for %s, err %d.", cmdContent, errno); + } + return; +} + +static void DoChmod(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: chmod xxxx /xxx/xxx/xxx + mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE); + if (mode == 0) { + INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno); + return; + } + + if (chmod(ctx->argv[1], mode) != 0) { + INIT_LOGE("Failed to change file \" %s \" mode to %04o, err = %d", ctx->argv[0], mode, errno); + } +} + +static char *CopySubStr(const char *srcStr, size_t startPos, size_t endPos) +{ + if (endPos <= startPos) { + INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr); + return NULL; + } + + size_t mallocLen = endPos - startPos + 1; + char *retStr = (char *)malloc(mallocLen); + if (retStr == NULL) { + INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr); + return NULL; + } + + const char *copyStart = srcStr + startPos; + if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) { + INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr); + free(retStr); + return NULL; + } + retStr[mallocLen - 1] = '\0'; + + // for example, source may be none + if (strncmp(retStr, "none", strlen("none")) == 0) { + retStr[0] = '\0'; + } + return retStr; +} + +static int GetMountFlag(unsigned long *mountflags, const char *targetStr, const char *source) +{ + if (targetStr == NULL) { + return 0; + } + + if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) { + (*mountflags) |= MS_NODEV; + } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) { + (*mountflags) |= MS_NOEXEC; + } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) { + (*mountflags) |= MS_NOSUID; + } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) { + (*mountflags) |= MS_RDONLY; + } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) { + (*mountflags) |= MS_NOATIME; + } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) { + WaitForFile(source, WAIT_MAX_COUNT); + } else { + return 0; + } + return 1; +} + +static int CountSpaces(const char *cmdContent, size_t *spaceCnt, size_t *spacePosArr, size_t spacePosArrLen) +{ + *spaceCnt = 0; + size_t strLen = strlen(cmdContent); + for (size_t i = 0; i < strLen; ++i) { + if (cmdContent[i] == ' ') { + ++(*spaceCnt); + if ((*spaceCnt) > spacePosArrLen) { + INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent); + return 0; + } + spacePosArr[(*spaceCnt) - 1] = i; + } + } + + if ((*spaceCnt) < SPACES_CNT_IN_CMD_MIN || // spaces count should not less than 2(at least 3 items) + spacePosArr[0] == 0 || // should not start with space + spacePosArr[(*spaceCnt) - 1] == strLen - 1) { // should not end with space + INIT_LOGE("DoMount, bad format for %s.", cmdContent); + return 0; + } + + // spaces should not be adjacent + for (size_t i = 1; i < (*spaceCnt); ++i) { + if (spacePosArr[i] == spacePosArr[i - 1] + 1) { + INIT_LOGE("DoMount, bad format for %s.", cmdContent); + return 0; + } + } + return 1; +} + +static void DoMount(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + size_t spaceCnt = 0; + size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = { 0 }; + if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) { + return; + } + + // format: fileSystemType source target mountFlag1 mountFlag2... data + unsigned long mountflags = 0; + size_t strLen = strlen(cmdContent); + size_t indexOffset = 0; + char *fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]); + if (fileSysType == NULL) { + return; + } + + char *source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]); + INIT_ERROR_CHECK(source != NULL, free(fileSysType); + return, "Failed to get source %s", cmdContent); + ++indexOffset; + + // maybe only has "filesystype source target", 2 spaces + size_t targetEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; + char *target = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, targetEndPos); + INIT_ERROR_CHECK(target != NULL, free(fileSysType); + free(source); + return, "Failed to get target %s", cmdContent); + ++indexOffset; + + // get mountflags, if fail, the rest part of string will be data + while (indexOffset < spaceCnt) { + size_t tmpStrEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; + char *tmpStr = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, tmpStrEndPos); + int ret = GetMountFlag(&mountflags, tmpStr, source); + free(tmpStr); + tmpStr = NULL; + + // get flag failed, the rest part of string will be data + if (ret == 0) { + break; + } + ++indexOffset; + } + + int mountRet; + if (indexOffset >= spaceCnt) { // no data + mountRet = mount(source, target, fileSysType, mountflags, NULL); + } else { + const char *dataStr = cmdContent + spacePosArr[indexOffset] + 1; + mountRet = mount(source, target, fileSysType, mountflags, dataStr); + } + + if (mountRet != 0) { + INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno); + } + + free(fileSysType); + free(source); + free(target); +} + +static bool CheckValidCfg(const char *path) +{ + static const char *g_supportCfg[] = { + "/etc/patch.cfg", + "/patch/fstab.cfg", + }; + INIT_ERROR_CHECK(path != NULL, return false, "Invalid path for cfg"); + struct stat fileStat = { 0 }; + if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) { + return false; + } + size_t cfgCnt = ARRAY_LENGTH(g_supportCfg); + for (size_t i = 0; i < cfgCnt; ++i) { + if (strcmp(path, g_supportCfg[i]) == 0) { + return true; + } + } + return false; +} + +static void DoLoadCfg(const struct CmdArgs *ctx, const char *path) +{ + UNUSED(ctx); + char buf[LOADCFG_BUF_SIZE] = { 0 }; + size_t maxLoop = 0; + int len; + if (!CheckValidCfg(path)) { + INIT_LOGE("CheckCfg file %s Failed", path); + return; + } + char *realPath = realpath(path, NULL); + INIT_ERROR_CHECK(realPath != NULL, return, "Failed to get realpath %s", path); + FILE *fp = fopen(realPath, "r"); + if (fp == NULL) { + INIT_LOGE("open cfg error = %d", errno); + free(realPath); + return; + } + + while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) { + maxLoop++; + len = strlen(buf); + if (len < 1) { + continue; + } + if (buf[len - 1] == '\n') { + buf[len - 1] = '\0'; // we replace '\n' with '\0' + } + const struct CmdTable *cmd = GetCmdByName(buf); + if (cmd == NULL) { + INIT_LOGE("Cannot support command: %s", buf); + continue; + } + ExecCmd(cmd, &buf[strlen(cmd->name) + 1]); + } + free(realPath); + (void)fclose(fp); +} + +static void DoWrite(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: write path content + char *realPath = realpath(ctx->argv[0], NULL); + if (realPath == NULL) { + return; + } + int fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); + if (fd >= 0) { + size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1])); + if (ret < 0) { + INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno); + } + } + free(realPath); + realPath = NULL; + close(fd); +} + +static void DoRmdir(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: rmdir path + int ret = rmdir(ctx->argv[0]); + if (ret == -1) { + INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno); + } + return; +} + +static void DoRebootCmd(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + ExecReboot(cmdContent); + return; +} + +static void DoSetrlimit(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + static const char *resource[] = { + "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS", + "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING", + "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS" + }; + // format: setrlimit resource curValue maxValue + const int rlimMaxPos = 2; + struct rlimit limit; + limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]); + limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]); + int rcs = -1; + for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) { + if (strcmp(ctx->argv[0], resource[i]) == 0) { + rcs = (int)i; + } + } + if (rcs == -1) { + INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]); + return; + } + int ret = setrlimit(rcs, &limit); + if (ret) { + INIT_LOGE("DoSetrlimit failed : %d", errno); + } +} + +static void DoRm(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: rm /xxx/xxx/xxx + int ret = unlink(ctx->argv[0]); + if (ret == -1) { + INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno); + } +} + +static void DoExport(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: export xxx /xxx/xxx/xxx + int ret = setenv(ctx->argv[0], ctx->argv[1], 1); + if (ret != 0) { + INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno); + } +} + +static const struct CmdTable CMD_TABLE[] = { + { "start ", 0, 1, DoStart }, + { "mkdir ", 1, 4, DoMkDir }, + { "chmod ", 2, 2, DoChmod }, + { "chown ", 3, 3, DoChown }, + { "mount ", 1, 10, DoMount }, + { "export ", 2, 2, DoExport }, + { "loadcfg ", 1, 1, DoLoadCfg }, + { "rm ", 1, 1, DoRm }, + { "rmdir ", 1, 1, DoRmdir }, + { "write ", 2, 2, DoWrite }, + { "stop ", 1, 1, DoStop }, + { "reset ", 1, 1, DoReset }, + { "copy ", 2, 2, DoCopy }, + { "reboot ", 1, 1, DoRebootCmd }, + { "setrlimit ", 3, 3, DoSetrlimit }, + { "sleep ", 1, 1, DoSleep }, + { "hostname ", 1, 1, DoSetHostname }, + { "domainname ", 1, 1, DoSetDomainname } +}; + +static const struct CmdTable *GetCommCmdTable(int *number) +{ + *number = (int)(sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0])); + return CMD_TABLE; +} + +const struct CmdTable *GetCmdByName(const char *name) +{ + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + for (int i = 0; i < cmdCnt; ++i) { + if (strncmp(name, commCmds[i].name, strlen(commCmds[i].name)) == 0) { + return &commCmds[i]; + } + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + for (int i = 0; i < number; ++i) { + if (strncmp(name, cmds[i].name, strlen(cmds[i].name)) == 0) { + return &cmds[i]; + } + } + return NULL; +} + +const char *GetMatchCmd(const char *cmdStr, int *index) +{ + if (cmdStr == NULL || index == NULL) { + return NULL; + } + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + for (int i = 0; i < cmdCnt; ++i) { + if (strncmp(cmdStr, commCmds[i].name, strlen(commCmds[i].name)) == 0) { + *index = i; + return commCmds[i].name; + } + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + for (int i = 0; i < number; ++i) { + if (strncmp(cmdStr, cmds[i].name, strlen(cmds[i].name)) == 0) { + *index = cmdCnt + i; + return cmds[i].name; + } + } + return NULL; +} + +const char *GetCmdKey(int index) +{ + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + if (index < cmdCnt) { + return commCmds[index].name; + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + if (index < number) { + return cmds[index].name; + } + return NULL; +} + +int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines) +{ + INIT_CHECK(root != NULL, return -1); + INIT_CHECK(cmdLines != NULL, return -1); + *cmdLines = NULL; + if (!cJSON_IsArray(root)) { + return -1; + } + int cmdCnt = cJSON_GetArraySize(root); + if (cmdCnt <= 0) { + return -1; + } + *cmdLines = (CmdLines *)malloc(sizeof(CmdLines) + sizeof(CmdLine) * cmdCnt); + if (*cmdLines == NULL) { + return -1; + } + (*cmdLines)->cmdNum = 0; + for (int i = 0; i < cmdCnt; ++i) { + cJSON *line = cJSON_GetArrayItem(root, i); + if (!cJSON_IsString(line)) { + continue; + } + char *tmp = cJSON_GetStringValue(line); + if (tmp == NULL) { + continue; + } + int index = 0; + const char *cmd = GetMatchCmd(tmp, &index); + if (cmd == NULL) { + INIT_LOGE("Cannot support command: %s", tmp); + continue; + } + int ret = strcpy_s((*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdContent, MAX_CMD_CONTENT_LEN, tmp + strlen(cmd)); + if (ret != EOK) { + INIT_LOGE("Invalid cmd arg: %s", tmp); + continue; + } + (*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdIndex = index; + (*cmdLines)->cmdNum++; + } + return 0; +} + +void DoCmdByName(const char *name, const char *cmdContent) +{ + if (name == NULL || cmdContent == NULL) { + return; + } + const struct CmdTable *cmd = GetCmdByName(name); + ExecCmd(cmd, cmdContent); +} + +void DoCmdByIndex(int index, const char *cmdContent) +{ + if (cmdContent == NULL) { + return; + } + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + if (index < cmdCnt) { + ExecCmd(&commCmds[index], cmdContent); + return; + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + if (index < (cmdCnt + number)) { + ExecCmd(&cmds[index - cmdCnt], cmdContent); + return; + } +} \ No newline at end of file diff --git a/services/src/init_import.c b/services/init/init_config.c old mode 100644 new mode 100755 similarity index 40% rename from services/src/init_import.c rename to services/init/init_config.c index 319c26516bd57d0303a9c853b7d93b151c22918b..d64c5f8de50445cec518780a33a51eda7da353be --- a/services/src/init_import.c +++ b/services/init/init_config.c @@ -1,84 +1,90 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "init_import.h" -#include -#include -#include "cJSON.h" -#include "init_cmds.h" -#include "init_log.h" -#include "init_read_cfg.h" -#include "securec.h" - -#ifndef OHOS_LITE -static int ExtractCfgFile(char **cfgFile, const char *content) -{ - if ((!cfgFile) || (!content)) { - return -1; - } - size_t cfgFileLen = strlen(content) + MAX_PARAM_VALUE_LEN + 1; - if (cfgFileLen <= 0) { - return -1; - } - if ((*cfgFile = malloc(cfgFileLen)) == NULL) { - INIT_LOGW("Failed to allocate memory to import cfg file. err = %d", errno); - return -1; - } - return GetParamValue(content, *cfgFile, cfgFileLen); -} -#endif - -void ParseAllImports(const cJSON *root) -{ - cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import"); - char *cfgFile = NULL; - if (!cJSON_IsArray(importAttr)) { - return; - } - int importAttrSize = cJSON_GetArraySize(importAttr); - - for (int i = 0; i < importAttrSize; i++) { - cJSON *importItem = cJSON_GetArrayItem(importAttr, i); - if (!cJSON_IsString(importItem)) { - INIT_LOGE("Invalid type of import item. should be string"); - return; - } - char *importContent = cJSON_GetStringValue(importItem); - if (importContent == NULL) { - INIT_LOGE("cannot get import config file"); - return; - } -// Only OHOS L2 support parameter. -#ifndef OHOS_LITE - if (ExtractCfgFile(&cfgFile, importContent) < 0) { - INIT_LOGW("Failed to import from %s", importContent); - if (cfgFile != NULL) { - free(cfgFile); - cfgFile = NULL; - } - continue; - } -#else - cfgFile = importContent; -#endif - INIT_LOGI("Import %s...", cfgFile); - ParseInitCfg(cfgFile); - // Do not forget to free memory. - free(cfgFile); - cfgFile = NULL; - } - INIT_LOGD("parse import file done"); - return; -} +/* + * Copyright (c) 2020 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.h" +#include "init_jobs.h" +#include "init_log.h" +#include "init_service_manager.h" +#include "init_utils.h" + +static void ParseAllImports(cJSON *root); + +static void ParseInitCfgContents(const char *cfgName, cJSON *root) +{ + INIT_ERROR_CHECK(root != NULL, return, "Root is null"); + INIT_LOGI("Parse init cfg %s ", cfgName); + + ParseAllServices(root); + // parse jobs + ParseAllJobs(root); + // parse imports + ParseAllImports(root); +} + +static int ParseInitCfg(const char *configFile, void *context) +{ + UNUSED(context); + char *fileBuf = ReadFileToBuf(configFile); + INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", configFile); + + cJSON *fileRoot = cJSON_Parse(fileBuf); + INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf); + return -1, "Failed to parse json file %s", configFile); + + ParseInitCfgContents(configFile, fileRoot); + cJSON_Delete(fileRoot); + free(fileBuf); + return 0; +} + +static void ParseAllImports(cJSON *root) +{ + char *tmpParamValue = malloc(PARAM_VALUE_LEN_MAX + 1); + INIT_ERROR_CHECK(tmpParamValue != 0, return, "Failed to alloc memory for param"); + + cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import"); + if (!cJSON_IsArray(importAttr)) { + free(tmpParamValue); + return; + } + int importAttrSize = cJSON_GetArraySize(importAttr); + for (int i = 0; i < importAttrSize; i++) { + cJSON *importItem = cJSON_GetArrayItem(importAttr, i); + if (!cJSON_IsString(importItem)) { + INIT_LOGE("Invalid type of import item. should be string"); + break; + } + char *importContent = cJSON_GetStringValue(importItem); + if (importContent == NULL) { + INIT_LOGE("cannot get import config file"); + break; + } + int ret = GetParamValue(importContent, strlen(importContent), tmpParamValue, PARAM_VALUE_LEN_MAX); + if (ret != 0) { + INIT_LOGE("cannot get value for %s", importContent); + continue; + } + INIT_LOGI("Import %s ...", tmpParamValue); + ParseInitCfg(tmpParamValue, NULL); + } + free(tmpParamValue); + return; +} + +void ReadConfig(void) +{ + // parse cfg + ParseInitCfg(INIT_CONFIGURATION_FILE, NULL); + ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL); +} diff --git a/services/src/init_service.c b/services/init/init_service.c old mode 100644 new mode 100755 similarity index 48% rename from services/src/init_service.c rename to services/init/init_service.c index 482d5a82808da9cad3886c16d8c2b89bfedb7faa..ca14f2c547d25919d1e1fb356312c13b3d718e4c --- a/services/src/init_service.c +++ b/services/init/init_service.c @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "init_service.h" #include @@ -24,27 +23,19 @@ #ifdef __MUSL__ #include #endif +#include #include -#ifndef OHOS_LITE -#include -#endif #include #include #include +#include "init.h" #include "init_adapter.h" #include "init_cmds.h" #include "init_log.h" -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "init_perms.h" #include "init_service_socket.h" #include "init_utils.h" #include "securec.h" -#ifndef OHOS_LITE -#include "sys_param.h" -#endif #define CAP_NUM 2 #define WAIT_MAX_COUNT 10 @@ -53,16 +44,14 @@ #define TIOCSCTTY 0x540E #endif // 240 seconds, 4 minutes -static const int CRASH_TIME_LIMIT = 240; +static const int CRASH_TIME_LIMIT = 240; // maximum number of crashes within time CRASH_TIME_LIMIT for one service static const int CRASH_COUNT_LIMIT = 4; // 240 seconds, 4 minutes -static const int CRITICAL_CRASH_TIME_LIMIT = 240; +static const int CRITICAL_CRASH_TIME_LIMIT = 240; // maximum number of crashes within time CRITICAL_CRASH_TIME_LIMIT for one service static const int CRITICAL_CRASH_COUNT_LIMIT = 4; -static const int MAX_PID_STRING_LENGTH = 50; - static int SetAllAmbientCapability(void) { @@ -103,10 +92,10 @@ static int SetPerms(const Service *service) struct __user_cap_data_struct capData[CAP_NUM] = {}; for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { if (service->servPerm.caps[i] == FULL_CAP) { - for (int i = 0; i < CAP_NUM; ++i) { - capData[i].effective = FULL_CAP; - capData[i].permitted = FULL_CAP; - capData[i].inheritable = FULL_CAP; + for (int j = 0; j < CAP_NUM; ++j) { + capData[j].effective = FULL_CAP; + capData[j].permitted = FULL_CAP; + capData[j].inheritable = FULL_CAP; } break; } @@ -133,6 +122,7 @@ static int SetPerms(const Service *service) static void OpenConsole(void) { + const int stdError = 2; setsid(); WaitForFile("/dev/console", WAIT_MAX_COUNT); int fd = open("/dev/console", O_RDWR); @@ -140,7 +130,7 @@ static void OpenConsole(void) ioctl(fd, TIOCSCTTY, 0); dup2(fd, 0); dup2(fd, 1); - dup2(fd, 2); // Redirect fd to 0, 1, 2 + dup2(fd, stdError); // Redirect fd to 0, 1, 2 close(fd); } else { INIT_LOGE("Open /dev/console failed. err = %d", errno); @@ -148,90 +138,99 @@ static void OpenConsole(void) return; } -static void WriteServicePid(Service *service, pid_t pid) +static int WritePid(Service *service) { + const int MAX_PID_STRING_LENGTH = 50; char pidString[MAX_PID_STRING_LENGTH]; - INIT_ERROR_CHECK(snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", pid) >= 0, - _exit(0x7f), "Build pid string failed"); - - for (int i = 0; i < MAX_WRITEPID_FILES; i++) { - if (service->writepidFiles[i] == NULL) { - break; + pid_t childPid = getpid(); + int len = snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", childPid); + if (len <= 0) { + INIT_LOGE("start service writepid sprintf failed."); + return SERVICE_FAILURE; + } + for (int i = 0; i < service->writePidArgs.count; i++) { + if (service->writePidArgs.argv[i] == NULL) { + continue; } - char *realPath = realpath(service->writepidFiles[i], NULL); + char *realPath = realpath(service->writePidArgs.argv[i], NULL); if (realPath == NULL) { continue; } FILE *fd = fopen(realPath, "wb"); + if (fd == NULL) { + INIT_LOGE("start service writepidFiles %s invalid.", service->writePidArgs.argv[i]); + free(realPath); + realPath = NULL; + continue; + } + if ((int)fwrite(pidString, 1, len, fd) != len) { + INIT_LOGE("start service writepid error.file:%s pid:%s", service->writePidArgs.argv[i], pidString); + } free(realPath); realPath = NULL; - INIT_ERROR_CHECK(fd != NULL, continue, "Open file %s failed, err = %d", service->writepidFiles[i], errno); - INIT_CHECK_ONLY_ELOG(fwrite(pidString, 1, strlen(pidString), fd) == strlen(pidString), - "write pid %s to file %s failed, err = %d", pidString, service->writepidFiles[i], errno); - fclose(fd); + (void)fclose(fd); + INIT_LOGD("ServiceStart writepid filename=%s, childPid=%s, ok", service->writePidArgs.argv[i], pidString); } + return SERVICE_SUCCESS; } int ServiceStart(Service *service) { INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr."); - INIT_INFO_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "service : %s had started already.", service->name); + if (service->pid > 0) { + INIT_LOGI("service : %s had started already.", service->name); + return SERVICE_SUCCESS; + } if (service->attribute & SERVICE_ATTR_INVALID) { INIT_LOGE("start service %s invalid.", service->name); return SERVICE_FAILURE; } - INIT_ERROR_CHECK(service->pathArgs != NULL, return SERVICE_FAILURE, "start service pathArgs is NULL."); - struct stat pathStat = {0}; + if (service->pathArgs.count == 0) { + INIT_LOGE("start service pathArgs is NULL."); + return SERVICE_FAILURE; + } + struct stat pathStat = { 0 }; service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP)); - INIT_ERROR_CHECK(stat(service->pathArgs[0], &pathStat) == 0, service->attribute |= SERVICE_ATTR_INVALID; - return SERVICE_FAILURE, "start service %s invalid, please check %s.", service->name, service->pathArgs[0]); - pid_t pid = fork(); + if (stat(service->pathArgs.argv[0], &pathStat) != 0) { + service->attribute |= SERVICE_ATTR_INVALID; + INIT_LOGE("start service %s invalid, please check %s.", service->name, service->pathArgs.argv[0]); + return SERVICE_FAILURE; + } + int ret = 0; + int pid = fork(); if (pid == 0) { - if (service->socketCfg != NULL) { // start socket service - INIT_ERROR_CHECK(DoCreateSocket(service->socketCfg) >= 0, _exit(0x7f), "Create Socket failed. "); + ret = DoCreateSocket(service->socketCfg); + if (ret < 0) { + INIT_LOGE("service %s exit! create socket failed!", service->name); + _exit(PROCESS_EXIT_CODE); } if (service->attribute & SERVICE_ATTR_CONSOLE) { OpenConsole(); } - INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(0x7f), - "service %s exit! set perms failed! err %d.", service->name, errno); - WriteServicePid(service, getpid()); - INIT_LOGI("service->name is %s ", service->name); -#ifndef OHOS_LITE - if (service->importance != 0) { - INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, _exit(0x7f), - "setpriority failed for %s, importance = %d", service->name, service->importance); + // permissions + if (SetPerms(service) != SERVICE_SUCCESS) { + INIT_LOGE("service %s exit! set perms failed! err %d.", service->name, errno); + _exit(PROCESS_EXIT_CODE); } - // L2 Can not be reset env - INIT_CHECK_ONLY_ELOG(execv(service->pathArgs[0], service->pathArgs) == 0, - "service %s execve failed! err %d.", service->name, errno); -#else - char* env[] = {"LD_LIBRARY_PATH=/storage/app/libs", NULL}; - INIT_CHECK_ONLY_ELOG(execve(service->pathArgs[0], service->pathArgs, env) == 0, - "service %s execve failed! err %d.", service->name, errno); -#endif - _exit(0x7f); // 0x7f: user specified + // write pid + if (WritePid(service) != SERVICE_SUCCESS) { + INIT_LOGE("service %s exit! write pid failed!", service->name); + _exit(PROCESS_EXIT_CODE); + } + ServiceExec(service); + _exit(PROCESS_EXIT_CODE); } else if (pid < 0) { INIT_LOGE("start service %s fork failed!", service->name); return SERVICE_FAILURE; } service->pid = pid; -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - INIT_CHECK_ONLY_ELOG(snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", - service->name) >= 0, "snprintf_s paramName error %d ", errno); - SystemWriteParam(paramName, "running"); -#endif + NotifyServiceChange(service->name, "running"); return SERVICE_SUCCESS; } int ServiceStop(Service *service) { - if (service == NULL) { - INIT_LOGE("stop service failed! null ptr."); - return SERVICE_FAILURE; - } - + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "stop service failed! null ptr."); service->attribute &= ~SERVICE_ATTR_NEED_RESTART; service->attribute |= SERVICE_ATTR_NEED_STOP; if (service->pid <= 0) { @@ -242,84 +241,62 @@ int ServiceStop(Service *service) INIT_LOGE("stop service %s pid %d failed! err %d.", service->name, service->pid, errno); return SERVICE_FAILURE; } -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) { - INIT_LOGE("snprintf_s paramName error %d ", errno); - } - SystemWriteParam(paramName, "stopping"); -#endif + NotifyServiceChange(service->name, "stopping"); INIT_LOGI("stop service %s, pid %d.", service->name, service->pid); return SERVICE_SUCCESS; } -// the service need to be restarted, if it crashed more than 4 times in 4 minutes -void CheckCritical(Service *service) +static bool CalculateCrashTime(Service *service, int crashTimeLimit, int crashCountLimit) { - if (service == NULL) { - return; - } - if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical - // crash time and count check - time_t curTime = time(NULL); - if (service->criticalCrashCnt == 0) { - service->firstCriticalCrashTime = curTime; - ++service->criticalCrashCnt; - } else if (difftime(curTime, service->firstCriticalCrashTime) > CRITICAL_CRASH_TIME_LIMIT) { - service->firstCriticalCrashTime = curTime; - service->criticalCrashCnt = 1; - } else { - ++service->criticalCrashCnt; - if (service->criticalCrashCnt > CRITICAL_CRASH_COUNT_LIMIT) { - INIT_LOGE("reap critical service %s, crash too many times! Need reboot!", service->name); - RebootSystem(); - } + INIT_ERROR_CHECK(service != NULL && crashTimeLimit > 0 && crashCountLimit > 0, return 0, + "Service name=%s, input params error.", service->name); + time_t curTime = time(NULL); + if (service->crashCnt == 0) { + service->firstCrashTime = curTime; + ++service->crashCnt; + } else if (difftime(curTime, service->firstCrashTime) > crashTimeLimit) { + service->firstCrashTime = curTime; + service->crashCnt = 1; + } else { + ++service->crashCnt; + if (service->crashCnt > crashCountLimit) { + return false; } } + return true; } static int ExecRestartCmd(const Service *service) { - INIT_LOGI("ExecRestartCmd "); - if ((service == NULL) || (service->onRestart == NULL) || (service->onRestart->cmdLine == NULL)) { - return SERVICE_FAILURE; - } + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr."); + INIT_ERROR_CHECK(service->restartArg != NULL, return SERVICE_FAILURE, "restartArg is null"); - for (int i = 0; i < service->onRestart->cmdNum; i++) { - INIT_LOGI("SetOnRestart cmdLine->name %s cmdLine->cmdContent %s ", service->onRestart->cmdLine[i].name, - service->onRestart->cmdLine[i].cmdContent); - DoCmd(&service->onRestart->cmdLine[i]); + 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); } - free(service->onRestart->cmdLine); - service->onRestart->cmdLine = NULL; - free(service->onRestart); + free(service->restartArg); return SERVICE_SUCCESS; } void ServiceReap(Service *service) { - if (service == NULL) { - INIT_LOGE("reap service failed! null ptr."); - return; - } + INIT_CHECK(service != NULL, return); service->pid = -1; -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) { - INIT_LOGE("snprintf_s paramName error %d ", errno); - } - SystemWriteParam(paramName, "stopped"); -#endif + NotifyServiceChange(service->name, "stopped"); + if (service->attribute & SERVICE_ATTR_INVALID) { - INIT_LOGE("ServiceReap service %s invalid.", service->name); + INIT_LOGE("Reap service %s invalid.", service->name); return; } + // stopped by system-init itself, no need to restart even if it is not one-shot service if (service->attribute & SERVICE_ATTR_NEED_STOP) { service->attribute &= (~SERVICE_ATTR_NEED_STOP); service->crashCnt = 0; return; } + // for one-shot service if (service->attribute & SERVICE_ATTR_ONCE) { // no need to restart @@ -327,30 +304,30 @@ void ServiceReap(Service *service) service->attribute &= (~SERVICE_ATTR_NEED_STOP); return; } + // the service could be restart even if it is one-shot service } - // the service that does not need to be restarted restarts, indicating that it has crashed - if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { - // crash time and count check - time_t curTime = time(NULL); - if (service->crashCnt == 0) { - service->firstCrashTime = curTime; - ++service->crashCnt; - } else if (difftime(curTime, service->firstCrashTime) > CRASH_TIME_LIMIT) { - service->firstCrashTime = curTime; - service->crashCnt = 1; - } else { - ++service->crashCnt; - if (service->crashCnt > CRASH_COUNT_LIMIT) { - INIT_LOGE("reap service %s, crash too many times!", service->name); - return; - } + + if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical + if (CalculateCrashTime(service, CRITICAL_CRASH_TIME_LIMIT, CRITICAL_CRASH_COUNT_LIMIT) == false) { + INIT_LOGE("Critical service \" %s \" crashed %d times, rebooting system", + service->name, CRITICAL_CRASH_COUNT_LIMIT); + ExecReboot("reboot"); } + } else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { + if (CalculateCrashTime(service, CRASH_TIME_LIMIT, CRASH_COUNT_LIMIT) == false) { + INIT_LOGE("Service name=%s, crash %d times, no more start.", service->name, CRASH_COUNT_LIMIT); + return; + } + } + + int ret = ExecRestartCmd(service); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Failed to exec restartArg for %s", service->name); } - CheckCritical(service); - if (service->onRestart != NULL) { - INIT_CHECK_ONLY_ELOG(ExecRestartCmd(service) == SERVICE_SUCCESS, "SetOnRestart fail "); + + ret = ServiceStart(service); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("reap service %s start failed!", service->name); } - INIT_CHECK_ONLY_ELOG(ServiceStart(service) == SERVICE_SUCCESS, "reap service %s start failed!", service->name); service->attribute &= (~SERVICE_ATTR_NEED_RESTART); } - diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c new file mode 100755 index 0000000000000000000000000000000000000000..10689c67307c702507bd3bceb30966d422ee49bb --- /dev/null +++ b/services/init/init_service_manager.c @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2020 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_service_manager.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cJSON.h" +#include "init.h" +#include "init_jobs.h" +#include "init_log.h" +#include "init_service_socket.h" +#include "init_utils.h" +#include "securec.h" + +// All serivce processes that init will fork+exec. +static ServiceSpace g_serviceSpace = { { &g_serviceSpace.services, &g_serviceSpace.services }, 0 }; + +#ifdef OHOS_SERVICE_DUMP +static void DumpServiceArgs(const ServiceArgs *args) +{ + INIT_LOGD("arg count %d", args->count); + for (int j = 0; j < args->count; j++) { + if (args->argv[j] != NULL) { + INIT_LOGD(" %s", args->argv[j]); + } + } +} + +void DumpAllServices() +{ + INIT_LOGD("Ready to dump all services:"); + INIT_LOGD("total service number: %d", g_serviceSpace.serviceCount); + ListNode *node = g_serviceSpace.services.next; + while (node != &g_serviceSpace.services) { + Service *service = ListEntry(node, Service, node); + INIT_LOGD("\tservice name: [%s]", service->name); + INIT_LOGD("\tpath :"); + DumpServiceArgs(&service->pathArgs); + INIT_LOGD("\twritepid :"); + DumpServiceArgs(&service->writePidArgs); + } + INIT_LOGD("Dump all services finished"); +} +#endif + +static void FreeServiceArg(ServiceArgs *arg) +{ + if (arg != NULL) { + return; + } + for (int i = 0; i < arg->count; ++i) { + if (arg->argv[i] != NULL) { + free(arg->argv[i]); + arg->argv[i] = NULL; + } + } + free(arg->argv); + arg->argv = NULL; + arg->count = 0; +} + +static void FreeServiceSocket(ServiceSocket *sockopt) +{ + while (sockopt != NULL) { + ServiceSocket *tmp = sockopt; + sockopt = sockopt->next; + free(tmp); + } + return; +} + +static Service *AddService(void) +{ + Service *service = (Service *)malloc(sizeof(Service)); + INIT_ERROR_CHECK(service != NULL, return, "Failed to malloc for service"); + ret = memset_s(service, sizeof(Service), 0, sizeof(Service)); + if (ret != EOK) { + free(service); + INIT_LOGE("Failed to init for service %s", tmpService.name); + return NULL; + } + ListInit(&service->node); + ListAddTail(&g_serviceSpace.services, &service->node); + g_serviceSpace.serviceCount++; +} + +static void ReleaseService(Service *service) +{ + if (service == NULL) { + return; + } + FreeServiceArg(&service->pathArgs); + FreeServiceArg(&service->writePidArgs); + + if (service->servPerm.caps != NULL) { + free(service->servPerm.caps); + service->servPerm.caps = NULL; + } + service->servPerm.capsCnt = 0; + if (service->servPerm.gIDArray != NULL) { + free(service->servPerm.gIDArray); + service->servPerm.gIDArray = NULL; + } + service->servPerm.gIDCnt = 0; + FreeServiceSocket(service->socketCfg); + + if (!ListEmpty(service->node)) { + ListRemove(&service->node); + g_serviceSpace.serviceCount--; + } + free(service); +} + +static int GetStringItem(const cJSON *json, const char *name, char *buffer, int32_t buffLen) +{ + INIT_ERROR_CHECK(json != NULL, return SERVICE_FAILURE, "Invalid json for %s", name); + char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name)); + INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get string for %s", name); + size_t strLen = strlen(fieldStr); + if ((strLen == 0) || (strLen > (size_t)buffLen)) { + INIT_LOGE("Invalid str filed %s for %s", fieldStr, name); + return SERVICE_FAILURE; + } + return strcpy_s(buffer, buffLen, fieldStr); +} + +cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName) +{ + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName); + if (!cJSON_IsArray(arrItem)) { + return NULL; + } + *arrSize = cJSON_GetArraySize(arrItem); + if (*arrSize <= 0) { + return NULL; + } + return arrItem; +} + +static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args) +{ + INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson"); + cJSON *obj = cJSON_GetObjectItem(argJson, name); + INIT_CHECK(obj != NULL, return SERVICE_FAILURE); + + int ret = cJSON_IsArray(obj); + INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type"); + int count = cJSON_GetArraySize(obj); + INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, "Array size = %d is wrong", count); + + args->argv = (char **)malloc((count + 1) * sizeof(char *)); + INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv"); + for (int i = 0; i < count + 1; ++i) { + args->argv[i] = NULL; + } + args->count = count + 1; + for (int i = 0; i < count; ++i) { + char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i)); + INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i); + INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam); + args->argv[i] = strdup(curParam); + INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to dupstring %s", curParam); + } + return SERVICE_SUCCESS; +} + +static int GetUid(cJSON *json, uid_t *uid) +{ + INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS); + if (cJSON_IsString(json)) { + char *str = cJSON_GetStringValue(json); + INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str"); + *uid = DecodeUid(str); + } else if (cJSON_IsNumber(json)) { + *uid = (uid_t)cJSON_GetNumberValue(json); + } + if (*uid == (uid_t)(-1)) { + return SERVICE_FAILURE; + } + return SERVICE_SUCCESS; +} + +static int GetServiceGids(const cJSON *curArrItem, Service *curServ) +{ + gid_t gid; + int gidCount = 0; + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG); + if (!cJSON_IsArray(arrItem)) { + gidCount = 1; + } else { + gidCount = cJSON_GetArraySize(arrItem); + } + if ((gidCount == 0) || (gidCount > NGROUPS_MAX + 1)) { + INIT_LOGE("Invalid gid count %d", gidCount); + return SERVICE_FAILURE; + } + + curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gidCount); + INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc"); + curServ->servPerm.gIDCnt = gidCount; + + if (!cJSON_IsArray(arrItem)) { + int ret = GetUid(arrItem, &gid); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to uid"); + curServ->servPerm.gIDArray[0] = gid; + return SERVICE_SUCCESS; + } + + for (int i = 0; i < gidCount; ++i) { + cJSON *item = cJSON_GetArrayItem(arrItem, i); + int ret = GetUid(item, &gid); + if (ret != 0) { + curServ->servPerm.gIDArray[i] = 0; + continue; + } + curServ->servPerm.gIDArray[i] = gid; + } + return SERVICE_SUCCESS; +} + +static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag, + int (*ProcessAttr)(Service *curServ, const char *attrName, int value, int flag)) +{ + cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName); + if (filedJ == NULL) { + return SERVICE_SUCCESS; + } + if (!cJSON_IsNumber(filedJ)) { + INIT_LOGE("%s is null or is not a number, service name is %s", attrName, curServ->name); + return SERVICE_FAILURE; + } + + int value = (int)cJSON_GetNumberValue(filedJ); + if (ProcessAttr == NULL) { + curServ->attribute &= ~flag; + if (value == 1) { + curServ->attribute |= flag; + } + return 0; + } + return ProcessAttr(curServ, attrName, value, flag); +} + +static int AddServiceSocket(cJSON *json, Service *service) +{ + char *opt[SOCK_OPT_NUMS] = { + NULL, + }; + if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) { + return SERVICE_FAILURE; + } + char *sockStr = cJSON_GetStringValue(json); + int num = SplitString(sockStr, opt, SOCK_OPT_NUMS); + if (num != SOCK_OPT_NUMS) { + return SERVICE_FAILURE; + } + if (opt[SERVICE_SOCK_NAME] == NULL || opt[SERVICE_SOCK_TYPE] == NULL || opt[SERVICE_SOCK_PERM] == NULL || + opt[SERVICE_SOCK_UID] == NULL || opt[SERVICE_SOCK_GID] == NULL || opt[SERVICE_SOCK_SETOPT] == NULL) { + INIT_LOGE("Invalid socket opt"); + return SERVICE_FAILURE; + } + + ServiceSocket *sockopt = (ServiceSocket *)malloc(sizeof(ServiceSocket) + strlen(opt[SERVICE_SOCK_NAME]) + 1); + INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for socket %s", opt[SERVICE_SOCK_NAME]); + + int ret = strcpy_s(sockopt->name, strlen(opt[SERVICE_SOCK_NAME]) + 1, opt[SERVICE_SOCK_NAME]); + INIT_INFO_CHECK(ret == 0, free(sockopt); + return SERVICE_FAILURE, "Failed to copy socket name %s", opt[SERVICE_SOCK_NAME]); + + sockopt->type = SOCK_SEQPACKET; + if (strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0) { + sockopt->type = SOCK_STREAM; + } else if (strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0) { + sockopt->type = SOCK_DGRAM; + } + sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE); + sockopt->uid = DecodeUid(opt[SERVICE_SOCK_UID]); + sockopt->gid = DecodeUid(opt[SERVICE_SOCK_GID]); + if (sockopt->uid == (uid_t)-1 || sockopt->gid == (uid_t)-1) { + free(sockopt); + INIT_LOGE("Invalid uid %d or gid %d", sockopt->uid, sockopt->gid); + return SERVICE_FAILURE; + } + sockopt->passcred = + strncmp(opt[SERVICE_SOCK_SETOPT], "passcred", strlen(opt[SERVICE_SOCK_SETOPT])) == 0 ? true : false; + sockopt->next = NULL; + if (service->socketCfg == NULL) { + service->socketCfg = sockopt; + } else { + sockopt->next = service->socketCfg->next; + service->socketCfg->next = sockopt; + } + return SERVICE_SUCCESS; +} + +static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ) +{ + int sockCnt = 0; + cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket"); + INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE); + int ret = 0; + curServ->socketCfg = NULL; + for (int i = 0; i < sockCnt; ++i) { + cJSON *sockJ = cJSON_GetArrayItem(filedJ, i); + ret = AddServiceSocket(sockJ, curServ); + if (ret != 0) { + break; + } + } + return ret; +} + +static bool IsServiceInMainStrap(Service *curServ) +{ + char *mainServiceList[] = { + "appspawn", "udevd", "samgr", "multimodalinput", "weston", "installs", + "hiview", "hilogd", "hdf_devmgr", "distributedsche", "softbus_server", "foundation" + }; + unsigned int length = ARRAY_LENGTH(mainServiceList); + for (unsigned int i = 0; i < length; ++i) { + if (strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) == 0) { + INIT_LOGI("%s must be main service", curServ->name); + return true; + } + } + return false; +} + +static int GetDynamicService(const cJSON *curArrItem, Service *curServ) +{ + cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic"); + if (item == NULL) { + return SERVICE_SUCCESS; + } + + INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE, + "Service : %s dynamic value only support bool.", curServ->name); + bool isDynamic = (bool)cJSON_GetNumberValue(item); + if (!isDynamic) { + INIT_LOGI("Service : %s dynamic value is false, it will be started with init.", curServ->name); + return SERVICE_SUCCESS; + } + + if (IsServiceInMainStrap(curServ)) { + return SERVICE_SUCCESS; + } + INIT_LOGI("%s is dynamic service", curServ->name); + curServ->attribute |= SERVICE_ATTR_DYNAMIC; + curServ->attribute |= SERVICE_ATTR_ONCE; + return SERVICE_SUCCESS; +} + +static int CheckServiceKeyName(const cJSON *curService) +{ + char *cfgServiceKeyList[] = { + "name", "path", "uid", "gid", "once", "importance", "caps", "disabled", + "writepid", "critical", "socket", "console", "dynamic" + }; + if (curService == NULL) { + return SERVICE_FAILURE; + } + cJSON *child = curService->child; + if (child == NULL) { + return SERVICE_FAILURE; + } + while (child != NULL) { + int i = 0; + int keyListSize = ARRAY_LENGTH(cfgServiceKeyList); + for (; i < keyListSize; i++) { + if (strcmp(child->string, cfgServiceKeyList[i]) == 0) { + break; + } + } + if (i < keyListSize) { + child = child->next; + } else { + INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string); + return SERVICE_FAILURE; + } + } + return SERVICE_SUCCESS; +} + +static int ParseOneService(const cJSON *curItem, Service *service) +{ + if (curItem == NULL || service == NULL) { + return SERVICE_FAILURE; + } + int ret = GetStringItem(curItem, "name", service->name, MAX_SERVICE_NAME); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get service name"); + ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name); + if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) { + INIT_LOGE("Service %s is forbidden.", service->name); + return SERVICE_FAILURE; + } + ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name); + ret = GetServiceGids(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name); + + ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name); + + (void)GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs); + ret = GetServiceCaps(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name); + ret = GetDynamicService(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name); + return ret; +} + +void ParseAllServices(const cJSON *fileRoot) +{ + int servArrSize = 0; + cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON); + INIT_INFO_CHECK(serviceArr != NULL, return, "This config does not contain service array."); + + 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); + + Service tmpService = {}; + for (int i = 0; i < servArrSize; ++i) { + cJSON *curItem = cJSON_GetArrayItem(serviceArr, i); + int ret = GetStringItem(curItem, "name", tmpService.name, MAX_SERVICE_NAME); + if (ret != 0) { + INIT_LOGE("Failed to get service name %s", tmpService.name); + continue; + } + if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { // invalid service + INIT_LOGE("Invalid service name %s", tmpService.name); + continue; + } + Service *service = GetServiceByName(tmpService.name); + if (service != NULL) { + INIT_LOGE("Service name %s has been exist", tmpService.name); + continue; + } + service = AddService(); + if (service != NULL) { + INIT_LOGE("Failed to create service name %s", tmpService.name); + continue; + } + + ret = ParseOneService(curItem, service); + if (ret != SERVICE_SUCCESS) { + ReleaseService(service); + continue; + } + ret = ParseServiceSocket(curItem, service); + if (ret != SERVICE_SUCCESS) { + FreeServiceSocket(service->socketCfg); + service->socketCfg = NULL; + } + ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg); + if (ret != SERVICE_SUCCESS) { + service->restartArg = NULL; + } + INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d", + i, service->name, service->servPerm.uID, + service->attribute & SERVICE_ATTR_CRITICAL ? 1 : 0, + service->attribute & SERVICE_ATTR_DISABLED ? 1 : 0); + } +} + +void StartServiceByName(const char *servName, bool checkDynamic) +{ + Service *service = GetServiceByName(servName); + INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName); + + if (checkDynamic && (service->attribute & SERVICE_ATTR_DYNAMIC)) { + INIT_LOGI("%s is dynamic service.", servName); + return; + } + if (ServiceStart(service) != SERVICE_SUCCESS) { + INIT_LOGE("Service %s start failed!", servName); + } + return; +} + +void StopServiceByName(const char *servName) +{ + Service *service = GetServiceByName(servName); + INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName); + + if (ServiceStop(service) != SERVICE_SUCCESS) { + INIT_LOGE("Service %s start failed!", servName); + } + return; +} + +void StopAllServices(int flags) +{ + ListNode *node = g_serviceSpace.services.next; + while (node != &g_serviceSpace.services) { + Service *service = ListEntry(node, Service, node); + service->attribute |= flags; + int ret = ServiceStop(service); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Service %s stop failed!", service->name); + } + node = node->next; + } +} + +Service *GetServiceByPid(pid_t pid) +{ + ListNode *node = g_serviceSpace.services.next; + while (node != &g_serviceSpace.services) { + Service *service = ListEntry(node, Service, node); + if (service->pid == pid) { + return service; + } + node = node->next; + } + return NULL; +} + +Service *GetServiceByName(const char *servName) +{ + ListNode *node = g_serviceSpace.services.next; + while (node != &g_serviceSpace.services) { + Service *service = ListEntry(node, Service, node); + if (strcmp(service->name, servName) == 0) { + return service; + } + node = node->next; + } + return NULL; +} diff --git a/services/src/init_service_socket.c b/services/init/init_service_socket.c old mode 100644 new mode 100755 similarity index 49% rename from services/src/init_service_socket.c rename to services/init/init_service_socket.c index 653f3f8242a240c21caaaaf374b8e078a909cdbd..ca319db30c2844081b56ac2d12fe1435cf8c15dc --- a/services/src/init_service_socket.c +++ b/services/init/init_service_socket.c @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "init_service_socket.h" #include #include @@ -23,19 +22,19 @@ #include #include #include + #include "init_log.h" +#include "init_service.h" #include "securec.h" -#define HOS_SOCKET_DIR "/dev/unix/socket" -#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_" +#define HOS_SOCKET_DIR "/dev/unix/socket" +#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_" #define MAX_SOCKET_ENV_PREFIX_LEN 64 #define MAX_SOCKET_FD_LEN 16 -static int CreateSocket(struct ServiceSocket *sockopt) +static int CreateSocket(ServiceSocket *sockopt) { - if (sockopt == NULL || sockopt->name == NULL) { - return -1; - } + INIT_ERROR_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Invalid socket opt"); if (sockopt->sockFd >= 0) { close(sockopt->sockFd); sockopt->sockFd = -1; @@ -46,61 +45,55 @@ static int CreateSocket(struct ServiceSocket *sockopt) struct sockaddr_un addr; bzero(&addr, sizeof(addr)); addr.sun_family = AF_UNIX; - if (snprintf_s(addr.sun_path, sizeof(addr.sun_path), sizeof(addr.sun_path) - 1, HOS_SOCKET_DIR"/%s", - sockopt->name) < 0) { - return -1; - } - if (access(addr.sun_path, F_OK)) { - INIT_LOGE("%s already exist, remove it", addr.sun_path); - if (unlink(addr.sun_path) != 0) { - INIT_LOGE("ulink fail err %d ", errno); + size_t addrLen = sizeof(addr.sun_path); + int ret = snprintf_s(addr.sun_path, addrLen, addrLen - 1, HOS_SOCKET_DIR "/%s", sockopt->name); + INIT_ERROR_CHECK(ret >= 0, return -1, "Failed to format addr %s", sockopt->name); + + do { + ret = -1; + if (access(addr.sun_path, F_OK)) { + INIT_LOGE("%s already exist, remove it", addr.sun_path); + break; } - } - if (sockopt->passcred) { - int on = 1; - if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { - unlink(addr.sun_path); - close(sockopt->sockFd); - return -1; + if (sockopt->passcred) { + int on = 1; + if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { + break; + } } - } - - if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) { - INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno); - unlink(addr.sun_path); - close(sockopt->sockFd); - return -1; - } - - if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) { - unlink(addr.sun_path); - close(sockopt->sockFd); - INIT_LOGE("lchown fail %d ", errno); - return -1; - } + if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) { + INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno); + break; + } + if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) { + INIT_LOGE("lchown fail %d ", errno); + break; + } + if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) { + INIT_LOGE("fchmodat fail %d ", errno); + break; + } + ret = 0; + } while (0); - if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) { + if (ret != 0) { unlink(addr.sun_path); close(sockopt->sockFd); - INIT_LOGE("fchmodat fail %d ", errno); return -1; } - INIT_LOGI("CreateSocket success "); + INIT_LOGI("CreateSocket %s success", sockopt->name); return sockopt->sockFd; } static int SetSocketEnv(int fd, const char *name) { - if (name == NULL) { + INIT_ERROR_CHECK(name != NULL, return SERVICE_FAILURE, "Invalid name"); + char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = { 0 }; + char val[MAX_SOCKET_FD_LEN] = { 0 }; + if (snprintf_s(pubName, sizeof(pubName), sizeof(pubName) - 1, HOS_SOCKET_ENV_PREFIX "%s", name) < 0) { return -1; } - char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = {0}; - char val[MAX_SOCKET_FD_LEN] = {0}; - if (snprintf_s(pubName, MAX_SOCKET_ENV_PREFIX_LEN, MAX_SOCKET_ENV_PREFIX_LEN - 1, - HOS_SOCKET_ENV_PREFIX"%s", name) < 0) { - return -1; - } - if (snprintf_s(val, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) { + if (snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", fd) < 0) { return -1; } int ret = setenv(pubName, val, 1); @@ -112,20 +105,15 @@ static int SetSocketEnv(int fd, const char *name) return 0; } -int DoCreateSocket(struct ServiceSocket *sockopt) +int DoCreateSocket(ServiceSocket *sockopt) { - if (sockopt == NULL) { - return -1; - } - struct ServiceSocket *tmpSock = sockopt; + INIT_CHECK(sockopt != NULL, return 0); + ServiceSocket *tmpSock = sockopt; while (tmpSock != NULL) { int fd = CreateSocket(tmpSock); if (fd < 0) { return -1; } - if (tmpSock->name == NULL) { - return -1; - } int ret = SetSocketEnv(fd, tmpSock->name); if (ret < 0) { return -1; @@ -134,4 +122,3 @@ int DoCreateSocket(struct ServiceSocket *sockopt) } return 0; } - diff --git a/services/init/lite/init.c b/services/init/lite/init.c new file mode 100755 index 0000000000000000000000000000000000000000..7a328b0ef7b648c0df1f03176972d65baf489cd1 --- /dev/null +++ b/services/init/lite/init.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 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.h" +#include "init_log.h" +#ifndef __LINUX__ +#include "init_stage.h" +#endif +#include "parameter.h" +#include "securec.h" + +static void PrintSysInfo(void) +{ + const char *sysInfo = GetVersionId(); + if (sysInfo != NULL) { + INIT_LOGE("%s", sysInfo); + return; + } +} + +void SystemInit(void) +{ +} + +void SystemPrepare(void) +{ + PrintSysInfo(); + SignalInit(); +} + +void SystemConfig(void) +{ + // read config + ReadConfig(); + + // dump config +#ifdef OHOS_SERVICE_DUMP + DumpAllServices(); +#endif + + // execute init + DoJob("pre-init"); +#ifndef __LINUX__ + TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1); +#endif + + DoJob("init"); +#ifndef __LINUX__ + TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2); +#endif + + DoJob("post-init"); +#ifndef __LINUX__ + TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3); + InitStageFinished(); +#endif + ReleaseAllJobs(); +} + +void SystemRun(void) +{ + while (1) { + // pause only returns when a signal was caught and the signal-catching function returned. + // pause only returns -1, no need to process the return value. + (void)pause(); + } +} \ No newline at end of file diff --git a/services/init/lite/init_cmds.c b/services/init/lite/init_cmds.c new file mode 100755 index 0000000000000000000000000000000000000000..fa21e71a07a72c5d2370cbd442b8d8e3866cac55 --- /dev/null +++ b/services/init/lite/init_cmds.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include "init_cmds.h" +#include "init_log.h" +#include "securec.h" + +int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen) +{ + return (strncpy_s(paramValue, paramLen, symValue, symLen) == EOK) ? 0 : -1; +} + +static void DoExec(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + // format: exec /xxx/xxx/xxx xxx + pid_t pid = fork(); + if (pid < 0) { + INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent); + return; + } + if (pid == 0) { + struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC); + if (subCtx == NULL || subCtx->argv[0] == NULL) { + INIT_LOGE("DoExec: invalid arguments :%s", cmdContent); + _exit(0x7f); + } + int ret = execve(subCtx->argv[0], subCtx->argv, NULL); + if (ret == -1) { + INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno); + } + FreeCmdArg(subCtx); + _exit(0x7f); + } + return; +} + +static const struct CmdTable CMD_TABLE[] = { { "exec ", 1, 10, DoExec } }; + +const struct CmdTable *GetCmdTable(int *number) +{ + *number = (int)(sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0])); + return CMD_TABLE; +} \ No newline at end of file diff --git a/services/src/init_jobs.c b/services/init/lite/init_jobs.c old mode 100644 new mode 100755 similarity index 60% rename from services/src/init_jobs.c rename to services/init/lite/init_jobs.c index 1bac3d7faf19ef421e142defe605368ebd843e3c..43af8d94ddc33d39705110910999d26ec315bd0f --- a/services/src/init_jobs.c +++ b/services/init/lite/init_jobs.c @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "init_jobs.h" #include @@ -25,9 +24,9 @@ #define JOBS_ARR_NAME_IN_JSON "jobs" #define CMDS_ARR_NAME_IN_JSON "cmds" -#define MAX_JOBS_COUNT 100 +#define MAX_JOBS_COUNT 100 -static Job* g_jobs = NULL; +static Job *g_jobs = NULL; static int g_jobCnt = 0; void DumpAllJobs(void) @@ -36,17 +35,17 @@ void DumpAllJobs(void) for (int i = 0; i < g_jobCnt; i++) { INIT_LOGD("\tjob name: %s", g_jobs[i].name); INIT_LOGD("\tlist all commands:"); - for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) { + for (int j = 0; j < g_jobs[i].cmdLines->cmdNum; j++) { INIT_LOGD("\t\tcommand name : %s, command options: %s", - g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent); + GetCmdKey(g_jobs[i].cmdLines->cmds[j].cmdIndex), g_jobs[i].cmdLines->cmds[j].cmdContent); } } INIT_LOGD("To dump all jobs finished"); } -static int GetJobName(const cJSON* jobItem, Job* resJob) +static int GetJobName(const cJSON *jobItem, Job *resJob) { - char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); + char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); if (jobNameStr == NULL) { return 0; } @@ -59,7 +58,7 @@ static int GetJobName(const cJSON* jobItem, Job* resJob) return 1; } -static void ParseJob(const cJSON* jobItem, Job* resJob) +static void ParseJob(const cJSON *jobItem, Job *resJob) { if (!GetJobName(jobItem, resJob)) { INIT_LOGE("get JobName failed"); @@ -67,52 +66,27 @@ static void ParseJob(const cJSON* jobItem, Job* resJob) return; } - cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON); + cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON); if (!cJSON_IsArray(cmdsItem)) { INIT_LOGE("job %s is not an arrary", resJob->name); return; } - - int cmdLinesCnt = cJSON_GetArraySize(cmdsItem); - if (cmdLinesCnt <= 0) { // empty job, no cmd - INIT_LOGE("empty job \"%s\"", resJob->name); - return; - } - - INIT_LOGD("job = %s, cmdLineCnt = %d", resJob->name, cmdLinesCnt); - if (cmdLinesCnt > MAX_CMD_CNT_IN_ONE_JOB) { - INIT_LOGE("ParseAllJobs, too many cmds[cnt %d] in one job, it should not exceed %d.", - cmdLinesCnt, MAX_CMD_CNT_IN_ONE_JOB); - return; - } - - resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine)); - if (resJob->cmdLines == NULL) { - INIT_LOGE("allocate memory for command line failed"); + int ret = GetCmdLinesFromJson(cmdsItem, &resJob->cmdLines); + if (ret != 0) { + INIT_LOGE("ParseJob, faild to get cmds for job!"); return; } - - if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(CmdLine), 0, cmdLinesCnt * sizeof(CmdLine)) != EOK) { - free(resJob->cmdLines); - resJob->cmdLines = NULL; - return; - } - resJob->cmdLinesCnt = cmdLinesCnt; - - for (int i = 0; i < cmdLinesCnt; ++i) { - char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); - ParseCmdLine(cmdLineStr, &(resJob->cmdLines[i])); - } + return; } -void ParseAllJobs(const cJSON* fileRoot) +void ParseAllJobs(const cJSON *fileRoot) { if (fileRoot == NULL) { INIT_LOGE("ParseAllJobs, input fileRoot is NULL!"); return; } - cJSON* jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON); + cJSON *jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON); if (!cJSON_IsArray(jobArr)) { INIT_LOGE("ParseAllJobs, job item is not array!"); return; @@ -125,13 +99,13 @@ void ParseAllJobs(const cJSON* fileRoot) return; } - Job* retJobs = (Job*)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize)); + Job *retJobs = (Job *)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize)); if (retJobs == NULL) { INIT_LOGE("ParseAllJobs, malloc failed! job arrSize %d.", jobArrSize); return; } - Job* tmp = retJobs + g_jobCnt; + Job *tmp = retJobs + g_jobCnt; if (memset_s(tmp, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) { INIT_LOGE("ParseAllJobs, memset_s failed."); free(retJobs); @@ -140,14 +114,14 @@ void ParseAllJobs(const cJSON* fileRoot) } for (int i = 0; i < jobArrSize; ++i) { - cJSON* jobItem = cJSON_GetArrayItem(jobArr, i); + cJSON *jobItem = cJSON_GetArrayItem(jobArr, i); ParseJob(jobItem, &(tmp[i])); } g_jobs = retJobs; g_jobCnt += jobArrSize; } -void DoJob(const char* jobName) +void DoJob(const char *jobName) { if (jobName == NULL) { INIT_LOGE("DoJob, input jobName NULL!"); @@ -157,9 +131,9 @@ void DoJob(const char* jobName) INIT_LOGD("Call job with name %s", jobName); for (int i = 0; i < g_jobCnt; ++i) { if (strncmp(jobName, g_jobs[i].name, strlen(g_jobs[i].name)) == 0) { - CmdLine* cmdLines = g_jobs[i].cmdLines; - for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) { - DoCmd(&(cmdLines[j])); + CmdLines *cmdLines = g_jobs[i].cmdLines; + for (int j = 0; j < cmdLines->cmdNum; ++j) { + DoCmdByIndex(cmdLines->cmds[i].cmdIndex, cmdLines->cmds[i].cmdContent); } } } @@ -174,13 +148,10 @@ void ReleaseAllJobs(void) for (int i = 0; i < g_jobCnt; ++i) { if (g_jobs[i].cmdLines != NULL) { free(g_jobs[i].cmdLines); - g_jobs[i].cmdLines = NULL; - g_jobs[i].cmdLinesCnt = 0; } } free(g_jobs); g_jobs = NULL; g_jobCnt = 0; -} - +} \ No newline at end of file diff --git a/services/include/init_perms.h b/services/init/lite/init_reboot.c old mode 100644 new mode 100755 similarity index 60% rename from services/include/init_perms.h rename to services/init/lite/init_reboot.c index ee8d9988e2d5b4339205d89dbf20323fa233d328..162f7e9d9bfd6e53e05a605c270a863e10156b3e --- a/services/include/init_perms.h +++ b/services/init/lite/init_reboot.c @@ -12,27 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_PERMS_H -#define BASE_STARTUP_INITLITE_PERMS_H +#include +#include +#include +#include +#include "init_log.h" -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -#define FULL_CAP 0xFFFFFFFF - -// init -#define DEFAULT_UMASK_INIT 022 - -// kit framework -#define DEFAULT_UID_KIT_FRAMEWORK 3 - -#ifdef __cplusplus -#if __cplusplus +void ExecReboot(const char *value) +{ + UNUSED(value); + int ret = reboot(RB_AUTOBOOT); + if (ret != 0) { + INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno); + } + return; } -#endif -#endif - -#endif // BASE_STARTUP_INITLITE_PERMS_H diff --git a/services/init/lite/init_service.c b/services/init/lite/init_service.c new file mode 100755 index 0000000000000000000000000000000000000000..fe314fef71ae6c09cc2ee364bcf8fe15fc5dbc94 --- /dev/null +++ b/services/init/lite/init_service.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 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_service.h" +#include +#include +#include +#include + +#include "init_log.h" +#include "init_service_manager.h" +#include "securec.h" + +void NotifyServiceChange(const char *serviceName, const char *change) +{ + UNUSED(serviceName); + UNUSED(change); +} + +int IsForbidden(const char *fieldStr) +{ + size_t fieldLen = strlen(fieldStr); + size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED); + if (fieldLen == forbidStrLen) { + if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) { + return 1; + } + return 0; + } else if (fieldLen > forbidStrLen) { + // "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid + if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) { + if (fieldStr[forbidStrLen] == ' ') { + return 1; + } + } + return 0; + } else { + return 0; + } +} + +int SetImportantValue(Service *service, const char *attrName, int value, int flag) +{ + UNUSED(attrName); + UNUSED(flag); + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); + if (value != 0) { + service->attribute |= SERVICE_ATTR_IMPORTANT; + } + return SERVICE_SUCCESS; +} + +int ServiceExec(Service *service) +{ + INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0, + return SERVICE_FAILURE, "Exec service failed! null ptr."); + INIT_LOGI("service->name is %s ", service->name); + char *env[] = { "LD_LIBRARY_PATH=/storage/app/libs", NULL }; + if (execve(service->pathArgs.argv[0], service->pathArgs.argv, env) != 0) { + INIT_LOGE("service %s execve failed! err %d.", service->name, errno); + return errno; + } + return SERVICE_SUCCESS; +} \ No newline at end of file diff --git a/services/init/lite/init_signal_handler.c b/services/init/lite/init_signal_handler.c new file mode 100755 index 0000000000000000000000000000000000000000..3bfb68c9d197f64bdb66bc2b7e6face7008b4f78 --- /dev/null +++ b/services/init/lite/init_signal_handler.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020 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 +#include +#include + +#include "init_adapter.h" +#include "init_log.h" +#include "init_service_manager.h" + +void ReapService(Service *service) +{ + if (service == NULL) { + return; + } + if (service->attribute & SERVICE_ATTR_IMPORTANT) { + // important process exit, need to reboot system + service->pid = -1; + StopAllServices(0); + RebootSystem(); + } + ServiceReap(service); +} + +static void SigHandler(int sig) +{ + switch (sig) { + case SIGCHLD: { + pid_t sigPID; + int procStat = 0; + while (1) { + sigPID = waitpid(-1, &procStat, WNOHANG); + if (sigPID <= 0) { + break; + } + INIT_LOGI("SigHandler, SIGCHLD received, sigPID = %d.", sigPID); + CheckWaitPid(sigPID); + ReapService(GetServiceByPid(sigPID)); + } + break; + } + case SIGTERM: { + INIT_LOGI("SigHandler, SIGTERM received."); + StopAllServices(0); + break; + } + default: + INIT_LOGI("SigHandler, unsupported signal %d.", sig); + break; + } +} + +void SignalInit(void) +{ + struct sigaction act; + act.sa_handler = SigHandler; + act.sa_flags = SA_RESTART; + (void)sigfillset(&act.sa_mask); + + sigaction(SIGCHLD, &act, NULL); + sigaction(SIGTERM, &act, NULL); +} \ No newline at end of file diff --git a/services/include/init_signal_handler.h b/services/init/main.c old mode 100644 new mode 100755 similarity index 56% rename from services/include/init_signal_handler.h rename to services/init/main.c index 433d4f99a696b8967a4aaa75447de37e18413aed..9dfd3791f0c26b913e8cfbbee20c6481fd6849d7 --- a/services/include/init_signal_handler.h +++ b/services/init/main.c @@ -12,31 +12,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include "init.h" +#include "init_log.h" -#ifndef BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H -#define BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H - -#ifdef __LINUX__ -#include -#include -#endif - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -void SignalInitModule(); - -#ifdef __LINUX__ -void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem); -#endif - -#ifdef __cplusplus -#if __cplusplus +static const pid_t INIT_PROCESS_PID = 1; +int main(int argc, char* const argv[]) +{ + UNUSED(argc); + UNUSED(argv); + SystemInit(); + if (getpid() != INIT_PROCESS_PID) { + INIT_LOGE("Process id error %d!", getpid()); + return 0; + } + SystemPrepare(); + SystemExecuteRcs(); + SystemConfig(); + SystemRun(); + return 0; } -#endif -#endif - -#endif // BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H diff --git a/services/src/device.c b/services/init/standard/device.c old mode 100644 new mode 100755 similarity index 94% rename from services/src/device.c rename to services/init/standard/device.c index 1c8a864745598be922c1e8d93f64f7af8638dc0b..bf50bcbc619c2676016443de534cdd2c13823f0a --- a/services/src/device.c +++ b/services/init/standard/device.c @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "device.h" #include #include @@ -20,6 +19,7 @@ #include #include #include + #include "init_log.h" #define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) @@ -77,18 +77,17 @@ void CreateDeviceNode(void) } } -int MakeSocketDir(const char *path, mode_t mode) +int MakeSocketDir(mode_t mode) { int rc = mkdir("/dev/unix/", mode); if (rc < 0 && errno != EEXIST) { - INIT_LOGE("Create %s failed. %d", path, errno); + INIT_LOGE("Failed to create /dev/unix, error:%d", errno); return -1; } rc = mkdir("/dev/unix/socket/", mode); if (rc < 0 && errno != EEXIST) { - INIT_LOGE("Create %s failed. %d", path, errno); + INIT_LOGE("Failed to create /dev/unix/socket, error:%d", errno); return -1; } return rc; } - diff --git a/services/init/standard/init.c b/services/init/standard/init.c new file mode 100755 index 0000000000000000000000000000000000000000..24a500295d4cab3904e80cda2560c8b953bbbc35 --- /dev/null +++ b/services/init/standard/init.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 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.h" +#include +#include + +#include "device.h" +#include "init_log.h" +#include "init_param.h" +#include "securec.h" + +void SystemInit(void) +{ + CloseStdio(); + OpenLogDevice(); +} + +void SystemPrepare(void) +{ + MountBasicFs(); + CreateDeviceNode(); + MakeSocketDir(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + EnableDevKmsg(); + SignalInit(); +} + +void SystemConfig(void) +{ + InitParamService(); + // parse parameters + LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); + LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL); + LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD); + + // read config + ReadConfig(); + INIT_LOGI("Parse init config file done."); + + // dump config +#ifdef OHOS_SERVICE_DUMP + DumpAllServices(); +#endif + + // execute init + PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); + PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init")); + PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init")); +} + +void SystemRun(void) +{ + StartParamService(); +} \ No newline at end of file diff --git a/services/init/standard/init_cmds.c b/services/init/standard/init_cmds.c new file mode 100755 index 0000000000000000000000000000000000000000..966e7a767ec466ff738cadd2d5fe51eed0929dc6 --- /dev/null +++ b/services/init/standard/init_cmds.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "init_cmds.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "init_jobs.h" +#include "init_log.h" +#include "init_param.h" +#include "init_service_manager.h" +#include "securec.h" + +#define OPTIONS_SIZE 128u +int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen) +{ + if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) { + return -1; + } + char tmpName[PARAM_NAME_LEN_MAX] = { 0 }; + int ret = 0; + uint32_t curr = 0; + char *start = (char *)symValue; + do { + char *begin = strchr(start, '$'); + if (begin == NULL) { // not has '$' copy the original string + ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen); + INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start); + break; + } else { + ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue); + curr += begin - start; + } + while (*begin != '{') { + begin++; + } + begin++; + char *end = strchr(begin, '}'); + if (end == NULL) { + return -1; + } + // copy param name + ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, end - begin); + INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue); + uint32_t valueLen = paramLen - curr; + ret = SystemReadParam(tmpName, paramValue + curr, &valueLen); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName); + curr += valueLen; + end++; + if ((end - symValue) >= symLen) { + break; + } + start = end; + } while (1); + return 0; +} + +static void DoIfup(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + struct ifreq interface; + if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) { + INIT_LOGE("DoIfup failed to copy interface name"); + return; + } + + INIT_LOGD("interface name: %s", interface.ifr_name); + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + INIT_LOGE("DoIfup failed to create socket, err = %d", errno); + return; + } + + if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) { + interface.ifr_flags |= IFF_UP; + if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) { + INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno); + } + } + close(fd); +} + +static void DoInsmodInternal(const char *fileName, char *secondPtr, char *restPtr, int flags) +{ + char options[OPTIONS_SIZE] = { 0 }; + if (flags == 0) { // '-f' option + if (restPtr != NULL && secondPtr != NULL) { // Reset arugments, combine then all. + if (snprintf_s(options, sizeof(options), OPTIONS_SIZE - 1, "%s %s", secondPtr, restPtr) == -1) { + return; + } + } else if (secondPtr != NULL) { + if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) { + return; + } + } + } else { // Only restPtr is option + if (restPtr != NULL) { + if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) { + return; + } + } + } + if (fileName == NULL) { + return; + } + char *realPath = realpath(fileName, NULL); + if (realPath == NULL) { + return; + } + int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) { + INIT_LOGE("failed to open %s: %d", realPath, errno); + free(realPath); + realPath = NULL; + return; + } + int rc = syscall(__NR_finit_module, fd, options, flags); + if (rc == -1) { + INIT_LOGE("finit_module for %s failed: %d", realPath, errno); + } + if (fd >= 0) { + close(fd); + } + free(realPath); + realPath = NULL; + return; +} + +// format insmod [-f] [options] +static void DoInsmod(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + char *p = NULL; + char *restPtr = NULL; + char *fileName = NULL; + char *line = NULL; + int flags = 0; + + size_t count = strlen(cmdContent); + if (count > OPTIONS_SIZE) { + INIT_LOGE("DoInsmod options too long, maybe lost some of options"); + } + line = (char *)malloc(count + 1); + if (line == NULL) { + INIT_LOGE("DoInsmod allocate memory failed."); + return; + } + + if (memcpy_s(line, count + 1, cmdContent, count) != EOK) { + INIT_LOGE("DoInsmod memcpy failed"); + free(line); + return; + } + line[count] = '\0'; + do { + if ((p = strtok_r(line, " ", &restPtr)) == NULL) { + INIT_LOGE("DoInsmod cannot get filename."); + free(line); + return; + } + fileName = p; + INIT_LOGI("DoInsmod fileName is [%s].", fileName); + if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) { + break; + } + if (!strcmp(p, "-f")) { + flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; + } + } while (0); + DoInsmodInternal(fileName, p, restPtr, flags); + if (line != NULL) { + free(line); + } + return; +} + +static void DoSetParam(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + INIT_LOGD("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]); + SystemWriteParam(ctx->argv[0], ctx->argv[1]); +} + +static void DoLoadPersistParams(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + INIT_LOGD("load persist params : %s", cmdContent); + LoadPersistParams(); +} + +static void DoTriggerCmd(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(ctx); + INIT_LOGD("DoTrigger :%s", cmdContent); + DoTriggerExec(cmdContent); +} + +static void DoLoadDefaultParams(const struct CmdArgs *ctx, const char *cmdContent) +{ + int mode = 0; + if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) { + mode = LOAD_PARAM_ONLY_ADD; + } + INIT_LOGD("DoLoadDefaultParams args : %s %d", cmdContent, mode); + LoadDefaultParams(ctx->argv[0], mode); +} + +static void DoExec(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: exec /xxx/xxx/xxx xxx + pid_t pid = fork(); + if (pid < 0) { + INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent); + return; + } + if (pid == 0) { + const struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC); + if (subCtx == NULL || subCtx->argv[0] == NULL) { + INIT_LOGE("DoExec: invalid arguments :%s", cmdContent); + _exit(0x7f); + } + int ret = execv(subCtx->argv[0], subCtx->argv); + if (ret == -1) { + INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno); + } + FreeCmdArg((struct CmdArgs *)subCtx); + _exit(0x7f); + } + return; +} + +static void DoSymlink(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx + int ret = symlink(ctx->argv[0], ctx->argv[1]); + if (ret != 0) { + INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno); + } +} + +static mode_t GetDeviceMode(const char *deviceStr) +{ + switch (*deviceStr) { + case 'b': + case 'B': + return S_IFBLK; + case 'c': + case 'C': + return S_IFCHR; + case 'f': + case 'F': + return S_IFIFO; + default: + return -1; + } +} + +static void DoMakeNode(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: mknod path b 0644 1 9 + const int deviceTypePos = 1; + const int authorityPos = 2; + const int majorDevicePos = 3; + const int minorDevicePos = 4; + const int decimal = 10; + const int octal = 8; + if (!access(ctx->argv[1], F_OK)) { + INIT_LOGE("DoMakeNode failed, path has not sexisted"); + return; + } + mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]); + errno = 0; + unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]); + unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]); + mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]); + int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor)); + if (ret != 0) { + INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno); + } +} + +static void DoMakeDevice(const struct CmdArgs *ctx, const char *cmdContent) +{ + UNUSED(cmdContent); + // format: makedev major minor + const int decimal = 10; + errno = 0; + unsigned int major = strtoul(ctx->argv[0], NULL, decimal); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]); + unsigned int minor = strtoul(ctx->argv[1], NULL, decimal); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]); + dev_t deviceId = makedev(major, minor); + if (deviceId < 0) { + INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno); + } +} + +static const struct CmdTable CMD_TABLE[] = { + { "exec ", 1, 10, DoExec }, + { "mknode ", 1, 5, DoMakeNode }, + { "makedev ", 2, 2, DoMakeDevice }, + { "symlink ", 2, 2, DoSymlink }, + { "trigger ", 1, 1, DoTriggerCmd }, + { "insmod ", 1, 10, DoInsmod }, + { "setparam ", 2, 2, DoSetParam }, + { "load_persist_params ", 1, 1, DoLoadPersistParams }, + { "load_param ", 1, 2, DoLoadDefaultParams }, + { "ifup ", 1, 1, DoIfup }, +}; + +const struct CmdTable *GetCmdTable(int *number) +{ + *number = (int)(sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0])); + return CMD_TABLE; +} \ No newline at end of file diff --git a/services/include/init_reboot.h b/services/init/standard/init_jobs.c old mode 100644 new mode 100755 similarity index 80% rename from services/include/init_reboot.h rename to services/init/standard/init_jobs.c index 181d811327ea1f4dfeb1bbf2c32b95ea8527687f..a0a300f18953dcf5980f87b4d06cc7e9f5bbdc9b --- a/services/include/init_reboot.h +++ b/services/init/standard/init_jobs.c @@ -13,9 +13,10 @@ * limitations under the License. */ -#ifndef INIT_REBOOT_H -#define INIT_REBOOT_H +#include "init_jobs.h" +#include "init_param.h" -void DoReboot(const char *value); - -#endif +void ParseAllJobs(const cJSON *fileRoot) +{ + ParseTriggerConfig(fileRoot); +} \ No newline at end of file diff --git a/services/src/init_reboot.c b/services/init/standard/init_reboot.c old mode 100644 new mode 100755 similarity index 51% rename from services/src/init_reboot.c rename to services/init/standard/init_reboot.c index f5242776d05e65a3f1a2a71e0e8892fac917d670..acf68fa226478fb95d6f1012dc3e9e3631e7b5f5 --- a/services/src/init_reboot.c +++ b/services/init/standard/init_reboot.c @@ -13,16 +13,12 @@ * limitations under the License. */ -#include "init_reboot.h" - #include #include #include -#include #include -#include #include -#include + #include "init_log.h" #include "init_service.h" #include "init_service_manager.h" @@ -38,68 +34,53 @@ struct RBMiscUpdateMessage { char update[MAX_UPDATE_SIZE]; }; -static bool RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot) +static int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot) { - if (path == NULL || boot == NULL) { - INIT_LOGE("path or boot is NULL."); - return false; - } char *realPath = realpath(path, NULL); if (realPath == NULL) { - return false; - } - FILE* fp = fopen(realPath, "rb+"); - if (fp == NULL) { - INIT_LOGE("open %s failed", path); - free(realPath); - realPath = NULL; - return false; + return -1; } - - size_t ret = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp); - if (ret < 0) { - INIT_LOGE("write to misc failed"); - free(realPath); - realPath = NULL; - fclose(fp); - return false; + int ret = 0; + FILE *fp = fopen(realPath, "rb+"); + if (fp != NULL) { + size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp); + if (writeLen != 1) { + INIT_LOGE("Failed to write misc for reboot"); + ret = -1; + } + } else { + ret = -1; + INIT_LOGE("Failed to open %s", path); } free(realPath); realPath = NULL; - fclose(fp); - return true; + (void)fclose(fp); + return ret; } -static bool RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot) +static int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot) { - if (path == NULL || boot == NULL) { - INIT_LOGE("path or boot is NULL."); - return false; - } char *realPath = realpath(path, NULL); if (realPath == NULL) { - return false; - } - FILE* fp = fopen(realPath, "rb"); - if (fp == NULL) { - INIT_LOGE("open %s failed", path); - free(realPath); - realPath = NULL; - return false; + return -1; } - size_t ret = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp); - if (ret <= 0) { - INIT_LOGE("read to misc failed"); - free(realPath); - realPath = NULL; - fclose(fp); - return false; + int ret = 0; + FILE *fp = fopen(realPath, "rb"); + if (fp != NULL) { + size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp); + if (readLen <= 0) { + ret = -1; + INIT_LOGE("Failed to read misc for reboot"); + } + } else { + ret = -1; + INIT_LOGE("Failed to open %s", path); } free(realPath); realPath = NULL; - fclose(fp); - return true; + (void)fclose(fp); + return ret; } static int GetMountStatusForMountPoint(const char *mountPoint) @@ -110,7 +91,6 @@ static int GetMountStatusForMountPoint(const char *mountPoint) const char *mountFile = "/proc/mounts"; FILE *fp = fopen(mountFile, "r"); if (fp == NULL) { - INIT_LOGE("DoReboot %s can't open.", mountPoint); return 1; } @@ -120,13 +100,11 @@ static int GetMountStatusForMountPoint(const char *mountPoint) buffer[n - 1] = '\0'; } if (strstr(buffer, mountPoint) != NULL) { - fclose(fp); + (void)fclose(fp); return 1; } } - - // Cannot find it from system. - fclose(fp); + (void)fclose(fp); return 0; } @@ -135,10 +113,10 @@ static int CheckAndRebootToUpdater(const char *valueData, const char *cmd, const // "updater" or "updater:" const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc"; struct RBMiscUpdateMessage msg; - bool bRet = RBMiscReadUpdaterMessage(miscFile, &msg); - INIT_ERROR_CHECK(bRet, return -1, "Failed to get misc info for %s.", cmd); + int ret = RBMiscReadUpdaterMessage(miscFile, &msg); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd); - int ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot); + ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot); INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd); msg.command[MAX_COMMAND_SIZE - 1] = 0; @@ -149,50 +127,55 @@ static int CheckAndRebootToUpdater(const char *valueData, const char *cmd, const msg.update[MAX_UPDATE_SIZE - 1] = 0; } - if (RBMiscWriteUpdaterMessage(miscFile, &msg)) { + if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) { return reboot(RB_AUTOBOOT); } return -1; } -void DoReboot(const char *value) +static int CheckRebootParam(const char *valueData) { + if (valueData == NULL) { + return 0; + } static const char *g_cmdParams[] = { - "shutdown", "updater", "updater:", "flashing", "flashing:", "NoArgument", "bootloader" + "shutdown", "updater", "updater:", "flash", "flash:", "NoArgument", "bootloader" }; - if (value == NULL || strlen(value) > MAX_VALUE_LENGTH) { - INIT_LOGE("DoReboot value = NULL"); - return; + size_t i = 0; + for (; i < ARRAY_LENGTH(g_cmdParams); i++) { + if (strncmp(valueData, g_cmdParams[i], strlen(g_cmdParams[i])) == 0) { + break; + } } + if (i >= ARRAY_LENGTH(g_cmdParams)) { + return -1; + } + return 0; +} + +void ExecReboot(const char *value) +{ + INIT_ERROR_CHECK(value != NULL && strlen(value) <= MAX_VALUE_LENGTH, return, "Invalid arg"); const char *valueData = NULL; - if (strcmp(value, "reboot") == 0) { - valueData = NULL; - } else if (strncmp(value, "reboot,", strlen("reboot,")) != 0) { - INIT_LOGE("DoReboot reboot value = %s, must started with reboot ,error.", value); - return; - } else { + if (strncmp(value, "reboot,", strlen("reboot,")) == 0) { valueData = value + strlen("reboot,"); + } else if (strcmp(value, "reboot") != 0) { + INIT_LOGE("Reboot value = %s, must started with reboot", value); + return; } - if (valueData != NULL) { - size_t i = 0; - for (; i < ARRAY_LENGTH(g_cmdParams); i++) { - if (strncmp(valueData, g_cmdParams[i], strlen(g_cmdParams[i])) == 0) { - break; - } - } - if (i >= ARRAY_LENGTH(g_cmdParams)) { - INIT_LOGE("DoReboot value = %s, parameters error.", value); - return; - } + if (CheckRebootParam(valueData) == 0) { + INIT_LOGE("Invalid arg % for reboot.", value); } - StopAllServicesBeforeReboot(); + + StopAllServices(SERVICE_ATTR_INVALID); sync(); if (GetMountStatusForMountPoint("/vendor") != 0 && umount("/vendor") != 0) { - INIT_LOGE("DoReboot umount vendor failed! errno = %d.", errno); + INIT_LOGE("Failed to umount vendor. errno = %d.", errno); } if (GetMountStatusForMountPoint("/data") != 0 && umount("/data") != 0) { - INIT_LOGE("DoReboot umount data failed! errno = %d.", errno); + INIT_LOGE("Failed umount data. errno = %d.", errno); } + int ret = 0; if (valueData == NULL) { ret = reboot(RB_AUTOBOOT); @@ -202,9 +185,9 @@ void DoReboot(const char *value) ret = reboot(RB_POWER_OFF); } else if (strncmp(valueData, "updater", strlen("updater")) == 0) { ret = CheckAndRebootToUpdater(valueData, "updater", "updater:", "boot_updater"); - } else if (strncmp(valueData, "flashing", strlen("flashing")) == 0) { - ret = CheckAndRebootToUpdater(valueData, "flashing", "flashing:", "boot_flashing"); + } else if (strncmp(valueData, "flash", strlen("flash")) == 0) { + ret = CheckAndRebootToUpdater(valueData, "flash", "flash:", "boot_flash"); } - INIT_LOGI("DoReboot value = %s %s.", value, (ret == 0) ? "success" : "fail"); + INIT_LOGI("Reboot %s %s.", value, (ret == 0) ? "success" : "fail"); return; } diff --git a/services/init/standard/init_service.c b/services/init/standard/init_service.c new file mode 100755 index 0000000000000000000000000000000000000000..d4e268ab0d863bc9a19356e81a2a8fdf1ef990a2 --- /dev/null +++ b/services/init/standard/init_service.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020 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_service.h" + +#include +#include +#include +#include +#include + +#include "init.h" +#include "init_log.h" +#include "init_param.h" +#include "securec.h" + +#define MIN_IMPORTANT_LEVEL (-20) +#define MAX_IMPORTANT_LEVEL 19 + +void NotifyServiceChange(const char *serviceName, const char *change) +{ + char paramName[PARAM_NAME_LEN_MAX] = { 0 }; + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) < 0) { + INIT_LOGE("snprintf_s paramName error %d ", errno); + } + SystemWriteParam(paramName, change); +} + +int IsForbidden(const char *fieldStr) +{ + UNUSED(fieldStr); + return 0; +} + +int SetImportantValue(Service *service, const char *attrName, int value, int flag) +{ + UNUSED(attrName); + UNUSED(flag); + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); + if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 + service->attribute |= SERVICE_ATTR_IMPORTANT; + service->importance = value; + } else { + INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value); + return SERVICE_FAILURE; + } + return SERVICE_SUCCESS; +} + +int ServiceExec(Service *service) +{ + INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0, + return SERVICE_FAILURE, "Exec service failed! null ptr."); + INIT_LOGI("service->name is %s ", service->name); + if (service->importance != 0) { + if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) { + INIT_LOGE("setpriority failed for %s, importance = %d", service->name, service->importance); + _exit(0x7f); // 0x7f: user specified + } + } + // L2 Can not be reset env + if (execv(service->pathArgs.argv[0], service->pathArgs.argv) != 0) { + INIT_LOGE("service %s execve failed! err %d.", service->name, errno); + } + return SERVICE_SUCCESS; +} \ No newline at end of file diff --git a/services/src/init_signal_handler.c b/services/init/standard/init_signal_handler.c old mode 100644 new mode 100755 similarity index 63% rename from services/src/init_signal_handler.c rename to services/init/standard/init_signal_handler.c index 81fdf42011d8960d5a94bf249d0d163c2e8b9385..7e98cf99016cf721017adb07c1ef59196fc9ca43 --- a/services/src/init_signal_handler.c +++ b/services/init/standard/init_signal_handler.c @@ -12,45 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include "init_signal_handler.h" - #include #include #include -#ifdef __LINUX__ -#include -#include -#endif /* __LINUX__ */ +#include "init_adapter.h" #include "init_log.h" +#include "init_param.h" #include "init_service_manager.h" - -#ifndef OHOS_LITE #include "uv.h" -#endif -#ifdef __LINUX__ -static pid_t g_waitPid = -1; -static sem_t* g_waitSem = NULL; - -void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem) -{ - g_waitPid = waitPid; - g_waitSem = waitSem; -} - -static void CheckWaitPid(pid_t sigPID) -{ - if (g_waitPid == sigPID && g_waitSem != NULL) { - if (sem_post(g_waitSem) != 0) { - INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno); - } - g_waitPid = -1; - g_waitSem = NULL; - } -} -#endif /* __LINUX__ */ +uv_signal_t g_sigchldHandler; +uv_signal_t g_sigtermHandler; static void SigHandler(int sig) { @@ -64,28 +37,25 @@ static void SigHandler(int sig) break; } -#ifndef OHOS_LITE // check child process exit status if (WIFSIGNALED(procStat)) { INIT_LOGE("Child process %d exit with signal: %d", sigPID, WTERMSIG(procStat)); } if (WIFEXITED(procStat)) { - INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS((unsigned int)procStat)); + INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS(procStat)); } -#endif INIT_LOGI("SigHandler, SIGCHLD received, sigPID = %d.", sigPID); -#ifdef __LINUX__ + CheckWaitPid(sigPID); -#endif /* __LINUX__ */ - ReapServiceByPID((int)sigPID); + ServiceReap(GetServiceByPid(sigPID)); } break; } case SIGTERM: { INIT_LOGI("SigHandler, SIGTERM received."); - StopAllServices(); + StopAllServices(0); break; } default: @@ -94,27 +64,12 @@ static void SigHandler(int sig) } } -#ifdef OHOS_LITE -void SignalInitModule() -{ - struct sigaction act; - act.sa_handler = SigHandler; - act.sa_flags = SA_RESTART; - (void)sigfillset(&act.sa_mask); - - sigaction(SIGCHLD, &act, NULL); - sigaction(SIGTERM, &act, NULL); -} -#else // L2 or above, use signal event in libuv -uv_signal_t g_sigchldHandler; -uv_signal_t g_sigtermHandler; - -static void UVSignalHandler(uv_signal_t* handle, int signum) +static void UVSignalHandler(uv_signal_t *handle, int signum) { SigHandler(signum); } -void SignalInitModule() +void SignalInit(void) { int ret = uv_signal_init(uv_default_loop(), &g_sigchldHandler); int ret1 = uv_signal_init(uv_default_loop(), &g_sigtermHandler); @@ -129,5 +84,4 @@ void SignalInitModule() if (uv_signal_start(&g_sigtermHandler, UVSignalHandler, SIGTERM) != 0) { INIT_LOGW("start SIGTERM handler failed"); } -} -#endif +} \ No newline at end of file diff --git a/services/log/init_log.h b/services/log/init_log.h index 84240a559ba8472e903c28fd6307a01f677d52c2..2a2634f83493e82c81b1724adfa4501d7751752d 100644 --- a/services/log/init_log.h +++ b/services/log/init_log.h @@ -74,6 +74,10 @@ void SetHiLogLevel(LogLevel logLevel); #define STARTUP_LOGI(LABEL, fmt, ...) InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "<6>", fmt "\n", ##__VA_ARGS__) #define STARTUP_LOGE(LABEL, fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt "\n", ##__VA_ARGS__) #else +#ifndef LABEL +#define LABEL "ParamAgent" +#endif + #include "hilog/log.h" #define PARAM_AGENT_LOG_PATH "/data/init_agent/init_agent.log" diff --git a/services/param/BUILD.gn b/services/param/BUILD.gn index 3249c348af373da7de9c4bdb62d70cba9ad6ed7f..62c914ceaf09472e2fe66fe690ad233bd1eb802d 100644 --- a/services/param/BUILD.gn +++ b/services/param/BUILD.gn @@ -28,7 +28,8 @@ ohos_prebuilt_etc("param_watcher.rc") { ohos_static_library("param_service") { sources = [ - "//base/startup/init_lite/services/src/list.c", + "//base/startup/init_lite/services/utils/list.c", + "//base/startup/init_lite/services/utils/init_utils.c", "adapter/param_libuvadp.c", "adapter/param_persistadp.c", "manager/param_manager.c", @@ -47,6 +48,7 @@ ohos_static_library("param_service") { "adapter", "//base/startup/init_lite/services/include/param", "//base/startup/init_lite/services/include", + "//base/startup/init_lite/services/init/include", "//base/startup/init_lite/services/log", "//third_party/libuv/include", "//third_party/cJSON", @@ -72,6 +74,7 @@ ohos_static_library("param_service") { ohos_shared_library("param_client") { sources = [ + "//base/startup/init_lite/services/utils/init_utils.c", "client/param_request.c", "manager/param_manager.c", "manager/param_message.c", @@ -206,7 +209,6 @@ ohos_executable("param") { "//base/startup/init_lite/services/log:agent_log", "//base/startup/init_lite/services/param:param_client", "//base/startup/init_lite/services/param:param_watcheragent", - "//base/update/updateservice/interfaces/innerkits/engine:updateservicekits", "//third_party/bounds_checking_function:libsec_static", ] external_deps = [ "hiviewdfx_hilog_native:libhilog" ] diff --git a/services/param/adapter/param_dac.c b/services/param/adapter/param_dac.c index 11adc177a80957641408b104cced66962ae968a2..bea8155a0e9cb5ea0fdbd0c98eedda7d9634f966 100755 --- a/services/param/adapter/param_dac.c +++ b/services/param/adapter/param_dac.c @@ -18,11 +18,11 @@ #include #include +#include "init_utils.h" #include "param_security.h" #include "param_utils.h" #define OCT_BASE 8 -#define LABEL "PARAM_DAC" static ParamSecurityLabel g_localSecurityLabel = {}; static void GetUserIdByName(FILE *fp, uid_t *uid, const char *name, uint32_t nameLen) diff --git a/services/param/adapter/param_libuvadp.c b/services/param/adapter/param_libuvadp.c index 1ce83379c6aeb475564e7e64c9d601c035b56718..ac994ca10ad521e0d3ff6acedc6fe976cfb9a2e7 100755 --- a/services/param/adapter/param_libuvadp.c +++ b/services/param/adapter/param_libuvadp.c @@ -15,7 +15,6 @@ #include "param_libuvadp.h" #include -#define LABEL "Libuvadp" static LibuvWorkSpace libuv = { NULL }; static const uint32_t RECV_BUFFER_MAX = 5 * 1024; @@ -285,9 +284,6 @@ int ParamTaskClose(ParamTaskPtr stream) } else if (stream->flags & WORKER_TYPE_MSG) { LibuvStreamTask *worker = (LibuvStreamTask *)stream; uv_close((uv_handle_t *)(&worker->stream.pipe), OnClientClose); - } else if (stream->flags & WORKER_TYPE_EVENT) { - LibuvAsyncEvent *event = (LibuvAsyncEvent *)stream; - uv_close((uv_handle_t *)&event->async, OnAsyncCloseCallback); } else { free(stream); } diff --git a/services/param/adapter/param_persistadp.c b/services/param/adapter/param_persistadp.c index 63673e4c1a4e94bb7fd3f01311c8e551df2c31be..e943ac4d286969cd37369b9569a16b60c04b18f4 100755 --- a/services/param/adapter/param_persistadp.c +++ b/services/param/adapter/param_persistadp.c @@ -21,8 +21,6 @@ #include "param_persist.h" #include "param_utils.h" -#define LABEL "PERSIST_ADP" - typedef struct { void *context; PersistParamGetPtr persistParamGet; diff --git a/services/param/adapter/param_selinux.c b/services/param/adapter/param_selinux.c index 139bfabc0d74d06d3e7e2a146bd4ef8c4bad4b58..becad78ab0d5e9c9e6168d8765792fe5b37ef871 100755 --- a/services/param/adapter/param_selinux.c +++ b/services/param/adapter/param_selinux.c @@ -15,12 +15,11 @@ #include +#include "init_utils.h" #include "param_security.h" #include "param_utils.h" -#define LABEL "PARAM_SELINUX" #define SELINUX_LABEL_LEN 128 - typedef struct SELinuxSecurityLabel { ParamSecurityLabel securityLabel; char label[SELINUX_LABEL_LEN]; diff --git a/services/param/client/param_request.c b/services/param/client/param_request.c index b8d83f39ec7e33a444afb0a38fda02a1aa154c32..2282aa274e63dcd25fd956716da52400191d05c1 100644 --- a/services/param/client/param_request.c +++ b/services/param/client/param_request.c @@ -26,7 +26,6 @@ #include "param_message.h" #define INVALID_SOCKET (-1) -#define LABEL "Client" static const uint32_t RECV_BUFFER_MAX = 5 * 1024; static atomic_uint g_requestId = ATOMIC_VAR_INIT(1); diff --git a/services/param/include/param_utils.h b/services/param/include/param_utils.h index 61decf08f413d91a29509694db52c021c948ad62..143e0eac1ccb6eef7b85ccf1004461a679bb4b24 100755 --- a/services/param/include/param_utils.h +++ b/services/param/include/param_utils.h @@ -50,14 +50,12 @@ typedef enum { #ifdef STARTUP_INIT_TEST #define PARAM_STATIC -#define PARAM_DEFAULT_PATH "" -#define PIPE_NAME "/data/paramservice" -#define PARAM_STORAGE_PATH PARAM_DEFAULT_PATH"/__parameters__/param_storage" -#define PARAM_PERSIST_SAVE_PATH PARAM_DEFAULT_PATH"/param/persist_parameters" -#define PARAM_PERSIST_SAVE_TMP_PATH PARAM_DEFAULT_PATH"/param/tmp_persist_parameters" +#define PARAM_DEFAULT_PATH "/data/init_ut" +#define PIPE_NAME PARAM_DEFAULT_PATH"/param/paramservice" +#define PARAM_STORAGE_PATH PARAM_DEFAULT_PATH "/param/param_storage" +#define PARAM_PERSIST_SAVE_PATH PARAM_DEFAULT_PATH "/param/persist_parameters" +#define PARAM_PERSIST_SAVE_TMP_PATH PARAM_DEFAULT_PATH "/param/tmp_persist_parameters" #define PARAM_CMD_LINE PARAM_DEFAULT_PATH"/proc/cmdline" -#define GROUP_FILE_PATH PARAM_DEFAULT_PATH"/etc/group" -#define USER_FILE_PATH PARAM_DEFAULT_PATH"/etc/passwd" #else #define PARAM_DEFAULT_PATH "" #define PARAM_STATIC static @@ -66,9 +64,10 @@ typedef enum { #define PARAM_PERSIST_SAVE_PATH "/data/parameters/persist_parameters" #define PARAM_PERSIST_SAVE_TMP_PATH "/data/parameters/tmp_persist_parameters" #define PARAM_CMD_LINE "/proc/cmdline" +#endif + #define GROUP_FILE_PATH "/etc/group" #define USER_FILE_PATH "/etc/passwd" -#endif #define WORKSPACE_FLAGS_INIT 0x01 #define WORKSPACE_FLAGS_LOADED 0x02 @@ -79,6 +78,10 @@ typedef enum { #define PARAM_CLEAR_FLAG(node, flag) ((node) &= ~(flag)) #define PARAM_TEST_FLAG(node, flag) (((node) & (flag)) == (flag)) +#ifndef LABEL +#define LABEL "Parameter" +#endif + #define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__) #define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__) #define PARAM_LOGD(fmt, ...) STARTUP_LOGD(LABEL, fmt, ##__VA_ARGS__) @@ -110,8 +113,6 @@ typedef struct { #define MAX_DATA_BUFFER 2048 char *ReadFileData(const char *fileName); void CheckAndCreateDir(const char *fileName); -int ReadFileInDir(const char *dirPath, const char *includeExt, - int (*processFile)(const char *fileName, void *context), void *context); int GetSubStringInfo(const char *buff, uint32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber); #ifdef __cplusplus #if __cplusplus diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c index 8324197cef7434b9e8a8714c02fc300292e47d7d..00fdf7345f23494c659e88f3b6edcade778d69c7 100644 --- a/services/param/manager/param_manager.c +++ b/services/param/manager/param_manager.c @@ -17,7 +17,6 @@ #include #include -#define LABEL "Manager" #if !defined PARAM_SUPPORT_SELINUX && !defined PARAM_SUPPORT_DAC static ParamSecurityLabel g_defaultSecurityLabel; #endif diff --git a/services/param/manager/param_message.c b/services/param/manager/param_message.c index 9d5d8dcfa9286fc15e1ffb90853e45c39102a678..72615ffb7781a0db1ba561c4351c0e0026cceca2 100755 --- a/services/param/manager/param_message.c +++ b/services/param/manager/param_message.c @@ -21,7 +21,6 @@ #include #include -#define LABEL "PARAM_MSG" int ConntectServer(int fd, const char *servername) { PARAM_CHECK(fd >= 0, return -1, "Invalid fd %d", fd); diff --git a/services/param/manager/param_trie.c b/services/param/manager/param_trie.c index 1de0df13449ca5c80d14de7b0aae25fc0df446b5..41d5e3a18a128ac132b11e998e5fc53028378885 100644 --- a/services/param/manager/param_trie.c +++ b/services/param/manager/param_trie.c @@ -31,8 +31,6 @@ #include "param_utils.h" #include "sys_param.h" -#define LABEL "Manager" - static int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, uint32_t spaceSize, int readOnly) { PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace"); diff --git a/services/param/manager/param_utils.c b/services/param/manager/param_utils.c index 7b1070cc610b3b16ea30dcc6b37f539e50667aa7..32f4ce19461c4f0685a3b4c4476e2bb1ae89756c 100755 --- a/services/param/manager/param_utils.c +++ b/services/param/manager/param_utils.c @@ -27,7 +27,6 @@ #include #include -#define LABEL "PARAM_UTILS" void CheckAndCreateDir(const char *fileName) { if (fileName == NULL || *fileName == '\0') { @@ -40,42 +39,6 @@ void CheckAndCreateDir(const char *fileName) free(path); } -int ReadFileInDir(const char *dirPath, const char *includeExt, - int (*processFile)(const char *fileName, void *context), void *context) -{ - DIR *pDir = opendir(dirPath); - PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno); - char *fileName = malloc(PARAM_BUFFER_SIZE); - PARAM_CHECK(fileName != NULL, closedir(pDir); - return -1, "Failed to malloc for %s", dirPath); - - struct dirent *dp; - while ((dp = readdir(pDir)) != NULL) { - if (dp->d_type == DT_DIR) { - continue; - } - PARAM_LOGD("ReadFileInDir %s", dp->d_name); - if (includeExt != NULL) { - char *tmp = strstr(dp->d_name, includeExt); - if (tmp == NULL) { - continue; - } - if (strcmp(tmp, includeExt) != 0) { - continue; - } - } - int ret = snprintf_s(fileName, PARAM_BUFFER_SIZE, PARAM_BUFFER_SIZE - 1, "%s/%s", dirPath, dp->d_name); - PARAM_CHECK(ret > EOK, continue, "Failed to get file name for %s", dp->d_name); - struct stat st; - if (stat(fileName, &st) == 0) { - processFile(fileName, context); - } - } - free(fileName); - closedir(pDir); - return 0; -} - char *ReadFileData(const char *fileName) { if (fileName == NULL) { diff --git a/services/param/service/param_persist.c b/services/param/service/param_persist.c index 09df4be2ae8a056ba962d43606728ece15112821..483155b9fb860863bd3e611e0cf91d351abfe4f2 100644 --- a/services/param/service/param_persist.c +++ b/services/param/service/param_persist.c @@ -24,8 +24,6 @@ #include "param_trie.h" #include "sys_param.h" -#define LABEL "Manager" - static ParamPersistWorkSpace g_persistWorkSpace = { 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } }; static int AddPersistParam(const char *name, const char *value, void *context) @@ -49,7 +47,6 @@ static int SavePersistParam(WorkSpace *workSpace, ParamTrieNode *node, void *coo if (entry == NULL) { return 0; } - PARAM_LOGD("SavePersistParam %s", entry->data); if (strncmp(entry->data, PARAM_CONST_PREFIX, strlen(PARAM_CONST_PREFIX)) != 0) { return 0; } @@ -113,15 +110,10 @@ int LoadPersistParam(ParamWorkSpace *workSpace) PARAM_LOGE("Persist param has been loaded"); return 0; } - ret = -1; if (g_persistWorkSpace.persistParamOps.load != NULL) { - ret = g_persistWorkSpace.persistParamOps.load(AddPersistParam, &workSpace->paramSpace); - } - if (ret == 0) { - PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); - } else { - PARAM_LOGE("Failed to load persist param "); + (void)g_persistWorkSpace.persistParamOps.load(AddPersistParam, &workSpace->paramSpace); } + PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); // 刷新新增的常量到persist BatchSavePersistParam(&workSpace->paramSpace); return 0; diff --git a/services/param/service/param_service.c b/services/param/service/param_service.c index e17b43d0381b4682bf2e4a36f20f214b974afdd5..ba9d38cc281987cff0254655ba37409742c2da13 100644 --- a/services/param/service/param_service.c +++ b/services/param/service/param_service.c @@ -26,12 +26,13 @@ #include #include "init_param.h" +#include "init_utils.h" #include "param_message.h" #include "param_manager.h" #include "param_request.h" #include "trigger_manager.h" -#define LABEL "ParamServer" + static ParamWorkSpace g_paramWorkSpace = { 0, {}, NULL, {}, NULL, NULL }; static void OnClose(ParamTaskPtr client) @@ -134,6 +135,8 @@ PARAM_STATIC int AddSecurityLabel(const ParamAuditData *auditData, void *context #ifdef STARTUP_INIT_TEST ParamSecruityNode *label = (ParamSecruityNode *)GetTrieNode(&workSpace->paramSpace, node->labelIndex); label->mode = auditData->dacData.mode; + label->uid = auditData->dacData.uid; + label->gid = auditData->dacData.gid; #endif PARAM_LOGE("Error, repeate to add label for name %s", auditData->name); } @@ -218,12 +221,12 @@ static int SystemSetParam(const char *name, const char *value, const ParamSecuri char *key = GetServiceCtrlName(name, value); if (srcLabel != NULL) { ret = CheckParamPermission(&g_paramWorkSpace, srcLabel, (key == NULL) ? name : key, DAC_WRITE); - PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name); } if (key != NULL) { serviceCtrl = 1; free(key); } + PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name); uint32_t dataIndex = 0; ret = WriteParam(&g_paramWorkSpace.paramSpace, name, value, &dataIndex, 0); PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); @@ -503,86 +506,94 @@ static void TimerCallback(ParamTaskPtr timer, void *context) } } -static int CopyBootParam(char *buffer, const char *key, size_t keyLen) +static int GetParamValueFromBuffer(const char *name, const char *buffer, char *value, int length) { + char *endData = (char *)buffer + strlen(buffer); size_t bootLen = strlen(OHOS_BOOT); - int ret = strncpy_s(buffer, PARAM_NAME_LEN_MAX - 1, OHOS_BOOT, bootLen); - PARAM_CHECK(ret == EOK, return -1, "Failed to cpy boot"); + char *tmp = strstr(buffer, name + bootLen); + do { + if (tmp == NULL) { + return -1; + } + tmp = tmp + strlen(name) - bootLen; + while (tmp < endData && *tmp == ' ') { + tmp++; + } + if (*tmp == '=') { + break; + } + tmp = strstr(tmp + 1, name + bootLen); + } while (tmp < endData); + tmp++; size_t i = 0; - for (; (i < PARAM_NAME_LEN_MAX - 1 - bootLen) && (i <= keyLen); i++) { - buffer[i + bootLen] = key[i]; - } - if (i > (PARAM_NAME_LEN_MAX - 1 - bootLen)) { - return -1; + size_t endIndex = 0; + while (tmp < endData && *tmp == ' ') { + tmp++; } - buffer[i + bootLen] = '\0'; - return 0; -} - -static int FindKey(const char *key, struct CmdLineEntry *cmdLineEntry, int length) -{ - PARAM_CHECK(key != NULL && cmdLineEntry != NULL && length > 0, return -1, "Input param error."); - for (int i = 0; i < length; i++) { - if (strstr(key, cmdLineEntry[i].key) != NULL) { - cmdLineEntry[i].set = 1; - return 1; + for (; i < length; tmp++) { + if (tmp >= endData) { + endIndex = i; + break; + } + if (*tmp == ' ') { + endIndex = i; + } + if (*tmp == '=') { + if (endIndex != 0) { // for root=uuid=xxxx + break; + } + i = 0; + endIndex = 0; + continue; } + value[i++] = *tmp; + } + if (i >= length) { + return -1; } + value[endIndex] = '\0'; return 0; } -static int LoadParamFromCmdLine(struct CmdLineEntry *cmdLineEntry, int length) +static int LoadParamFromCmdLine(void) { - PARAM_CHECK(cmdLineEntry != NULL && length > 0, return -1, "Input params error."); - char *buffer = ReadFileData(PARAM_CMD_LINE); - PARAM_CHECK(buffer != NULL, return -1, "Failed to read file %s", PARAM_CMD_LINE); - char *data = malloc(PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX); - PARAM_CHECK(data != NULL, free(buffer); + static const char *cmdLines[] = { + OHOS_BOOT"hardware", +#ifdef STARTUP_INIT_TEST + OHOS_BOOT"mem", + OHOS_BOOT"console", + OHOS_BOOT"mmz", + OHOS_BOOT"androidboot.selinux", + OHOS_BOOT"init", + OHOS_BOOT"root", + OHOS_BOOT"uuid", + OHOS_BOOT"aaaaa", + OHOS_BOOT"rootfstype", + OHOS_BOOT"blkdevparts", +#endif + }; + char *data = ReadFileData(PARAM_CMD_LINE); + PARAM_CHECK(data != NULL, return -1, "Failed to read file %s", PARAM_CMD_LINE); + char *value = malloc(PARAM_CONST_VALUE_LEN_MAX); + PARAM_CHECK(value != NULL, free(data); return -1, "Failed to read file %s", PARAM_CMD_LINE); - char *endBuffer = buffer + strlen(buffer); - char *key = data; - char *value = data + PARAM_NAME_LEN_MAX; - char *tmp = strchr(buffer, '='); - char *next = buffer; - while (tmp != 0) { - int ret = CopyBootParam(key, next, tmp - next - 1); - int ret1 = 0; - next = strchr(tmp + 1, '='); - if (next != NULL) { - while (!isspace(*next) && (next > buffer)) { // 直到属性值结束位置 - next--; - } - while (isspace(*next) && (next > buffer)) { // 去掉空格 - next--; - } - ret1 = strncpy_s(value, PARAM_CONST_VALUE_LEN_MAX - 1, tmp + 1, next - tmp); - next++; - while (isspace(*next) && (next < endBuffer)) { // 跳过空格 - next++; - } - } else { - ret1 = strncpy_s(value, PARAM_CONST_VALUE_LEN_MAX - 1, tmp + 1, endBuffer - tmp); - } - if ((ret == 0) && (ret1 == 0) && (CheckParamName(key, 0) == 0)) { + for (size_t i = 0; i < ARRAY_LENGTH(cmdLines); i++) { + int ret = GetParamValueFromBuffer(cmdLines[i], data, value, PARAM_CONST_VALUE_LEN_MAX); + if (ret == 0) { + PARAM_LOGD("Add param from cmdline %s %s", cmdLines[i], value); + ret = CheckParamName(cmdLines[i], 0); + PARAM_CHECK(ret == 0, return -1, "Invalid name %s", cmdLines[i]); uint32_t dataIndex = 0; - if (FindKey(key, cmdLineEntry, length) == 1) { - PARAM_LOGD("LoadParamFromCmdLine %s %s", key, value); - (void)WriteParam(&g_paramWorkSpace.paramSpace, key, value, &dataIndex, 0); - } - } - if (next == NULL) { - break; - } - tmp = strchr(next, '='); - } - for (int i = 0; i < length; i++) { - if (cmdLineEntry[i].set == 0) { - PARAM_LOGI("Warning, LoadParamFromCmdLine key %s is not found.", cmdLineEntry[i].key); + ret = WriteParam(&g_paramWorkSpace.paramSpace, cmdLines[i], value, &dataIndex, 0); + PARAM_CHECK(ret == 0, return -1, "Failed to write param %s %s", cmdLines[i], value); + } else { + PARAM_LOGE("Can not find arrt %s", cmdLines[i]); } } + PARAM_LOGD("Parse cmdline finish %s", PARAM_CMD_LINE); free(data); - free(buffer); + free(value); return 0; } @@ -682,8 +693,7 @@ void InitParamService(void) PARAM_CHECK(ret == 0, return, "Failed to add default dac label"); // 读取cmdline的参数 - struct CmdLineEntry cmdLineEntry[] = {{"hardware", 0}}; - LoadParamFromCmdLine(cmdLineEntry, sizeof(cmdLineEntry) / sizeof(cmdLineEntry[0])); + LoadParamFromCmdLine(); } static void OnPidDelete(pid_t pid) @@ -701,6 +711,7 @@ void StopParamService(void) PARAM_LOGI("StopParamService."); CloseParamWorkSpace(&g_paramWorkSpace); CloseTriggerWorkSpace(); + ParamTaskClose(g_paramWorkSpace.serverTask); g_paramWorkSpace.serverTask = NULL; ParamServiceStop(); } diff --git a/services/param/trigger/trigger_checker.c b/services/param/trigger/trigger_checker.c index 990ab9383fd362145b594a2d7d6fb3640affea56..c939e01a383931cddf4dc60fa398ec1dd4318e5c 100644 --- a/services/param/trigger/trigger_checker.c +++ b/services/param/trigger/trigger_checker.c @@ -20,7 +20,6 @@ #include "trigger_manager.h" #define MAX_CALC_PARAM 100 -#define LABEL "Trigger" // 申请整块能存作为计算的节点 int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition) { diff --git a/services/param/trigger/trigger_manager.c b/services/param/trigger/trigger_manager.c index fcf84ebc04dae1f3cbba94d600f6bd8bccb65225..b6824c1093caa03ef6bdd71f9b0cc1cfd82f9f9a 100644 --- a/services/param/trigger/trigger_manager.c +++ b/services/param/trigger/trigger_manager.c @@ -31,7 +31,6 @@ #include "param_manager.h" #include "trigger_checker.h" -#define LABEL "Trigger" int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content) { PARAM_CHECK(trigger != NULL, return -1, "trigger is null"); @@ -47,7 +46,7 @@ int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content) if (content != NULL && strlen(content) != 0) { int ret = memcpy_s(node->content, size, content, strlen(content)); node->content[strlen(content)] = '\0'; - PARAM_CHECK(ret == EOK, return 0, "Failed to copy command"); + PARAM_CHECK(ret == EOK, return -1, "Failed to copy command"); } // 插入队列 if (trigger->firstCmd == NULL) { diff --git a/services/param/trigger/trigger_processor.c b/services/param/trigger/trigger_processor.c index 1642767e327e78368f9ce64c3c502cbb5e683f44..80dbc3a7603461b7980fa8aa781f53d43aef7c78 100644 --- a/services/param/trigger/trigger_processor.c +++ b/services/param/trigger/trigger_processor.c @@ -22,7 +22,6 @@ #include "trigger_checker.h" #include "trigger_manager.h" -#define LABEL "Trigger" #define MAX_TRIGGER_COUNT_RUN_ONCE 20 static TriggerWorkSpace g_triggerWorkSpace = {}; @@ -46,16 +45,8 @@ static void DoCmdExec(TriggerNode *trigger, CommandNode *cmd, const char *conten } return; } - const char *cmdName = GetCmdKey(cmd->cmdKeyIndex); - if (cmdName == NULL) { - return; - } - if (strncmp(cmdName, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) { - DoTriggerExec(cmd->content); - return; - } #ifndef STARTUP_INIT_TEST - DoCmdByName(cmdName, cmd->content); + DoCmdByIndex(cmd->cmdKeyIndex, cmd->content); #endif } @@ -152,7 +143,7 @@ static void ProcessBeforeEvent(uint64_t eventId, const char *content, uint32_t s break; } default: - PARAM_LOGI("CheckTriggers: %lu", eventId); + PARAM_LOGI("CheckTriggers: %llu", eventId); break; } } @@ -162,7 +153,7 @@ static const char *GetCmdInfo(const char *content, uint32_t contentSize, char ** static const char *ctrlCmds[][2] = { {"reboot", "reboot "} }; - uint32_t index = 0; + int index = 0; for (size_t i = 0; i < sizeof(ctrlCmds) / sizeof(ctrlCmds[0]); i++) { if (strncmp(content, ctrlCmds[i][0], strlen(ctrlCmds[i][0])) == 0) { *cmdParam = (char *)content; @@ -265,7 +256,7 @@ static int ParseTrigger_(TriggerWorkSpace *workSpace, cJSON *triggerItem) PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name); int ret = 0; - uint32_t cmdKeyIndex = 0; + int cmdKeyIndex = 0; for (int i = 0; i < cmdLinesCnt; ++i) { char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i)); PARAM_CHECK(cmdLinesCnt > 0, continue, "Command is null"); @@ -275,9 +266,9 @@ static int ParseTrigger_(TriggerWorkSpace *workSpace, cJSON *triggerItem) PARAM_CHECK(matchCmd != NULL, continue, "Command not support %s", cmdLineStr); size_t matchLen = strlen(matchCmd); if (matchLen == cmdLineLen) { - ret = AddCommand(trigger, cmdKeyIndex, NULL); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, NULL); } else { - ret = AddCommand(trigger, cmdKeyIndex, cmdLineStr + matchLen); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, cmdLineStr + matchLen); } PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr); } diff --git a/services/param/watcher/include/watcher_utils.h b/services/param/watcher/include/watcher_utils.h index 1026e5c47203bae39226e7d5927d9e2c584a0de2..09aa72bc6a48465fcac0194f68c7cb8cf186791a 100755 --- a/services/param/watcher/include/watcher_utils.h +++ b/services/param/watcher/include/watcher_utils.h @@ -28,7 +28,7 @@ namespace init_param { #define UNUSED(x) (void)(x) #ifndef LABEL -#define LABEL "Watcher" +#define LABEL "ParameterWatcher" #endif #define WATCHER_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__) diff --git a/services/src/init_capability.c b/services/src/init_capability.c deleted file mode 100644 index d86b4b23334a14c7f5b51736aec8507e10a2aa8d..0000000000000000000000000000000000000000 --- a/services/src/init_capability.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2020 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_capability.h" - -#include -#include -#if defined OHOS_LITE && !defined __LINUX__ -#include -#else -#include -#endif -#include - -#include "init_log.h" -#include "init_perms.h" -#include "init_utils.h" - -#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100 - -struct CapStrCapNum { - char *capStr; - int CapNum; -}; - -static const struct CapStrCapNum g_capStrCapNum[] = { - {"CHOWN", CAP_CHOWN}, - {"DAC_OVERRIDE", CAP_DAC_OVERRIDE}, - {"DAC_READ_SEARCH", CAP_DAC_READ_SEARCH}, - {"FOWNER", CAP_FOWNER}, - {"FSETID", CAP_FSETID}, - {"KILL", CAP_KILL}, - {"SETGID", CAP_SETGID}, - {"SETUID", CAP_SETUID}, - {"SETPCAP", CAP_SETPCAP}, - {"LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE}, - {"NET_BIND_SERVICE", CAP_NET_BIND_SERVICE}, - {"NET_BROADCAST", CAP_NET_BROADCAST}, - {"NET_ADMIN", CAP_NET_ADMIN}, - {"NET_RAW", CAP_NET_RAW}, - {"IPC_LOCK", CAP_IPC_LOCK}, - {"IPC_OWNER", CAP_IPC_OWNER}, - {"SYS_MODULE", CAP_SYS_MODULE}, - {"SYS_RAWIO", CAP_SYS_RAWIO}, - {"SYS_CHROOT", CAP_SYS_CHROOT}, - {"SYS_PTRACE", CAP_SYS_PTRACE}, - {"SYS_PACCT", CAP_SYS_PACCT}, - {"SYS_ADMIN", CAP_SYS_ADMIN}, - {"SYS_BOOT", CAP_SYS_BOOT}, - {"SYS_NICE", CAP_SYS_NICE}, - {"SYS_RESOURCE", CAP_SYS_RESOURCE}, - {"SYS_TIME", CAP_SYS_TIME}, - {"SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG}, - {"MKNOD", CAP_MKNOD}, - {"LEASE", CAP_LEASE}, - {"AUDIT_WRITE", CAP_AUDIT_WRITE}, - {"AUDIT_CONTROL", CAP_AUDIT_CONTROL}, - {"SETFCAP", CAP_SETFCAP}, - {"MAC_OVERRIDE", CAP_MAC_OVERRIDE}, - {"MAC_ADMIN", CAP_MAC_ADMIN}, - {"SYSLOG", CAP_SYSLOG}, - {"WAKE_ALARM", CAP_WAKE_ALARM}, - {"BLOCK_SUSPEND", CAP_BLOCK_SUSPEND}, - {"AUDIT_READ", CAP_AUDIT_READ}, -}; - -static int GetServiceStringCaps(const cJSON* filedJ, Service* curServ) // string form -{ - unsigned int i = 0; - for (; i < curServ->servPerm.capsCnt; ++i) { - if (cJSON_GetArrayItem(filedJ, i) == NULL || !cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i)) - || strlen(cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))) <= 0) { // check all errors - INIT_LOGE("service=%s, parse item[%d] as string, error.", curServ->name, i); - break; - } - char* fieldStr = cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i)); - if (fieldStr == NULL) { - INIT_LOGE("fieldStr is NULL"); - break; - } - int mapSize = ARRAY_LENGTH(g_capStrCapNum); // search - int j = 0; - for (; j < mapSize; j++) { - if (!strcmp(fieldStr, g_capStrCapNum[j].capStr)) { - break; - } - } - if (j < mapSize) { - curServ->servPerm.caps[i] = g_capStrCapNum[j].CapNum; - } else { - INIT_LOGE("service=%s, CapbilityName=%s, error.", curServ->name, fieldStr); - break; - } - if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("service=%s, cap = %d, error.", curServ->name, curServ->servPerm.caps[i]); - return SERVICE_FAILURE; - } - } - int ret = (i == curServ->servPerm.capsCnt ? SERVICE_SUCCESS : SERVICE_FAILURE); - return ret; -} - -int GetServiceCaps(const cJSON* curArrItem, Service* curServ) -{ - if (curServ == NULL || curArrItem == NULL) { - INIT_LOGE("GetServiceCaps failed, curServ or curArrItem is NULL."); - return SERVICE_FAILURE; - } - curServ->servPerm.capsCnt = 0; - curServ->servPerm.caps = NULL; - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps"); - if (filedJ == NULL) { - return SERVICE_SUCCESS; - } - if (!cJSON_IsArray(filedJ)) { - INIT_LOGE("service=%s, caps is not a list, error.", curServ->name); - return SERVICE_FAILURE; - } - // caps array does not exist, means do not need any capability - int capsCnt = cJSON_GetArraySize(filedJ); - if (capsCnt <= 0) { - return SERVICE_SUCCESS; - } - if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) { - INIT_LOGE("service=%s, too many caps[cnt %d] for one service, max is %d.", - curServ->name, capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE); - return SERVICE_FAILURE; - } - curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt); - if (curServ->servPerm.caps == NULL) { - INIT_LOGE("GetServiceCaps, service=%s, malloc error.", curServ->name); - return SERVICE_FAILURE; - } - curServ->servPerm.capsCnt = capsCnt; - int i = 0; - for (; i < capsCnt; ++i) { // number form - cJSON* capJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) { - // resources will be released by function: ReleaseServiceMem - break; - } - curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ); - if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("service=%s, caps = %d, error.", curServ->name, curServ->servPerm.caps[i]); - return SERVICE_FAILURE; - } - } - if (i == capsCnt) { - return SERVICE_SUCCESS; - } - int ret = GetServiceStringCaps(filedJ, curServ); - return ret; -} - diff --git a/services/src/init_cmds.c b/services/src/init_cmds.c deleted file mode 100644 index 9663b4349b9dbc2b8fc8a120baa482904ac01316..0000000000000000000000000000000000000000 --- a/services/src/init_cmds.c +++ /dev/null @@ -1,1309 +0,0 @@ -/* - * Copyright (c) 2020-2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "init_cmds.h" - -#include -#include -#include -#ifndef OHOS_LITE -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "init_jobs.h" -#include "init_log.h" -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "init_reboot.h" -#include "init_service_manager.h" -#include "init_utils.h" -#include "securec.h" - -#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode -#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline -#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline - -#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline -#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K -#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop -#define OCTAL_TYPE 8 // 8 means octal to decimal -#define MAX_BUFFER 256UL -#define AUTHORITY_MAX_SIZE 128 -#define WAIT_MAX_COUNT 10 - -static const char *g_supportCfg[] = { - "/etc/patch.cfg", - "/patch/fstab.cfg", -}; - -#ifndef OHOS_LITE -int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen) -{ - if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) { - return -1; - } - char tmpName[MAX_PARAM_NAME_LEN] = {0}; - char tmpValue[MAX_PARAM_VALUE_LEN] = {0}; - char *p = NULL; - char *tmpptr = NULL; - p = strchr(symValue, '$'); - if (p == NULL) { // not has '$' copy the original string - INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, paramLen - 1) == EOK, -1); - return 0; - } - unsigned int tmpLen = p - symValue; - if (tmpLen > 0) { // copy '$' front string - INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, tmpLen) == EOK, -1); - } - p++; - if (*p == '{') { - p++; - char *right = strchr(p, '}'); - if (right == NULL) { - INIT_LOGE("Invalid cfg file name, miss '}'."); - return -1; - } - tmpLen = right - p; - if (tmpLen > MAX_PARAM_NAME_LEN) { - INIT_LOGE("Parameter name longer than %d", MAX_PARAM_NAME_LEN); - return -1; - } - INIT_CHECK_RETURN_VALUE(strncpy_s(tmpName, MAX_PARAM_NAME_LEN, p, tmpLen) == EOK, -1); - int ret = SystemReadParam(tmpName, tmpValue, &tmpLen); // get param - if (ret != 0) { - INIT_LOGE("Failed to read parameter \" %s \"", tmpName); - return -1; - } - // change param to new string - INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpValue, MAX_PARAM_VALUE_LEN) == EOK, -1); - tmpptr = right + 1; - tmpLen = paramLen - (tmpptr - symValue); - if (*tmpptr != '\0') { // copy last string - INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpptr, tmpLen) == EOK, -1); - } - INIT_LOGI("paramValue is %s ", paramValue); - return 0; - } else { - INIT_LOGE("Invalid cfg file name, miss '{'."); - return -1; - } -} -#else -// For ite ohos, do not support parameter operation. just do string copy -inline int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen) -{ - return (strncpy_s(paramValue, paramLen, symValue, strlen(symValue)) == EOK) ? 0 : -1; -} -#endif - -static struct CmdArgs *CopyCmd(struct CmdArgs *ctx, const char *cmd, size_t allocSize) -{ - if (cmd == NULL) { - FreeCmd(ctx); - return NULL; - } - - ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(ctx); - return NULL); - INIT_CHECK(GetParamValue(cmd, ctx->argv[ctx->argc], allocSize) == 0, FreeCmd(ctx); - return NULL); - ctx->argc += 1; - ctx->argv[ctx->argc] = NULL; - return ctx; -} - -#define SKIP_SPACES(p) \ - do { \ - while (isspace(*(p))) { \ - (p)++; \ - } \ - } while (0) - -struct CmdArgs *GetCmd(const char *cmdContent, const char *delim, int argsCount) -{ - INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL); - struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs)); - INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL); - - ctx->argv = (char**)malloc(sizeof(char*) * (size_t)(argsCount + 1)); - INIT_CHECK(ctx->argv != NULL, FreeCmd(ctx); - return NULL); - - char tmpCmd[MAX_BUFFER] = {0}; - size_t cmdLength = strlen(cmdContent); - if (cmdLength > MAX_BUFFER - 1) { - FreeCmd(ctx); - return NULL; - } - - INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK, FreeCmd(ctx); - return NULL); - - char *p = tmpCmd; - char *token = NULL; - size_t allocSize = 0; - - // Skip lead whitespaces - SKIP_SPACES(p); - ctx->argc = 0; - token = strstr(p, delim); - if (token == NULL) { // No whitespaces - // Make surce there is enough memory to store parameter value - allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1); - return CopyCmd(ctx, p, allocSize); - } - - while (token != NULL) { - // Too more arguments, treat rest of data as one argument - if (ctx->argc == (argsCount - 1)) { - break; - } - *token = '\0'; // replace it with '\0'; - allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1); - ctx = CopyCmd(ctx, p, allocSize); - INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL); - p = token + 1; // skip '\0' - // Skip lead whitespaces - SKIP_SPACES(p); - token = strstr(p, delim); - } - - if (p < tmpCmd + cmdLength) { - // no more white space or encounter max argument count - size_t restSize = tmpCmd + cmdLength - p; - allocSize = restSize + MAX_PARAM_VALUE_LEN + 1; - ctx = CopyCmd(ctx, p, allocSize); - INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL); - } - return ctx; -} - -void FreeCmd(struct CmdArgs *cmd) -{ - INIT_CHECK_ONLY_RETURN(cmd != NULL); - for (int i = 0; i < cmd->argc; ++i) { - INIT_CHECK(cmd->argv[i] == NULL, free(cmd->argv[i])); - } - INIT_CHECK(cmd->argv == NULL, free(cmd->argv)); - free(cmd); - return; -} - -static void WriteCommon(const char *file, char *buffer, int flags, mode_t mode) -{ - if (file == NULL || *file == '\0' || buffer == NULL || *buffer == '\0') { - INIT_LOGE("Invalid arugment"); - return; - } - char realPath[PATH_MAX] = {0}; - char *rp = realpath(file, realPath); - - if (rp == NULL) { - INIT_LOGE("Failed resolve real path name of %s", rp); - return; - } - - int fd = open(rp, flags, mode); - if (fd >= 0) { - size_t totalSize = strlen(buffer); - size_t written = WriteAll(fd, buffer, totalSize); - if (written != totalSize) { - INIT_LOGE("Write %lu bytes to file failed", totalSize, file); - } - close(fd); - } - fd = -1; -} - -static void DoSetDomainname(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) { - INIT_LOGE("Command setdomainname with invalid arugment"); - FreeCmd(ctx); - return; - } - - WriteCommon("/proc/sys/kernel/domainname", ctx->argv[0], O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); - FreeCmd(ctx); - return; -} - -static void DoSetHostname(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) { - INIT_LOGE("Command sethostname with invalid arugment"); - FreeCmd(ctx); - return; - } - WriteCommon("/proc/sys/kernel/hostname", ctx->argv[0], O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); - FreeCmd(ctx); - return; -} - -#ifndef OHOS_LITE -static void DoIfup(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) { - INIT_LOGE("Command ifup with invalid arguments"); - FreeCmd(ctx); - return; - } - - struct ifreq interface; - if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) { - INIT_LOGE("Failed to copy interface name"); - FreeCmd(ctx); - return; - } - - int fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd >= 0) { - do { - if (ioctl(fd, SIOCGIFFLAGS, &interface) < 0) { - INIT_LOGE("Failed to do ioctl with command \"SIOCGIFFLAGS\", err = %d", errno); - break; - } - interface.ifr_flags |= IFF_UP; - if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) { - INIT_LOGE("Failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno); - break; - } - } while (0); - close(fd); - fd = -1; - } - - FreeCmd(ctx); - return; -} -#endif - -static void DoSleep(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) { - INIT_LOGE("Command sleep with invalid arguments"); - FreeCmd(ctx); - return; - } - - unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); - // Limit sleep time in 5 seconds - const unsigned long sleepTimeLimit = 5; - if (sleepTime > sleepTimeLimit) { - sleepTime = sleepTimeLimit; - } - INIT_LOGI("Sleeping %d second(s)", sleepTime); - sleep((unsigned int)sleepTime); - - FreeCmd(ctx); - return; -} - -static void DoStart(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command start with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("Starting service \" %s \"", ctx->argv[0]); - StartServiceByName(ctx->argv[0], true); - - FreeCmd(ctx); - return; -} - -static void DoStop(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command stop with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("Stopping service \" %s \"", ctx->argv[0]); - StopServiceByName(ctx->argv[0]); - - FreeCmd(ctx); - return; -} - -static void DoReset(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command reset with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("Reseting service %s", ctx->argv[0]); - DoStop(ctx->argv[0], maxArg); - DoStart(ctx->argv[0], maxArg); - - FreeCmd(ctx); - return; -} - -static void DoCopyInernal(const char *source, const char *target) -{ - bool isSuccess = true; - if (source == NULL || target == NULL) { - INIT_LOGE("Copy file with invalid arguments"); - return; - } - - struct stat st = {0}; - int srcFd = open(source, O_RDONLY | O_CLOEXEC, S_IRUSR | S_IWUSR); - if (srcFd < 0) { - INIT_LOGE("Open \" %s \" failed, err = %d", source, errno); - close(srcFd); - srcFd = -1; - return; - } - - if (fstat(srcFd, &st) < 0) { - INIT_LOGE("Failed to get file \" %s \" stat", source); - close(srcFd); - srcFd = -1; - return; - } - int dstFd = open(target, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode); - if (dstFd >= 0) { - char buf[MAX_COPY_BUF_SIZE] = {0}; - ssize_t readn = -1; - ssize_t writen = -1; - while ((readn = read(srcFd, buf, MAX_COPY_BUF_SIZE - 1)) > 0) { - writen = WriteAll(dstFd, buf, (size_t)readn); - if (writen != readn) { - isSuccess = false; - break; - } - } - } - - if (!isSuccess) { - INIT_LOGE("Copy from \" %s \" to \" %s \" failed", source, target); - } else { - fsync(dstFd); - } - close(srcFd); - close(dstFd); - srcFd = -1; - dstFd = -1; -} - -static void DoCopy(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != DEFAULT_COPY_ARGS_CNT) { - INIT_LOGE("Command copy with invalid arguments"); - FreeCmd(ctx); - return; - } - char *sourceFile = realpath(ctx->argv[0], NULL); - char *targetFile = realpath(ctx->argv[1], NULL); - - if (sourceFile == NULL || targetFile == NULL) { - INIT_LOGE("Failed resolve real path name in copy command"); - FreeCmd(ctx); - return; - } - - DoCopyInernal(sourceFile, targetFile); - FreeCmd(ctx); - free(sourceFile); - free(targetFile); - ctx = NULL; - sourceFile = NULL; - targetFile = NULL; - return; -} - -static int Chown(const char *path, const char *uid, const char *gid) -{ - if (path == NULL || uid == NULL || gid == NULL) { - return -1; - } - uid_t user = DecodeUid(uid); - gid_t group = DecodeUid(gid); - if (user == (uid_t) -1 || group == (uid_t)-1) { - INIT_LOGE("Change path owner with invalid user/group"); - return -1; - } - - int rc = chown(path, user, group); - if (rc < 0) { - INIT_LOGE("Change path \" %s \" ower to user: %s group: %s failed", - path, uid, gid); - return -1; - } - return 0; -} - -static void DoChown(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command chown with invalid arguments"); - FreeCmd(ctx); - return; - } - const int uidPos = 0; - const int gidPos = 1; - const int pathPos = 2; - int ret = Chown(ctx->argv[pathPos], ctx->argv[uidPos], ctx->argv[gidPos]); - if (ret < 0) { - INIT_LOGE("Run command chown failed"); - } - FreeCmd(ctx); - return; -} - -static void DoMkDir(const char *cmdContent, int maxArg) -{ - // mkdir support format: - // 1.mkdir path - // 2.mkdir path mode - // 3.mkdir path mode owner group - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc < 1) { - INIT_LOGE("Command mkdir with invalid arguments"); - FreeCmd(ctx); - return; - } - int rc = -1; - do { - int index = 0; - rc = mkdir(ctx->argv[index], DEFAULT_DIR_MODE); - if (rc < 0) { - if (errno == EEXIST) { - INIT_LOGE("Path \" %s \" already exist", ctx->argv[0]); - rc = 0; - } - break; - } - - if (ctx->argv[++index] != NULL) { // mkdir with specific mode - mode_t mode = strtoul(ctx->argv[1], NULL, OCTAL_BASE); - rc = chmod(ctx->argv[0], mode); - if (rc < 0) { - INIT_LOGE("Change path \" %s \" mode to %04o failed", ctx->argv[0], mode); - break; - } - index = index + 1; - if ((ctx->argv[index] != NULL) && (ctx->argv[index + 1] != NULL)) { - rc = Chown(ctx->argv[0], ctx->argv[index], ctx->argv[index + 1]); - } else { - rc = -1; - } - } - } while (0); - - if (rc < 0) { - INIT_LOGE("Run command mkdir failed err = %d", errno); - (void)rmdir(ctx->argv[0]); - } - FreeCmd(ctx); -} - -static void DoChmod(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command chmod with invalid arguments"); - FreeCmd(ctx); - return; - } - - mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_BASE); - if (mode != 0) { - if (chmod(ctx->argv[1], mode) != 0) { - INIT_LOGE("Failed to change file \" %s \" mode to %04o, err = %d", ctx->argv[1], mode, errno); - } - } - FreeCmd(ctx); - return; -} - -static char* CopySubStr(const char *srcStr, size_t startPos, size_t endPos) -{ - if (endPos <= startPos) { - INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr); - return NULL; - } - - size_t mallocLen = endPos - startPos + 1; - char* retStr = (char*)malloc(mallocLen); - if (retStr == NULL) { - INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr); - return NULL; - } - - const char* copyStart = srcStr + startPos; - if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) { - INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr); - free(retStr); - return NULL; - } - retStr[mallocLen - 1] = '\0'; - - // for example, source may be none - if (strncmp(retStr, "none", strlen("none")) == 0) { - retStr[0] = '\0'; - } - return retStr; -} - -static int GetMountFlag(unsigned long *mountflags, const char *targetStr, const char *source) -{ - if (targetStr == NULL) { - return 0; - } - - if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) { - (*mountflags) |= MS_NODEV; - } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) { - (*mountflags) |= MS_NOEXEC; - } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) { - (*mountflags) |= MS_NOSUID; - } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) { - (*mountflags) |= MS_RDONLY; - } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) { - (*mountflags) |= MS_NOATIME; - } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) { - WaitForFile(source, WAIT_MAX_COUNT); - } else { - return 0; - } - return 1; -} - -static int CountSpaces(const char *cmdContent, size_t *spaceCnt, size_t *spacePosArr, size_t spacePosArrLen) -{ - *spaceCnt = 0; - size_t strLen = strlen(cmdContent); - for (size_t i = 0; i < strLen; ++i) { - if (cmdContent[i] == ' ') { - ++(*spaceCnt); - if ((*spaceCnt) > spacePosArrLen) { - INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent); - return 0; - } - spacePosArr[(*spaceCnt) - 1] = i; - } - } - - if ((*spaceCnt) < SPACES_CNT_IN_CMD_MIN || // spaces count should not less than 2(at least 3 items) - spacePosArr[0] == 0 || // should not start with space - spacePosArr[(*spaceCnt) - 1] == strLen - 1) { // should not end with space - INIT_LOGE("DoMount, bad format for %s.", cmdContent); - return 0; - } - - // spaces should not be adjacent - for (size_t i = 1; i < (*spaceCnt); ++i) { - if (spacePosArr[i] == spacePosArr[i - 1] + 1) { - INIT_LOGE("DoMount, bad format for %s.", cmdContent); - return 0; - } - } - return 1; -} - -static void DoMount(const char *cmdContent, int maxArg) -{ - size_t spaceCnt = 0; - size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = {0}; - if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) { - return; - } - - // format: fileSystemType source target mountFlag1 mountFlag2... data - unsigned long mountflags = 0; - size_t strLen = strlen(cmdContent); - size_t indexOffset = 0; - char* fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]); - if (fileSysType == NULL) { - return; - } - - char* source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]); - if (source == NULL) { - free(fileSysType); - return; - } - ++indexOffset; - - // maybe only has "filesystype source target", 2 spaces - size_t targetEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; - char* target = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, targetEndPos); - if (target == NULL) { - free(fileSysType); - free(source); - return; - } - ++indexOffset; - - // get mountflags, if fail, the rest part of string will be data - while (indexOffset < spaceCnt) { - size_t tmpStrEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; - char* tmpStr = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, tmpStrEndPos); - int ret = GetMountFlag(&mountflags, tmpStr, source); - free(tmpStr); - tmpStr = NULL; - - // get flag failed, the rest part of string will be data - if (ret == 0) { - break; - } - ++indexOffset; - } - - int mountRet; - if (indexOffset >= spaceCnt) { // no data - mountRet = mount(source, target, fileSysType, mountflags, NULL); - } else { - const char* dataStr = cmdContent + spacePosArr[indexOffset] + 1; - mountRet = mount(source, target, fileSysType, mountflags, dataStr); - } - - if (mountRet != 0) { - INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno); - } - - free(fileSysType); - free(source); - free(target); -} - -#ifndef OHOS_LITE -#define OPTIONS_SIZE 128u -static void DoInsmodInternal(const char *fileName, const char *secondPtr, const char *restPtr, int flags) -{ - char options[OPTIONS_SIZE] = {0}; - if (flags == 0) { // '-f' option - if (restPtr != NULL && secondPtr != NULL) { // Reset arugments, combine then all. - if (snprintf_s(options, sizeof(options), OPTIONS_SIZE -1, "%s %s", secondPtr, restPtr) == -1) { - return; - } - } else if (secondPtr != NULL) { - if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) { - return; - } - } - } else { // Only restPtr is option - if (restPtr != NULL) { - if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) { - return; - } - } - } - if (fileName == NULL) { - return; - } - char *realPath = realpath(fileName, NULL); - if (realPath == NULL) { - return; - } - int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) { - INIT_LOGE("failed to open %s: %d", realPath, errno); - free(realPath); - realPath = NULL; - return; - } - int rc = syscall(__NR_finit_module, fd, options, flags); - if (rc == -1) { - INIT_LOGE("finit_module for %s failed: %d", realPath, errno); - } - if (fd >= 0) { - close(fd); - } - free(realPath); - realPath = NULL; - return; -} - -// format insmod [-f] [options] -static void DoInsmod(const char *cmdContent, int maxArg) -{ - char *p = NULL; - char *restPtr = NULL; - char *fileName = NULL; - char *line = NULL; - int flags = 0; - - size_t count = strlen(cmdContent); - if (count > OPTIONS_SIZE) { - INIT_LOGE("DoInsmod options too long, maybe lost some of options"); - } - line = (char *)malloc(count + 1); - if (line == NULL) { - INIT_LOGE("DoInsmod allocate memory failed."); - return; - } - - if (memcpy_s(line, count + 1, cmdContent, count) != EOK) { - INIT_LOGE("DoInsmod memcpy failed"); - free(line); - return; - } - line[count] = '\0'; - do { - if ((p = strtok_r(line, " ", &restPtr)) == NULL) { - INIT_LOGE("DoInsmod cannot get filename."); - free(line); - return; - } - fileName = p; - INIT_LOGI("DoInsmod fileName is [%s].", fileName); - if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) { - break; - } - if (!strcmp(p, "-f")) { - flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; - } - } while (0); - DoInsmodInternal(fileName, p, restPtr, flags); - if (line != NULL) { - free(line); - } - return; -} - -static void DoSetParam(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command setparam with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]); - SystemWriteParam(ctx->argv[0], ctx->argv[1]); - - FreeCmd(ctx); - return; -} - - -static void DoLoadPersistParams(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command load_persist_params with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("load persist params : %s", cmdContent); - LoadPersistParams(); - FreeCmd(ctx); - return; -} - -static void DoTriggerCmd(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command trigger with invalid arguments"); - FreeCmd(ctx); - return; - } - INIT_LOGD("Trigger job :%s", ctx->argv[0]); - DoTriggerExec(ctx->argv[0]); - FreeCmd(ctx); - return; -} - -static void DoLoadDefaultParams(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command load_param with invalid arguments"); - FreeCmd(ctx); - return; - } - int mode = 0; - if (strcmp(ctx->argv[1], "onlyadd") == 0) { - mode = LOAD_PARAM_ONLY_ADD; - } - LoadDefaultParams(ctx->argv[0], mode); - FreeCmd(ctx); - return; -} - -#endif // OHOS_LITE - -static bool CheckValidCfg(const char *path) -{ - size_t cfgCnt = ARRAY_LENGTH(g_supportCfg); - struct stat fileStat = {0}; - - if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) { - return false; - } - - for (size_t i = 0; i < cfgCnt; ++i) { - if (strcmp(path, g_supportCfg[i]) == 0) { - return true; - } - } - return false; -} - -static void DoLoadCfg(const char *path, int maxArg) -{ - char buf[LOADCFG_BUF_SIZE] = {0}; - FILE *fp = NULL; - size_t maxLoop = 0; - CmdLine *cmdLine = NULL; - size_t len; - INIT_CHECK_ONLY_RETURN(path != NULL); - INIT_LOGI("DoLoadCfg cfg file %s", path); - if (!CheckValidCfg(path)) { - INIT_LOGE("CheckCfg file %s Failed", path); - return; - } - INIT_ERROR_CHECK(path != NULL, return, "CheckCfg path is NULL."); - char *realPath = realpath(path, NULL); - INIT_CHECK_ONLY_RETURN(realPath != NULL); - fp = fopen(realPath, "r"); - if (fp == NULL) { - INIT_LOGE("open cfg error = %d", errno); - free(realPath); - realPath = NULL; - return; - } - - cmdLine = (CmdLine *)malloc(sizeof(CmdLine)); - if (cmdLine == NULL) { - INIT_LOGE("malloc cmdline error"); - fclose(fp); - free(realPath); - realPath = NULL; - return; - } - - while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) { - maxLoop++; - len = strlen(buf); - if (len < 1) { - continue; - } - if (buf[len - 1] == '\n') { - buf[len - 1] = '\0'; // we replace '\n' with '\0' - } - (void)memset_s(cmdLine, sizeof(CmdLine), 0, sizeof(CmdLine)); - ParseCmdLine(buf, cmdLine); - DoCmd(cmdLine); - (void)memset_s(buf, sizeof(char) * LOADCFG_BUF_SIZE, 0, sizeof(char) * LOADCFG_BUF_SIZE); - } - free(realPath); - realPath = NULL; - free(cmdLine); - fclose(fp); -} - -static void DoWrite(const char *cmdContent, int maxArg) -{ - // format: write path content - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command write with invalid arguments"); - FreeCmd(ctx); - return; - } - - WriteCommon(ctx->argv[0], ctx->argv[1], O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, - S_IRUSR | S_IWUSR); - - FreeCmd(ctx); - return; -} - -static void DoRmdir(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command rmdir with invalid arguments"); - FreeCmd(ctx); - return; - } - - int ret = rmdir(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("Remove directory \" %s \" failed, err = %d", ctx->argv[0], errno); - } - FreeCmd(ctx); - return; -} - -static void DoRebootCmd(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command reboot with invalid arguments"); - FreeCmd(ctx); - return; - } - DoReboot(cmdContent); - FreeCmd(ctx); - return; -} - -static void DoSetrlimit(const char *cmdContent, int maxArg) -{ - static const char *resource[] = { - "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS", - "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING", - "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS" - }; - // format: setrlimit resource curValue maxValue - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int rlimMaxPos = 2; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command setrlimit with invalid arguments"); - FreeCmd(ctx); - return; - } - - struct rlimit limit; - limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]); - limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]); - int rcs = -1; - for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) { - if (strcmp(ctx->argv[0], resource[i]) == 0) { - rcs = (int)i; - } - } - if (rcs == -1) { - INIT_LOGE("Set limit with unsupported resource \" %s \"", ctx->argv[0]); - } else { - int ret = setrlimit(rcs, &limit); - if (ret) { - INIT_LOGE("Set limit with resource %s, value : %lu, max value: %lu failed, err = %d", - ctx->argv[0], limit.rlim_cur, limit.rlim_max, errno); - } - } - FreeCmd(ctx); - return; -} - -static void DoRm(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command rm with invalid arguments"); - FreeCmd(ctx); - return; - } - int ret = unlink(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("Unlink %s failed, err = %d", ctx->argv[0], errno); - } - FreeCmd(ctx); - return; -} - -static void DoExport(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command export with invalid arguments"); - FreeCmd(ctx); - return; - } - int ret = setenv(ctx->argv[0], ctx->argv[1], 1); - if (ret != 0) { - INIT_LOGE("export env name \" %s \", value \" %s \" failed, err = %d ", - ctx->argv[0], ctx->argv[1], errno); - } - - FreeCmd(ctx); - return; -} - -static void DoExec(const char *cmdContent, int maxArg) -{ - pid_t pid = fork(); - if (pid < 0) { - INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent); - return; - } - if (pid == 0) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) { - INIT_LOGE("Command exec with invalid arguments"); - _exit(0x7f); - } -#ifdef OHOS_LITE - int ret = execve(ctx->argv[0], ctx->argv, NULL); -#else - int ret = execv(ctx->argv[0], ctx->argv); -#endif - if (ret == -1) { - INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno); - } - FreeCmd(ctx); - _exit(0x7f); - } - return; -} - -#ifndef __LITEOS__ -static void DoSymlink(const char *cmdContent, int maxArg) -{ - // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command symlink with invalid arguments"); - FreeCmd(ctx); - return; - } - - int ret = symlink(ctx->argv[0], ctx->argv[1]); - if (ret != 0) { - INIT_LOGE("Link \" %s \" to target \" %s \" failed, err = %d", ctx->argv[0], ctx->argv[1], errno); - } - - FreeCmd(ctx); - return; -} - -static mode_t GetDeviceMode(const char *deviceStr) -{ - switch (*deviceStr) { - case 'b': - case 'B': - return S_IFBLK; - case 'c': - case 'C': - return S_IFCHR; - case 'f': - case 'F': - return S_IFIFO; - default: - return -1; - } -} - -static void DoMakeNode(const char *cmdContent, int maxArg) -{ - // format: mknod path b 0644 1 9 - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int deviceTypePos = 1; - const int authorityPos = 2; - const int majorDevicePos = 3; - const int minorDevicePos = 4; - - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command mknode with invalid arguments"); - FreeCmd(ctx); - return; - } - - if (!access(ctx->argv[1], F_OK)) { - INIT_LOGE("Cannot access \" %s \", err = %d", ctx->argv[1], errno); - } else { - mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]); - unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, DECIMAL_BASE); - unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, DECIMAL_BASE); - mode_t mode = strtoul(ctx->argv[authorityPos], NULL, OCTAL_BASE); - - int ret = mknod(ctx->argv[0], deviceMode | mode, makedev(major, minor)); - if (ret != 0) { - INIT_LOGE("Create device node \" %s \" failed, err = %d", ctx->argv[0], errno); - } - } - - FreeCmd(ctx); - return; -} - -static void DoMakeDevice(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("Command makedev with invalid arguments"); - FreeCmd(ctx); - return; - } - unsigned int major = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); - unsigned int minor = strtoul(ctx->argv[1], NULL, DECIMAL_BASE); - if (major == 0 || minor == 0) { - return; - } - dev_t deviceId = makedev(major, minor); - if (deviceId < 0) { - INIT_LOGE("Make device with major %u, minor %u failed :%d ", major, minor, errno); - } - - FreeCmd(ctx); - return; -} -#endif // __LITEOS__ - -void DoCmd(const CmdLine *curCmd) -{ - // null curCmd or empty command, just quit. - if (curCmd == NULL || curCmd->name[0] == '\0') { - return; - } - DoCmdByName(curCmd->name, curCmd->cmdContent); -} - -struct CmdTable { - char name[MAX_CMD_NAME_LEN]; - int maxArg; - void (*DoFuncion)(const char *cmdContent, int maxArg); -}; - -static const struct CmdTable CMD_TABLE[] = { - { "start ", 1, DoStart }, - { "mkdir ", 4, DoMkDir }, - { "chmod ", 2, DoChmod }, - { "chown ", 3, DoChown }, - { "mount ", 10, DoMount }, - { "export ", 2, DoExport }, - { "loadcfg ", 1, DoLoadCfg }, - { "rm ", 1, DoRm }, - { "rmdir ", 1, DoRmdir }, - { "write ", 2, DoWrite }, - { "exec ", 10, DoExec }, -#ifndef OHOS_LITE - { "mknode ", 5, DoMakeNode }, - { "makedev ", 2, DoMakeDevice }, - { "symlink ", 2, DoSymlink }, - { "trigger ", 1, DoTriggerCmd }, - { "insmod ", 10, DoInsmod }, - { "setparam ", 2, DoSetParam }, - { "load_persist_params ", 1, DoLoadPersistParams }, - { "load_param ", 2, DoLoadDefaultParams }, - { "ifup ", 1, DoIfup }, -#endif - { "stop ", 1, DoStop }, - { "reset ", 1, DoReset }, - { "copy ", 2, DoCopy }, - { "reboot ", 1, DoRebootCmd }, - { "setrlimit ", 3, DoSetrlimit }, - { "sleep ", 1, DoSleep }, - { "hostname ", 1, DoSetHostname }, - { "domainname ", 1, DoSetDomainname } -}; - -void DoCmdByName(const char *name, const char *cmdContent) -{ - if (name == NULL || cmdContent == NULL) { - return; - } - - size_t cmdCnt = ARRAY_LENGTH(CMD_TABLE); - unsigned int i = 0; - for (; i < cmdCnt; ++i) { - if (strncmp(name, CMD_TABLE[i].name, strlen(CMD_TABLE[i].name)) == 0) { - CMD_TABLE[i].DoFuncion(cmdContent, CMD_TABLE[i].maxArg); - break; - } - } - if (i == cmdCnt) { - INIT_LOGE("DoCmd, unknown cmd name %s.", name); - } -} - -void ParseCmdLine(const char *cmdStr, CmdLine *resCmd) -{ - size_t cmdLineLen = 0; - if (cmdStr == NULL || resCmd == NULL || (cmdLineLen = strlen(cmdStr)) == 0) { - return; - } - - size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE); - int foundAndSucceed = 0; - for (size_t i = 0; i < supportCmdCnt; ++i) { - size_t curCmdNameLen = strlen(CMD_TABLE[i].name); - if (cmdLineLen > curCmdNameLen && cmdLineLen <= (curCmdNameLen + MAX_CMD_CONTENT_LEN) && - strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) { - if (memcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmdStr, curCmdNameLen) != EOK) { - break; - } - resCmd->name[curCmdNameLen] = '\0'; - - const char* cmdContent = cmdStr + curCmdNameLen; - size_t cmdContentLen = cmdLineLen - curCmdNameLen; - if (memcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, cmdContent, cmdContentLen) != EOK) { - break; - } - resCmd->cmdContent[cmdContentLen] = '\0'; - foundAndSucceed = 1; - break; - } - } - - if (!foundAndSucceed) { - INIT_LOGE("Cannot parse command: %s", cmdStr); - (void)memset_s(resCmd, sizeof(*resCmd), 0, sizeof(*resCmd)); - } -} - -const char *GetMatchCmd(const char *cmdStr, unsigned int *index) -{ - if (cmdStr == NULL || index == NULL) { - return NULL; - } - size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE); - for (size_t i = 0; i < supportCmdCnt; ++i) { - size_t curCmdNameLen = strlen(CMD_TABLE[i].name); - if (strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) { - *index = (unsigned int)i; - return CMD_TABLE[i].name; - } - } - return NULL; -} - -const char *GetCmdKey(unsigned int index) -{ - size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE); - if (index >= supportCmdCnt) { - return NULL; - } - return CMD_TABLE[index].name; -} \ No newline at end of file diff --git a/services/src/init_read_cfg.c b/services/src/init_read_cfg.c deleted file mode 100644 index 732f7db87370a7c86b538b38328d7dee6d7939d0..0000000000000000000000000000000000000000 --- a/services/src/init_read_cfg.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2020 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_read_cfg.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "init_import.h" -#include "init_jobs.h" -#include "init_log.h" -#include "init_perms.h" -#include "init_service_manager.h" -#include "init_utils.h" - -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "securec.h" -#ifndef __LINUX__ -#ifdef OHOS_LITE -#include "init_stage.h" -#endif -#endif - -#define FILE_NAME_MAX_SIZE 100 -static void ParseInitCfgContents(const cJSON *root) -{ - if (root == NULL) { - INIT_LOGE("ParseInitCfgContents root is NULL"); - return; - } - // parse services - ParseAllServices(root); -#ifdef OHOS_LITE - // parse jobs - ParseAllJobs(root); -#else - ParseTriggerConfig(root); -#endif - - // parse imports - ParseAllImports(root); -} - -void ParseInitCfg(const char *configFile) -{ - if (configFile == NULL || *configFile == '\0') { - INIT_LOGE("Invalid config file"); - return; - } - - char *fileBuf = ReadFileToBuf(configFile); - if (fileBuf == NULL) { - INIT_LOGE("Read %s failed", configFile); - return; - } - cJSON* fileRoot = cJSON_Parse(fileBuf); - free(fileBuf); - fileBuf = NULL; - - if (fileRoot == NULL) { - INIT_LOGE("InitReadCfg, parse failed! please check file %s format.", configFile); - return; - } - ParseInitCfgContents(fileRoot); - // Release JSON object - cJSON_Delete(fileRoot); - return; -} - -static void ReadCfgs(const char *dirPath) -{ - DIR *pDir = opendir(dirPath); - if (pDir == NULL) { - INIT_LOGE("ParseCfgs open cfg dir :%s failed.%d", dirPath, errno); - return; - } - struct dirent *dp; - while ((dp = readdir(pDir)) != NULL) { - char fileName[FILE_NAME_MAX_SIZE]; - if (snprintf_s(fileName, FILE_NAME_MAX_SIZE, FILE_NAME_MAX_SIZE - 1, "%s/%s", dirPath, dp->d_name) == -1) { - INIT_LOGE("ParseCfgs snprintf_s failed."); - closedir(pDir); - return; - } - struct stat st; - if (stat(fileName, &st) == 0) { - if (strstr(dp->d_name, ".cfg") == NULL) { - continue; - } - INIT_LOGI("ReadCfgs :%s from %s success.", fileName, dirPath); - ParseInitCfg(fileName); - } - } - closedir(pDir); - return; -} - -static void ParseOtherCfgs() -{ - ReadCfgs("/system/etc/init"); - return; -} - -void InitReadCfg() -{ -#ifndef OHOS_LITE - InitParamService(); - LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); - LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL); - LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD); -#endif - ParseInitCfg(INIT_CONFIGURATION_FILE); - ParseOtherCfgs(); - INIT_LOGI("Parse init config file done."); -#ifdef OHOS_SERVICE_DUMP - DumpAllServices(); -#endif - -#ifdef OHOS_LITE - // do jobs - DoJob("pre-init"); -#ifndef __LINUX__ - TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1); -#endif - - DoJob("init"); -#ifndef __LINUX__ - TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2); -#endif - - DoJob("post-init"); -#ifndef __LINUX__ - TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3); - - InitStageFinished(); -#endif - ReleaseAllJobs(); -#else - PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); - - PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init")); - - PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init")); -#endif -} - diff --git a/services/src/init_service_manager.c b/services/src/init_service_manager.c deleted file mode 100644 index 06fca3db6a86cf85daeb71e60ff47604c5d60f4e..0000000000000000000000000000000000000000 --- a/services/src/init_service_manager.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright (c) 2020 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_service_manager.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cJSON.h" -#include "init_adapter.h" -#include "init_jobs.h" -#include "init_log.h" -#include "init_perms.h" -#include "init_read_cfg.h" -#include "init_capability.h" -#include "init_service_socket.h" -#include "init_utils.h" -#include "securec.h" - -#define MIN_IMPORTANT_LEVEL (-20) -#define MAX_IMPORTANT_LEVEL 19 - -// All serivce processes that init will fork+exec. -static Service* g_services = NULL; -static int g_servicesCnt = 0; - -#ifdef OHOS_SERVICE_DUMP -void DumpAllServices(void) -{ - if (g_services == NULL) { - return; - } - INIT_LOGD("Ready to dump all services:"); - INIT_LOGD("total service number: %d", g_servicesCnt); - for (int i = 0; i < g_servicesCnt; i++) { - INIT_LOGD("\tservice name: [%s]", g_services[i].name); - INIT_LOGD("\tpath :"); - for (int j = 0; j < g_services[i].pathArgsCnt; j++) { - if (g_services[i].pathArgs[j] != NULL) { - INIT_LOGD(" %s", g_services[i].pathArgs[j]); - } - } - } - INIT_LOGD("Dump all services finished"); -} -#endif - -void RegisterServices(Service* services, int servicesCnt) -{ - if (services == NULL) { - return; - } - g_services = services; - g_servicesCnt += servicesCnt; -} - -static void ReleaseServiceMem(Service* curServ) -{ - if (curServ == NULL) { - return; - } - if (curServ->pathArgs != NULL) { - for (int i = 0; i < curServ->pathArgsCnt; ++i) { - if (curServ->pathArgs[i] != NULL) { - free(curServ->pathArgs[i]); - curServ->pathArgs[i] = NULL; - } - } - free(curServ->pathArgs); - curServ->pathArgs = NULL; - } - curServ->pathArgsCnt = 0; - - if (curServ->servPerm.caps != NULL) { - free(curServ->servPerm.caps); - curServ->servPerm.caps = NULL; - } - curServ->servPerm.capsCnt = 0; - for (int i = 0; i < MAX_WRITEPID_FILES; i++) { - if (curServ->writepidFiles[i] != NULL) { - free(curServ->writepidFiles[i]); - curServ->writepidFiles[i] = NULL; - } - } - - if (curServ->servPerm.gIDArray != NULL) { - free(curServ->servPerm.gIDArray); - curServ->servPerm.gIDArray = NULL; - } - curServ->servPerm.gIDCnt = 0; -} - -static int GetServiceName(const cJSON* curArrItem, Service* curServ) -{ - char* fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(curArrItem, "name")); - if (fieldStr == NULL) { - INIT_LOGE("GetServiceName cJSON_GetStringValue error"); - return SERVICE_FAILURE; - } - - size_t strLen = strlen(fieldStr); - if (strLen == 0 || strLen > MAX_SERVICE_NAME) { - INIT_LOGE("GetServiceName strLen = %d, error", strLen); - return SERVICE_FAILURE; - } - - if (memcpy_s(curServ->name, MAX_SERVICE_NAME, fieldStr, strLen) != EOK) { - INIT_LOGE("GetServiceName memcpy_s error"); - return SERVICE_FAILURE; - } - curServ->name[strLen] = '\0'; - return SERVICE_SUCCESS; -} - -#ifdef OHOS_LITE -static int IsForbidden(const char* fieldStr) -{ - size_t fieldLen = strlen(fieldStr); - size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED); - if (fieldLen == forbidStrLen) { - if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) { - return 1; - } - return 0; - } else if (fieldLen > forbidStrLen) { - // "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid - if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) { - if (fieldStr[forbidStrLen] == ' ') { - return 1; - } - } - return 0; - } else { - return 0; - } -} -#else -static int IsForbidden(const char* fieldStr) -{ - return 0; -} -#endif - -static cJSON* GetArrItem(const cJSON* fileRoot, int* arrSize, const char* arrName) -{ - cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName); - if (!cJSON_IsArray(arrItem)) { - return NULL; - } - - *arrSize = cJSON_GetArraySize(arrItem); - if (*arrSize <= 0) { - return NULL; - } - return arrItem; -} - -static int GetWritepidStrings(const cJSON *curArrItem, Service *curServ) // writepid -{ - int writepidCnt = 0; - cJSON *filedJ = GetArrItem(curArrItem, &writepidCnt, "writepid"); - if ((writepidCnt <= 0) || (filedJ == NULL)) { // not item is ok. - return SERVICE_SUCCESS; - } - - if (writepidCnt > MAX_WRITEPID_FILES) { - INIT_LOGE("GetWritepidStrings, too many writepid[cnt %d] for one service, should not exceed %d.", - writepidCnt, MAX_WRITEPID_FILES); - return SERVICE_FAILURE; - } - - for (int i = 0; i < writepidCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - return SERVICE_FAILURE; - } - char *fieldStr = cJSON_GetStringValue(item); - if ((fieldStr == NULL) || (fieldStr[0] == '\0')) { - return SERVICE_FAILURE; - } - size_t strLen = strlen(fieldStr); - curServ->writepidFiles[i] = (char *)malloc(sizeof(char) * strLen + 1); - if (curServ->writepidFiles[i] == NULL) { - INIT_LOGE("GetWritepidStrings, malloc item[%d] error.", i); - return SERVICE_FAILURE; - } - if (memcpy_s(curServ->writepidFiles[i], strLen + 1, fieldStr, strLen) != EOK) { - INIT_LOGE("GetWritepidStrings, memcpy_s error."); - return SERVICE_FAILURE; - } - curServ->writepidFiles[i][strLen] = '\0'; - } - - return SERVICE_SUCCESS; -} - -static int GetGidOneItem(const cJSON *curArrItem, Service *curServ) // gid one item -{ - cJSON *filedJ = cJSON_GetObjectItem(curArrItem, GID_STR_IN_CFG); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // not found - } - curServ->servPerm.gIDCnt = 1; - curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t)); - if (curServ->servPerm.gIDArray == NULL) { - INIT_LOGE("GetGidOneItem, can't malloc, error."); - return SERVICE_FAILURE; - } - - if (cJSON_IsString(filedJ)) { - char *fieldStr = cJSON_GetStringValue(filedJ); - if (fieldStr == NULL) { - return SERVICE_FAILURE; - } - gid_t gID = DecodeUid(fieldStr); - if (gID == (gid_t)(-1)) { - INIT_LOGE("GetGidOneItem, DecodeUid %s error.", fieldStr); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[0] = gID; - return SERVICE_SUCCESS; - } - - if (cJSON_IsNumber(filedJ)) { - gid_t gID = (int)cJSON_GetNumberValue(filedJ); - if (gID < 0) { - INIT_LOGE("GetGidOneItem, gID = %d error.", gID); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[0] = gID; - return SERVICE_SUCCESS; - } - - INIT_LOGE("GetGidOneItem, this gid is neither a string nor a number, error."); - return SERVICE_FAILURE; -} - -static int GetGidArray(const cJSON *curArrItem, Service *curServ) // gid array -{ - int gIDCnt = 0; - cJSON *filedJ = GetArrItem(curArrItem, &gIDCnt, GID_STR_IN_CFG); // "gid" must have 1 item. - if ((gIDCnt <= 0) || (filedJ == NULL)) { // not a array, but maybe a item? - return GetGidOneItem(curArrItem, curServ); - } - if (gIDCnt > NGROUPS_MAX + 1) { - INIT_LOGE("GetGidArray, too many gids[cnt %d] for one service, should not exceed %d.", - gIDCnt, NGROUPS_MAX + 1); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gIDCnt); - if (curServ->servPerm.gIDArray == NULL) { - INIT_LOGE("GetGidArray malloc error"); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDCnt = gIDCnt; - int i = 0; - for (; i < gIDCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - break; - } - char *fieldStr = cJSON_GetStringValue(item); - if ((fieldStr == NULL) || (fieldStr[0] == '\0')) { - break; - } - gid_t gID = DecodeUid(fieldStr); - if ((gID) == (gid_t)(-1)) { - INIT_LOGE("GetGidArray, DecodeUid item[%d] error.", i); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[i] = gID; - } - INIT_CHECK_RETURN_VALUE(i != gIDCnt, SERVICE_SUCCESS); - for (i = 0; i < gIDCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - break; - } - if (!cJSON_IsNumber(item)) { - break; - } - gid_t gID = (int)cJSON_GetNumberValue(item); - if (gID < 0) { - INIT_LOGE("GetGidArray gID = %d, error", gID); - break; - } - curServ->servPerm.gIDArray[i] = gID; - } - return (((i == gIDCnt) ? SERVICE_SUCCESS : SERVICE_FAILURE)); -} - -static int GetServicePathAndArgs(const cJSON *curArrItem, Service *curServ) -{ - cJSON* pathItem = cJSON_GetObjectItem(curArrItem, "path"); - if (!cJSON_IsArray(pathItem)) { - INIT_LOGE("Path item not found or not a array"); - return SERVICE_FAILURE; - } - - int arrSize = cJSON_GetArraySize(pathItem); - if (arrSize <= 0 || arrSize > MAX_PATH_ARGS_CNT) { // array size invalid - INIT_LOGE("Array size = %d is wrong", arrSize); - return SERVICE_FAILURE; - } - - curServ->pathArgs = (char **)malloc((arrSize + 1) * sizeof(char *)); - if (curServ->pathArgs == NULL) { - INIT_LOGE("Current path is null."); - return SERVICE_FAILURE; - } - for (int i = 0; i < arrSize + 1; ++i) { - curServ->pathArgs[i] = NULL; - } - curServ->pathArgsCnt = arrSize + 1; - - for (int i = 0; i < arrSize; ++i) { - char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathItem, i)); - if (curParam == NULL || strlen(curParam) > MAX_ONE_ARG_LEN) { - // resources will be released by function: ReleaseServiceMem - if (curParam == NULL) { - INIT_LOGE("Current param is null."); - } else { - INIT_LOGE("Length of current param is too long."); - } - return SERVICE_FAILURE; - } - - if (i == 0 && IsForbidden(curParam)) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("Service %s is forbidden.", curServ->name); - return SERVICE_FAILURE; - } - - size_t paramLen = strlen(curParam); - curServ->pathArgs[i] = (char*)malloc(paramLen + 1); - if (curServ->pathArgs[i] == NULL) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("Service %s path is null.", curServ->name); - return SERVICE_FAILURE; - } - - if (memcpy_s(curServ->pathArgs[i], paramLen + 1, curParam, paramLen) != EOK) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("memcpy_s failed."); - return SERVICE_FAILURE; - } - curServ->pathArgs[i][paramLen] = '\0'; - } - return SERVICE_SUCCESS; -} - -static int GetImportantValue(int value, Service *curServ) -{ -#ifdef OHOS_LITE - if (value != 0) { - curServ->attribute |= SERVICE_ATTR_IMPORTANT; - } -#else - if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 - curServ->importance = value; - } else { - INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value); - return SERVICE_FAILURE; - } -#endif - return SERVICE_SUCCESS; -} - -static int GetServiceNumber(const cJSON* curArrItem, Service* curServ, const char* targetField) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, targetField); - if (filedJ == NULL && (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0 - || strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0 - || strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0 - || strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0 - || strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0)) { - return SERVICE_SUCCESS; // not found "critical","disabled","once","importance","console" item is ok - } - - if (!cJSON_IsNumber(filedJ)) { - INIT_LOGE("%s is null or is not a number, service name is %s", targetField, curServ->name); - return SERVICE_FAILURE; - } - - int value = (int)cJSON_GetNumberValue(filedJ); - // importance value allow < 0 - if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) != 0) { - if (value < 0) { - INIT_LOGE("Service %s value = %d is wrong", curServ->name, value); - return SERVICE_FAILURE; - } - } - - if (strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0) { - if (value != 0) { - curServ->attribute |= SERVICE_ATTR_ONCE; - } - } else if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0) { - INIT_CHECK_RETURN_VALUE(GetImportantValue(value, curServ) == SERVICE_SUCCESS, SERVICE_FAILURE); - } else if (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0) { // set critical - curServ->attribute &= ~SERVICE_ATTR_CRITICAL; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_CRITICAL; - } - } else if (strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0) { // set disabled - curServ->attribute &= ~SERVICE_ATTR_DISABLED; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_DISABLED; - } - } else if (strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0) { // set console - curServ->attribute &= ~SERVICE_ATTR_CONSOLE; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_CONSOLE; - } - } else { - INIT_LOGE("Item = %s, not expected, error.service name is %s", targetField, curServ->name); - return SERVICE_FAILURE; - } - return SERVICE_SUCCESS; -} - -static int GetUidStringNumber(const cJSON *curArrItem, Service *curServ) -{ - cJSON *filedJ = cJSON_GetObjectItem(curArrItem, UID_STR_IN_CFG); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // uID not found, but ok. - } - - if (cJSON_IsString(filedJ)) { - char *fieldStr = cJSON_GetStringValue(filedJ); - if (fieldStr == NULL) { - return SERVICE_FAILURE; - } - uid_t uID = DecodeUid(fieldStr); - if (uID == (uid_t)-1) { - INIT_LOGE("Decode uid %s error.", fieldStr); - return SERVICE_FAILURE; - } - curServ->servPerm.uID = uID; - return SERVICE_SUCCESS; - } - - if (cJSON_IsNumber(filedJ)) { - int uID = (int)cJSON_GetNumberValue(filedJ); - if (uID < 0) { - INIT_LOGE("Uid = %d error.", uID); - return SERVICE_FAILURE; - } - curServ->servPerm.uID = uID; - return SERVICE_SUCCESS; - } - - INIT_LOGE("This uid is neither a string nor a number, error."); - return SERVICE_FAILURE; -} - -static int ParseServiceSocket(char **opt, const int optNum, struct ServiceSocket *sockopt) -{ - if (optNum != SOCK_OPT_NUMS) { - return -1; - } - if (opt[SERVICE_SOCK_TYPE] == NULL) { - return -1; - } - sockopt->type = - ((strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0) ? SOCK_STREAM : - ((strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0) ? SOCK_DGRAM : SOCK_SEQPACKET)); - - if (opt[SERVICE_SOCK_PERM] == NULL) { - return -1; - } - sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE); - if (opt[SERVICE_SOCK_UID] == NULL) { - return -1; - } - uid_t uid = DecodeUid(opt[SERVICE_SOCK_UID]); - if (uid == (uid_t)-1) { - return -1; - } - sockopt->uid = uid; - if (opt[SERVICE_SOCK_GID] == NULL) { - return -1; - } - gid_t gid = DecodeUid(opt[SERVICE_SOCK_GID]); - if (gid == (gid_t)-1) { - return -1; - } - sockopt->gid = gid; - if (opt[SERVICE_SOCK_SETOPT] == NULL) { - return -1; - } - sockopt->passcred = ((strncmp(opt[SERVICE_SOCK_SETOPT], "passcred", - strlen(opt[SERVICE_SOCK_SETOPT])) == 0) ? true : false); - if (opt[SERVICE_SOCK_NAME] == NULL) { - return -1; - } - sockopt->name = (char *)calloc(MAX_SOCK_NAME_LEN, sizeof(char)); - if (sockopt->name == NULL) { - return -1; - } - int ret = memcpy_s(sockopt->name, MAX_SOCK_NAME_LEN, opt[SERVICE_SOCK_NAME], MAX_SOCK_NAME_LEN - 1); - if (ret != 0) { - free(sockopt->name); - sockopt->name = NULL; - return -1; - } - sockopt->next = NULL; - sockopt->sockFd = -1; - return 0; -} - -static void FreeServiceSocket(struct ServiceSocket *sockopt) -{ - if (sockopt == NULL) { - return; - } - struct ServiceSocket *tmpSock = NULL; - while (sockopt) { - tmpSock = sockopt; - if (sockopt->name != NULL) { - free(sockopt->name); - sockopt->name = NULL; - } - sockopt = tmpSock->next; - free(tmpSock); - } - return; -} - -static int GetServiceSocket(const cJSON* curArrItem, Service* curServ) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "socket"); - if (!cJSON_IsArray(filedJ)) { - return SERVICE_FAILURE; - } - - int sockCnt = cJSON_GetArraySize(filedJ); - if (sockCnt <= 0) { - return SERVICE_FAILURE; - } - curServ->socketCfg = NULL; - for (int i = 0; i < sockCnt; ++i) { - cJSON *sockJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsString(sockJ) || !cJSON_GetStringValue(sockJ)) { - return SERVICE_FAILURE; - } - char *sockStr = cJSON_GetStringValue(sockJ); - char *tmpStr[SOCK_OPT_NUMS] = {NULL}; - int num = SplitString(sockStr, tmpStr, SOCK_OPT_NUMS); - if (num != SOCK_OPT_NUMS) { - return SERVICE_FAILURE; - } - struct ServiceSocket *socktmp = (struct ServiceSocket *)calloc(1, sizeof(struct ServiceSocket)); - if (socktmp == NULL) { - return SERVICE_FAILURE; - } - int ret = ParseServiceSocket(tmpStr, SOCK_OPT_NUMS, socktmp); - if (ret < 0) { - free(socktmp); - socktmp = NULL; - return SERVICE_FAILURE; - } - if (curServ->socketCfg == NULL) { - curServ->socketCfg = socktmp; - } else { - socktmp->next = curServ->socketCfg->next; - curServ->socketCfg->next = socktmp; - } - } - return SERVICE_SUCCESS; -} - -static int GetServiceOnRestart(const cJSON* curArrItem, Service* curServ) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "onrestart"); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // onrestart not found, but ok. - } - if (!cJSON_IsArray(filedJ)) { - return SERVICE_FAILURE; - } - int cmdCnt = cJSON_GetArraySize(filedJ); - if (cmdCnt <= 0) { - return SERVICE_FAILURE; - } - curServ->onRestart = (struct OnRestartCmd *)calloc(1, sizeof(struct OnRestartCmd)); - if (curServ->onRestart == NULL) { - return SERVICE_FAILURE; - } - curServ->onRestart->cmdLine = (CmdLine *)calloc(cmdCnt, sizeof(CmdLine)); - if (curServ->onRestart->cmdLine == NULL) { - free(curServ->onRestart); - curServ->onRestart = NULL; - return SERVICE_FAILURE; - } - curServ->onRestart->cmdNum = cmdCnt; - for (int i = 0; i < cmdCnt; ++i) { - cJSON* cmdJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsString(cmdJ) || !cJSON_GetStringValue(cmdJ)) { - free(curServ->onRestart->cmdLine); - curServ->onRestart->cmdLine = NULL; - free(curServ->onRestart); - curServ->onRestart = NULL; - return SERVICE_FAILURE; - } - char *cmdStr = cJSON_GetStringValue(cmdJ); - ParseCmdLine(cmdStr, &curServ->onRestart->cmdLine[i]); - } - return SERVICE_SUCCESS; -} - -static bool IsServiceInMainStrap(Service *curServ) -{ - char *mainServiceList[] = { - "appspawn", "udevd", "samgr", "multimodalinput", "weston", "installs", "hiview", "hilogd", "hdf_devmgr", - "distributedsche", "softbus_server", "foundation" - }; - unsigned int length = ARRAY_LENGTH(mainServiceList); - for (unsigned int i = 0; i < length; ++i) { - if (strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) == 0) { - INIT_LOGI("%s must be main service", curServ->name); - return true; - } - } - return false; -} - -static int GetDynamicService(const cJSON *curArrItem, Service *curServ) -{ - cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic"); - if (item == NULL) { - return SERVICE_SUCCESS; - } - - INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE, - "Service : %s dynamic value only support bool.", curServ->name); - bool isDynamic = (bool)cJSON_GetNumberValue(item); - if (!isDynamic) { - INIT_LOGI("Service : %s dynamic value is false, it will be started with init.", curServ->name); - return SERVICE_SUCCESS; - } - - if (IsServiceInMainStrap(curServ)) { - return SERVICE_SUCCESS; - } - INIT_LOGI("%s is dynamic service", curServ->name); - curServ->attribute |= SERVICE_ATTR_DYNAMIC; - curServ->attribute |= SERVICE_ATTR_ONCE; - return SERVICE_SUCCESS; -} - -static int CheckServiceKeyName(const cJSON* curService) -{ - char *cfgServiceKeyList[] = { - "name", "path", "uid", "gid", "once", "importance", "caps", "disabled", - "writepid", "critical", "socket", "console", "dynamic" - }; - if (curService == NULL) { - return SERVICE_FAILURE; - } - cJSON *child = curService->child; - if (child == NULL) { - return SERVICE_FAILURE; - } - while (child != NULL) { - int i = 0; - int keyListSize = ARRAY_LENGTH(cfgServiceKeyList); - for (; i < keyListSize; i++) { - if (strcmp(child->string, cfgServiceKeyList[i]) == 0) { - break; - } - } - if (i < keyListSize) { - child = child->next; - } else { - INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string); - return SERVICE_FAILURE; - } - } - return SERVICE_SUCCESS; -} - -static int ParseOneService(const cJSON *curItem, Service *service) -{ - if (curItem == NULL || service == NULL) { - return SERVICE_FAILURE; - } - int ret = GetServiceName(curItem, service); - ret |= GetServicePathAndArgs(curItem, service); - ret |= GetUidStringNumber(curItem, service); - ret |= GetGidArray(curItem, service); - ret |= GetServiceNumber(curItem, service, ONCE_STR_IN_CFG); - ret |= GetServiceNumber(curItem, service, IMPORTANT_STR_IN_CFG); - ret |= GetServiceNumber(curItem, service, CRITICAL_STR_IN_CFG); - ret |= GetServiceNumber(curItem, service, DISABLED_STR_IN_CFG); - ret |= GetServiceNumber(curItem, service, CONSOLE_STR_IN_CFG); - ret |= GetWritepidStrings(curItem, service); - ret |= GetServiceCaps(curItem, service); - ret |= GetDynamicService(curItem, service); - return ret; -} - -void ParseAllServices(const cJSON* fileRoot) -{ - int servArrSize = 0; - cJSON* serviceArr = GetArrItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON); - INIT_INFO_CHECK(serviceArr != NULL, return, "This config does not contain service array."); - - 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); - INIT_CHECK_ONLY_RETURN((g_servicesCnt + servArrSize) > 0); - - Service* retServices = (Service*)realloc(g_services, sizeof(Service) * (g_servicesCnt + servArrSize)); - INIT_ERROR_CHECK(retServices != NULL, return, - "Realloc for %s arr failed! %d.", SERVICES_ARR_NAME_IN_JSON, servArrSize); - - // Skip already saved services, - Service* tmp = retServices + g_servicesCnt; - if (memset_s(tmp, sizeof(Service) * servArrSize, 0, sizeof(Service) * servArrSize) != EOK) { - free(retServices); - retServices = NULL; - return; - } - - for (int i = 0; i < servArrSize; ++i) { - cJSON* curItem = cJSON_GetArrayItem(serviceArr, i); - if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { - ReleaseServiceMem(&tmp[i]); - tmp[i].attribute |= SERVICE_ATTR_INVALID; - continue; - } - int ret = ParseOneService(curItem, &tmp[i]); - if (ret != SERVICE_SUCCESS) { - // release resources if it fails - ReleaseServiceMem(&tmp[i]); - tmp[i].attribute |= SERVICE_ATTR_INVALID; - INIT_LOGE("Parse information for service %s failed. ", tmp[i].name); - continue; - } else { - INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d", - i, tmp[i].name, tmp[i].servPerm.uID, (tmp[i].attribute & SERVICE_ATTR_CRITICAL) ? 1 : 0, - (tmp[i].attribute & SERVICE_ATTR_DISABLED) ? 1 : 0); - } - if (GetServiceSocket(curItem, &tmp[i]) != SERVICE_SUCCESS) { - if (tmp[i].socketCfg != NULL) { - FreeServiceSocket(tmp[i].socketCfg); - tmp[i].socketCfg = NULL; - } - } - (void)GetServiceOnRestart(curItem, &tmp[i]); - } - // Increase service counter. - RegisterServices(retServices, servArrSize); -} - -static int FindServiceByName(const char* servName) -{ - if ((servName == NULL) || (g_services == NULL)) { - return -1; - } - - for (int i = 0; i < g_servicesCnt; ++i) { - if (strlen(g_services[i].name) == strlen(servName) && - strncmp(g_services[i].name, servName, strlen(g_services[i].name)) == 0) { - return i; - } - } - return -1; -} - -void StartServiceByName(const char *servName, bool checkDynamic) -{ - // find service by name - int servIdx = FindServiceByName(servName); - if (servIdx < 0) { - INIT_LOGE("Cannot find service %s.", servName); - return; - } - if (checkDynamic && (g_services[servIdx].attribute & SERVICE_ATTR_DYNAMIC)) { - INIT_LOGI("%s is dynamic service.", servName); - return; - } - if (ServiceStart(&g_services[servIdx]) != SERVICE_SUCCESS) { - INIT_LOGE("Service %s start failed!", g_services[servIdx].name); - } - return; -} - -void StopServiceByName(const char* servName) -{ - // find service by name - int servIdx = FindServiceByName(servName); - if (servIdx < 0) { - INIT_LOGE("Cannot find service %s.", servName); - return; - } - - if (ServiceStop(&g_services[servIdx]) != SERVICE_SUCCESS) { - INIT_LOGE("Service %s start failed!", g_services[servIdx].name); - } - - return; -} - -void StopAllServices(void) -{ - if (g_services == NULL) { - return; - } - for (int i = 0; i < g_servicesCnt; i++) { - if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) { - INIT_LOGE("Service %s stop failed!", g_services[i].name); - } - } -} - -void StopAllServicesBeforeReboot(void) -{ - if (g_services == NULL) { - return; - } - - for (int i = 0; i < g_servicesCnt; i++) { - g_services[i].attribute |= SERVICE_ATTR_INVALID; - if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) { - INIT_LOGE("Service %s stop failed!", g_services[i].name); - } - } -} - -void ReapServiceByPID(int pid) -{ - if (g_services == NULL) { - return; - } - - for (int i = 0; i < g_servicesCnt; i++) { - if (g_services[i].pid == pid) { -#ifdef OHOS_LITE - if (g_services[i].attribute & SERVICE_ATTR_IMPORTANT) { - // important process exit, need to reboot system - g_services[i].pid = -1; - StopAllServices(); - RebootSystem(); - } -#endif - ServiceReap(&g_services[i]); - break; - } - } -} - diff --git a/services/src/main.c b/services/src/main.c deleted file mode 100644 index 40a6de2798a684221d6ab935f1efe0a0cd5d9c92..0000000000000000000000000000000000000000 --- a/services/src/main.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2020 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 -#include -#include -#include -#include - -#ifdef OHOS_DEBUG -#include -#endif // OHOS_DEBUG - -#include - -#include "init_adapter.h" -#include "init_log.h" -#include "init_read_cfg.h" -#include "init_signal_handler.h" -#ifdef OHOS_LITE -#include "parameter.h" -#endif - -#ifndef OHOS_LITE -#include "device.h" -#include "init_param.h" -#endif - -static const pid_t INIT_PROCESS_PID = 1; - -static void PrintSysInfo() -{ -#ifdef OHOS_LITE - const char* sysInfo = GetVersionId(); - if (sysInfo != NULL) { - INIT_LOGE("%s", sysInfo); - return; - } - INIT_LOGE("main, GetVersionId failed!"); -#endif -} - -#ifdef OHOS_DEBUG -static long TimeDiffMs(const struct timespec* tmBefore, const struct timespec* tmAfter) -{ - if (tmBefore != NULL && tmAfter != NULL) { - long timeUsed = (tmAfter->tv_sec - tmBefore->tv_sec) * 1000 + // 1 s = 1000 ms - (tmAfter->tv_nsec - tmBefore->tv_nsec) / 1000000L; // 1 ms = 1000000 ns - return timeUsed; - } - return -1; -} -#endif // OHOS_DEBUG - -int main(int argc, char **argv) -{ -#ifndef OHOS_LITE - if (setenv("UV_THREADPOOL_SIZE", "1", 1) != 0) { - INIT_LOGE("set UV_THREADPOOL_SIZE error : %d.", errno); - } - CloseStdio(); - OpenLogDevice(); -#endif - -#ifdef OHOS_DEBUG - struct timespec tmEnter; - if (clock_gettime(CLOCK_REALTIME, &tmEnter) != 0) { - INIT_LOGE("main, enter, get time failed! err %d.\n", errno); - } -#endif // OHOS_DEBUG - - if (getpid() != INIT_PROCESS_PID) { - INIT_LOGE("main, current process id is %d not %d, failed!", getpid(), INIT_PROCESS_PID); - return 0; - } - PrintSysInfo(); - -#ifndef OHOS_LITE - MountBasicFs(); - CreateDeviceNode(); - EnableDevKmsg(); - MakeSocketDir("/dev/unix/socket/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); -#endif - - SignalInitModule(); - -#ifdef OHOS_DEBUG - struct timespec tmSysInfo; - if (clock_gettime(CLOCK_REALTIME, &tmSysInfo) != 0) { - INIT_LOGE("main, after sysinfo, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - - ExecuteRcs(); - -#ifdef OHOS_DEBUG - struct timespec tmRcs; - if (clock_gettime(CLOCK_REALTIME, &tmRcs) != 0) { - INIT_LOGE("main, after rcs, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - InitReadCfg(); -#ifdef OHOS_DEBUG - struct timespec tmCfg; - if (clock_gettime(CLOCK_REALTIME, &tmCfg) != 0) { - INIT_LOGE("main, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - -#ifdef OHOS_DEBUG - INIT_LOGI("main, time used: sigInfo %ld ms, rcs %ld ms, cfg %ld ms.", \ - TimeDiffMs(&tmEnter, &tmSysInfo), TimeDiffMs(&tmSysInfo, &tmRcs), TimeDiffMs(&tmRcs, &tmCfg)); -#endif - - INIT_LOGI("main, entering wait."); -#ifndef OHOS_LITE - StartParamService(); -#endif - while (1) { - (void)pause(); - } - return 0; -} diff --git a/services/utils/BUILD.gn b/services/utils/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..b1d70f99058d0c62616ce51834e0c31ff6794886 --- /dev/null +++ b/services/utils/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_static_library("libinit_utils") { + sources = [ "init_utils.c" ] + + include_dirs = [ + "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/services/log", + "//base/startup/init_lite/services/include", + ] + + deps = [ + "//base/startup/init_lite/services/log:init_log", + "//third_party/bounds_checking_function:libsec_static", + ] + part_name = "init" +} diff --git a/services/src/init_utils.c b/services/utils/init_utils.c old mode 100644 new mode 100755 similarity index 53% rename from services/src/init_utils.c rename to services/utils/init_utils.c index 58c2262498f8b4e81e207a6d17a730f0562f58e4..bcf4359d9f20e75166f114e6d2cb789c65320660 --- a/services/src/init_utils.c +++ b/services/utils/init_utils.c @@ -13,9 +13,12 @@ * limitations under the License. */ #include "init_utils.h" + #include #include +#include #include +#include #include #include #include @@ -26,7 +29,6 @@ #include #include "init_log.h" -#include "init_utils.h" #include "securec.h" #define WAIT_MAX_COUNT 10 @@ -38,6 +40,11 @@ #endif #define MAX_JSON_FILE_LEN 102400 // max init.cfg size 100KB +#define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0) +#ifndef DT_DIR +#define DT_DIR 4 +#endif + #define THOUSAND_UNIT_INT 1000 #define THOUSAND_UNIT_FLOAT 1000.0 @@ -74,10 +81,10 @@ uid_t DecodeUid(const char *name) } } -char* ReadFileToBuf(const char *configFile) +char *ReadFileToBuf(const char *configFile) { - char* buffer = NULL; - FILE* fd = NULL; + char *buffer = NULL; + FILE *fd = NULL; struct stat fileStat = {0}; if (configFile == NULL || *configFile == '\0') { return NULL; @@ -109,7 +116,7 @@ char* ReadFileToBuf(const char *configFile) } while (0); if (fd != NULL) { - fclose(fd); + (void)fclose(fd); fd = NULL; } return buffer; @@ -133,9 +140,10 @@ int SplitString(char *srcPtr, char **dstPtr, int maxNum) void WaitForFile(const char *source, unsigned int maxCount) { - if (maxCount > WAIT_MAX_COUNT) { + unsigned int maxCountTmp = maxCount; + if (maxCountTmp > WAIT_MAX_COUNT) { INIT_LOGE("WaitForFile max time is 5s"); - maxCount = WAIT_MAX_COUNT; + maxCountTmp = WAIT_MAX_COUNT; } struct stat sourceInfo; const unsigned int waitTime = 500000; @@ -143,10 +151,10 @@ void WaitForFile(const char *source, unsigned int maxCount) do { usleep(waitTime); count++; - } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < maxCount)); + } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < maxCountTmp)); float secTime = ConvertMicrosecondToSecond(waitTime); - if (count == maxCount) { - INIT_LOGE("wait for file:%s failed after %f.", source, maxCount * secTime); + if (count == maxCountTmp) { + INIT_LOGE("wait for file:%s failed after %f.", source, maxCountTmp * secTime); } return; } @@ -173,4 +181,116 @@ size_t WriteAll(int fd, char *buffer, size_t size) left -= written; } return size - left; -} \ No newline at end of file +} + +char *Realpath(const char *source, char *resolvedPath, size_t resolvedPathSize) +{ + if ((source == NULL) || (resolvedPath == NULL) || (resolvedPathSize != PATH_MAX)) { + return NULL; + } + if (realpath(source, resolvedPath) == NULL) { + if (errno != ENOENT) { + INIT_LOGE("Fail resolve %s real path err=%d", source, errno); + return NULL; + } + } + return resolvedPath; +} + +int MakeDir(const char *dir, mode_t mode) +{ + int rc = -1; + if (dir == NULL || *dir == '\0') { + errno = EINVAL; + return rc; + } + rc = mkdir(dir, mode); + if (rc < 0 && errno != EEXIST) { + INIT_LOGE("Create directory \" %s \" failed, err = %d", dir, errno); + return rc; + } + // create dir success or it already exist. + return 0; +} + +int MakeDirRecursive(const char *dir, mode_t mode) +{ + int rc = -1; + char buffer[PATH_MAX] = {}; + const char *p = NULL; + if (dir == NULL || *dir == '\0') { + errno = EINVAL; + return rc; + } + p = dir; + char *slash = strchr(dir, '/'); + while (slash != NULL) { + int gap = slash - p; + p = slash + 1; + if (gap == 0) { + slash = strchr(p, '/'); + continue; + } + if (gap < 0) { // end with '/' + break; + } + if (memcpy_s(buffer, PATH_MAX, dir, p - dir - 1) != 0) { + return -1; + } + rc = MakeDir(buffer, mode); + if (rc < 0) { + return rc; + } + slash = strchr(p, '/'); + } + return MakeDir(dir, mode); +} + +int StringToInt(const char *str, int defaultValue) +{ + if (str == NULL || *str == '\0') { + return defaultValue; + } + errno = 0; + int value = (int)strtoul(str, NULL, DECIMAL_BASE); + return errno != 0 ? defaultValue : value; +} + +int ReadFileInDir(const char *dirPath, const char *includeExt, + int (*processFile)(const char *fileName, void *context), void *context) +{ + DIR *pDir = opendir(dirPath); + INIT_ERROR_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno); + char *fileName = malloc(MAX_BUF_SIZE); + INIT_ERROR_CHECK(fileName != NULL, closedir(pDir); + return -1, "Failed to malloc for %s", dirPath); + + struct dirent *dp; + while ((dp = readdir(pDir)) != NULL) { + if (dp->d_type == DT_DIR) { + continue; + } + INIT_LOGD("ReadFileInDir %s", dp->d_name); + if (includeExt != NULL) { + char *tmp = strstr(dp->d_name, includeExt); + if (tmp == NULL) { + continue; + } + if (strcmp(tmp, includeExt) != 0) { + continue; + } + } + int ret = snprintf_s(fileName, MAX_BUF_SIZE, MAX_BUF_SIZE - 1, "%s/%s", dirPath, dp->d_name); + if (ret <= 0) { + INIT_LOGE("Failed to get file name for %s", dp->d_name); + continue; + } + struct stat st; + if (stat(fileName, &st) == 0) { + processFile(fileName, context); + } + } + free(fileName); + closedir(pDir); + return 0; +} diff --git a/services/src/list.c b/services/utils/list.c similarity index 100% rename from services/src/list.c rename to services/utils/list.c diff --git a/ueventd/BUILD.gn b/ueventd/BUILD.gn index 719441da6eec4437201dd07f028e360fcec658f2..eb3e89cbd02ac2747e41c517df02db5d212f5d53 100755 --- a/ueventd/BUILD.gn +++ b/ueventd/BUILD.gn @@ -16,7 +16,7 @@ if (!defined(ohos_lite)) { ohos_executable("ueventd") { sources = [ - "//base/startup/init_lite/services/src/list.c", + "//base/startup/init_lite/services/utils/list.c", "//base/startup/init_lite/ueventd/ueventd.c", "//base/startup/init_lite/ueventd/ueventd_device_handler.c", "//base/startup/init_lite/ueventd/ueventd_firmware_handler.c",