diff --git a/services/include/init_cmds.h b/services/include/init_cmds.h index 232f24a3d3a515cca0eb3217a1b7bcfffada763e..86644e5d3352f8e1c86a067f4703b66ec5ed3f03 100644 --- a/services/include/init_cmds.h +++ b/services/include/init_cmds.h @@ -39,24 +39,8 @@ extern "C" { #define MAX_PARAM_NAME_LEN 0 #endif -// one cmd line -typedef struct { - char name[MAX_CMD_NAME_LEN + 1]; - char cmdContent[MAX_CMD_CONTENT_LEN + 1]; -} CmdLine; - -struct CmdArgs { - int argc; - char **argv; -}; - 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); - +void DoCmdLine(const char *cmdStr); void DoCmdByName(const char *name, const char *cmdContent); const char *GetMatchCmd(const char *cmdStr); #ifdef __cplusplus diff --git a/services/include/init_jobs.h b/services/include/init_jobs.h index 7c7ffaed5cd53b53715f2317d128f7a9594f1e48..5a96e42db2cfcca1ff61ee62a4272dece2b55e26 100644 --- a/services/include/init_jobs.h +++ b/services/include/init_jobs.h @@ -31,7 +31,7 @@ extern "C" { typedef struct { char name[MAX_JOB_NAME_LEN + 1]; int cmdLinesCnt; - CmdLine* cmdLines; + char **cmdLines; } Job; void ParseAllJobs(const cJSON* fileRoot); diff --git a/services/include/init_service.h b/services/include/init_service.h index fd269c23887f201e354d8eafd671c7ea27068b7b..d89035f336c3cb3b2fe9dc86aff31defd43da20f 100644 --- a/services/include/init_service.h +++ b/services/include/init_service.h @@ -56,7 +56,7 @@ typedef struct { } Perms; struct OnRestartCmd { - CmdLine *cmdLine; + char **cmdLine; int cmdNum; }; diff --git a/services/src/init_cmds.c b/services/src/init_cmds.c index d929e7976765fa8b75222158416957ae8b6a3eba..004b0b658e46fb4e1c6f4f20478a1b46d2135b64 100644 --- a/services/src/init_cmds.c +++ b/services/src/init_cmds.c @@ -44,18 +44,15 @@ #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 +struct CmdArgs { + int argc; + char **argv; +}; + static const char *g_supportCfg[] = { "/etc/patch.cfg", "/patch/fstab.cfg", @@ -122,178 +119,344 @@ inline int GetParamValue(const char *symValue, char *paramValue, unsigned int pa } #endif -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); +struct simple_buffer { + void *data; + size_t top; + size_t capacity; +}; - 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; +static inline void simple_buffer_require(struct simple_buffer *sb, size_t size) { + size_t least = sb->top + size; + if (least < size) { + do { + size *= 2; + } while (least < size); + sb->data = realloc(sb->data, size); + sb->capacity = size; + } +} + +static inline void simple_buffer_putchar(struct simple_buffer *sb, char c) { + simple_buffer_require(sb, 1); + ((char*)sb->data)[sb->top++] = c; +} + +static inline void simple_buffer_putstr(struct simple_buffer *sb, const char *str) { + size_t len = strlen(str); + simple_buffer_require(sb, len); + memcpy((char*)sb->data + sb->top, str, len); + sb->top += len; +} + +static inline void simple_buffer_init(struct simple_buffer *sb, size_t initial_size) { + sb->data = malloc(initial_size); + sb->capacity = initial_size; + sb->top = 0; +} + +static char* ParseCommandInternal(const char *command, int *argc_p) +{ + const char *variable, *input = command; + struct simple_buffer output; + int argc = 0; + enum { + S_SEARCH_NEXT, + S_COPY_STRING, + S_SINGLE_QUOTE, + S_DOUBLE_QUOTE, + S_BACK_SLASH, + S_DOLLAR, + S_SEARCH_BACK_BRACE, + } state = S_SEARCH_NEXT, state_bak; + + simple_buffer_init(&output, strlen(command) + 1); + for (; *input; ++input) { + char c = *input; + + switch_entry: + switch (state) { + case S_SEARCH_NEXT: + if (isspace(c)) { + break; + } + if (c == '#') { + // to support comment + goto out; + } + state = S_COPY_STRING; + argc++; + goto switch_entry; // do not consume input char + case S_COPY_STRING: + if (isspace(c)) { + simple_buffer_putchar(&output, '\0'); + state = S_SEARCH_NEXT; + break; + } + switch (c) { + case '\'': + state = S_SINGLE_QUOTE; + break; + case '\"': + state = S_DOUBLE_QUOTE; + break; + case '\\': + state_bak = state; + state = S_BACK_SLASH; + break; + case '$': + state_bak = state; + state = S_DOLLAR; + break; + default: + simple_buffer_putchar(&output, c); + } + break; + case S_SINGLE_QUOTE: + if (c == '\'') { + state = S_COPY_STRING; + break; + } + simple_buffer_putchar(&output, c); + break; + case S_DOUBLE_QUOTE: + switch (c) { + case '\"': + state = S_COPY_STRING; + break; + case '\\': + state_bak = state; + state = S_BACK_SLASH; + break; + case '$': + state_bak = state; + state = S_DOLLAR; + break; + default: + simple_buffer_putchar(&output, c); + } + break; + case S_BACK_SLASH: + if (strchr("\\\"`|", c) == NULL) { + simple_buffer_putchar(&output, '\\'); + } + simple_buffer_putchar(&output, c); + state = state_bak; + break; + case S_DOLLAR: + if (c != '{') { + INIT_LOGE("syntax error: missing '{'"); + argc = -1; + goto out; + } + state = S_SEARCH_BACK_BRACE; + variable = input + 1; + break; + case S_SEARCH_BACK_BRACE: + if (c == '}') { + char key[MAX_PARAM_NAME_LEN], value[MAX_PARAM_VALUE_LEN]; + unsigned int len = input - variable; + if (len == 0) { + INIT_LOGE("syntax error: variable is empty"); + argc = -1; + goto out; + } else if (len >= MAX_PARAM_VALUE_LEN) { + INIT_LOGE("parsing error: variable name too long: %u", len); + argc = -1; + goto out; + } + memcpy(key, variable, len); + key[len] = '\0'; + len = MAX_PARAM_VALUE_LEN; + if (SystemReadParam(key, value, &len) != 0) { + INIT_LOGE("parsing error: cannot found this variable: %s", key); + argc = -1; + goto out; + } + simple_buffer_putstr(&output, value); + state = state_bak; + break; + } + // variable name only allow [0-9a-zA-Z_\.] + if (!isdigit(c) && !isalpha(c) && c != '_' && c != '.') { + INIT_LOGE("parsing error: unexpected character: %c", c); + argc = -1; + goto out; + } + break; + } } - ctx->argv = (char**)malloc(sizeof(char*) * (size_t)argsCount + 1); - INIT_CHECK(ctx->argv != NULL, FreeCmd(&ctx); return NULL); - - char tmpCmd[MAX_BUFFER]; - size_t cmdLength = strlen(cmdContent); - if (cmdLength > MAX_BUFFER - 1) { - INIT_LOGE("command line is too larget, should not bigger than %d. ignore...\n", MAX_BUFFER); - FreeCmd(&ctx); - return NULL; + + if (state != S_SEARCH_NEXT && state != S_COPY_STRING) { + INIT_LOGE("parsing error: early null-terminator"); + argc = -1; + goto out; + } + if (state == S_COPY_STRING) { + simple_buffer_putchar(&output, '\0'); } - INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK, - FreeCmd(&ctx); - return NULL); - tmpCmd[strlen(cmdContent)] = '\0'; +out: + if (argc <= 0) { + free(output.data); + output.data = NULL; + } + *argc_p = argc; + return output.data; +} - char *p = tmpCmd; - char *token = NULL; - size_t allocSize = 0; +static struct CmdArgs* ParseCommand(const char *command) +{ + char *buffer, **argv; + int argc; + struct CmdArgs *cmd; - // Skip lead whitespaces - while (isspace(*p)) { - 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); - ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[ctx->argc], allocSize) == 0, - FreeCmd(&ctx); return NULL); - ctx->argc += 1; - ctx->argv[ctx->argc] = NULL; - return ctx; + buffer = ParseCommandInternal(command, &argc); + if (argc < 0) { + return NULL; } - int index = ctx->argc; - while (token != NULL) { - // Too more arguments, treat rest of data as one argument - if (index == (argsCount - 1)) { - break; - } - *token = '\0'; // replace it with '\0'; - allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1); - ctx->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(&ctx); return NULL); - p = token + 1; // skip '\0' - // Skip lead whitespaces - while (isspace(*p)) { - p++; + // C11 5.1.2.2.1: argv[argc] shall be a null pointer + argv = malloc((argc+1) * sizeof(char*)); + argv[argc] = NULL; + + if (argc) { + argv[0] = buffer; + for (int i = 1; i < argc; ++i) { + buffer += strlen(buffer) + 1; + argv[i] = buffer; } - index++; - token = strstr(p, delim); } - ctx->argc = index; - 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->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(&ctx); return NULL); - ctx->argc = index + 1; - } + cmd = malloc(sizeof(struct CmdArgs)); + cmd->argc = argc; + cmd->argv = argv; + return cmd; +} - ctx->argv[ctx->argc] = NULL; - return ctx; +static void FreeCmd(struct CmdArgs *cmd) +{ + if (cmd) { + free(cmd->argv[0]); + free(cmd->argv); + free(cmd); + } } -void FreeCmd(struct CmdArgs **cmd) +static char* ArgvToString(int argc, char * const *argv) { - struct CmdArgs *tmpCmd = *cmd; - INIT_CHECK_ONLY_RETURN(tmpCmd != NULL); - for (int i = 0; i < tmpCmd->argc; ++i) { - INIT_CHECK(tmpCmd->argv[i] == NULL, free(tmpCmd->argv[i])); + // draft version + // do not support add quote mark when space in string + // do not support escape for special character + char *buffer, *p; + size_t len = 1; // include null-terminator + int i; + + for (i = 0; i < argc || (argc < 0 && argv[i]); ++i) { + len += strlen(argv[i]); + len += i > 0; // space size } - INIT_CHECK(tmpCmd->argv == NULL, free(tmpCmd->argv)); - free(tmpCmd); - return; + + p = buffer = malloc(len); + while (i--) { + const char *arg = *argv++; + if (p != buffer) { + *p++ = ' '; + } + len = strlen(arg); + memcpy(p, arg, len); + p += len; + } + *p = '\0'; + return buffer; } -#define EXTRACT_ARGS(cmdname, cmdContent, args) \ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", args); \ - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != args)) { \ - INIT_LOGE("Command \"%s\" with invalid arguments: %s", #cmdname, cmdContent); \ - goto out; \ +#define AssertArgcEqualTo(argc, expected) do { \ + int argc_ = (argc); \ + int ex_ = (expected); \ + if ((argc_) != (ex_)) { \ + INIT_LOGE("%s: invalid argc %d, expected %d", __func__, (argc_), (ex_)); \ + return ; \ + } \ +} while(0) + +#define AssertArgcNotEqual(argc, expected) do { \ + int argc_ = (argc); \ + int ex_ = (expected); \ + if ((argc_) == (ex_)) { \ + INIT_LOGE("%s: invalid argc %d, cannot be %d", __func__, (argc_), (ex_)); \ + return ; \ } \ +} while(0) + +#define AssertArgcGreaterEqual(argc, expected) do { \ + int argc_ = (argc); \ + int ex_ = (expected); \ + if ((argc_) < (ex_)) { \ + INIT_LOGE("%s: invalid argc %d, expected not less than %d", __func__, (argc_), (ex_)); \ + return ; \ + } \ +} while(0) + +#define AssertArgcLessEqual(argc, expected) do { \ + int argc_ = (argc); \ + int ex_ = (expected); \ + if ((argc_) > (ex_)) { \ + INIT_LOGE("%s: invalid argc %d, expected not greater than %d", __func__, (argc_), (ex_)); \ + return ; \ + } \ +} while(0) -static void DoSetDomainname(const char *cmdContent, int maxArg) +static void WriteCommon(const char *caller, const char *path, const char *value, int oflags, mode_t mode) { - EXTRACT_ARGS(domainname, cmdContent, maxArg) - int fd = open("/proc/sys/kernel/domainname", O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); + int fd = open(path, oflags, mode); if (fd < 0) { - INIT_LOGE("DoSetDomainame failed to open \"/proc/sys/kernel/domainname\". err = %d", errno); - goto out; + INIT_LOGE("%s: failed to open %s. err = %d", caller, path, errno); + return; } - size_t size = strlen(ctx->argv[0]); - ssize_t n = write(fd, ctx->argv[0], size); + size_t size = strlen(value); + ssize_t n = write(fd, value, size); if (n != (ssize_t)size) { - INIT_LOGE("DoSetHostname failed to write %s to \"/proc/sys/kernel/domainname\". err = %d", errno); + INIT_LOGE("%s: failed to write %s to %s. err = %d", caller, value, path, errno); } - close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; } -static void DoSetHostname(const char *cmdContent, int maxArg) +static void DoSetDomainname(int argc, char *argv[]) { - EXTRACT_ARGS(hostname, cmdContent, maxArg) - int fd = open("/proc/sys/kernel/hostname", O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); - if (fd < 0) { - INIT_LOGE("DoSetHostname failed to open \"/proc/sys/kernel/hostname\". err = %d", errno); - goto out; - } - - size_t size = strlen(ctx->argv[0]); - ssize_t n = write(fd, ctx->argv[0], size); - if (n != (ssize_t)size) { - INIT_LOGE("DoSetHostname failed to write %s to \"/proc/sys/kernel/hostname\". err = %d", errno); - } + AssertArgcEqualTo(argc, 1); + WriteCommon(__func__, "/proc/sys/kernel/domainname", argv[0], + O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); +} - close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; +static void DoSetHostname(int argc, char *argv[]) +{ + AssertArgcEqualTo(argc, 1); + WriteCommon(__func__, "/proc/sys/kernel/hostname", argv[0], + O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); } #ifndef OHOS_LITE -static void DoIfup(const char *cmdContent, int maxArg) +static void DoIfup(int argc, char *argv[]) { - EXTRACT_ARGS(ifup, cmdContent, maxArg) + AssertArgcEqualTo(argc, 1); struct ifreq interface; - if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) { + if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, argv[0], strlen(argv[0])) != EOK) { INIT_LOGE("DoIfup failed to copy interface name"); - goto out; + 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); - goto out; + return; } if (ioctl(fd, SIOCGIFFLAGS, &interface) < 0) { INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCGIFFLAGS\", err = %d", errno); close(fd); - fd = -1; - goto out; + return; } interface.ifr_flags |= IFF_UP; @@ -302,26 +465,17 @@ static void DoIfup(const char *cmdContent, int maxArg) } close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; } #endif -static void DoSleep(const char *cmdContent, int maxArg) +static void DoSleep(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoSleep invalid arguments :%s", cmdContent); - goto out; - } - + AssertArgcEqualTo(argc, 1); errno = 0; - unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); + unsigned long sleepTime = strtoul(argv[0], NULL, DECIMAL_BASE); if (errno != 0) { INIT_LOGE("cannot covert sleep time in command \" sleep \""); - goto out; + return; } // Limit sleep time in 5 seconds @@ -329,245 +483,131 @@ static void DoSleep(const char *cmdContent, int maxArg) if (sleepTime > sleepTimeLimit) { sleepTime = sleepTimeLimit; } - INIT_LOGI("Sleeping %d second(s)", sleepTime); + INIT_LOGI("Sleeping %d second(s)", (int)sleepTime); sleep((unsigned int)sleepTime); -out: - FreeCmd(&ctx); return; } -static void DoStart(const char* cmdContent, int maxArg) +static void DoStart(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoStart invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoStart %s", cmdContent); - StartServiceByName(cmdContent); -out: - FreeCmd(&ctx); - return; + AssertArgcEqualTo(argc, 1); + StartServiceByName(argv[0]); } -static void DoStop(const char* cmdContent, int maxArg) +static void DoStop(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoStop invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoStop %s", cmdContent); - StopServiceByName(cmdContent); -out: - FreeCmd(&ctx); - return; + AssertArgcEqualTo(argc, 1); + StopServiceByName(argv[0]); } -static void DoReset(const char* cmdContent, int maxArg) +static void DoReset(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoReset invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoReset %s", cmdContent); - DoStop(cmdContent, maxArg); - DoStart(cmdContent, maxArg); -out: - FreeCmd(&ctx); - return; + AssertArgcEqualTo(argc, 1); + DoStop(argc, argv); + DoStart(argc, argv); } -static void DoCopy(const char* cmdContent, int maxArg) +static void DoCopy(int argc, char *argv[]) { int srcFd = -1; int dstFd = -1; int rdLen = 0; int rtLen = 0; char buf[MAX_COPY_BUF_SIZE] = {0}; - char *realPath1 = NULL; - char *realPath2 = NULL; mode_t mode = 0; struct stat fileStat = {0}; - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argv[1] == NULL || - ctx->argc != DEFAULT_COPY_ARGS_CNT) { - INIT_LOGE("DoCopy invalid arguments :%s", cmdContent); - goto out; - } - realPath1 = realpath(ctx->argv[0], NULL); - if (realPath1 == NULL) { - goto out; - } - realPath2 = realpath(ctx->argv[1], NULL); - if (realPath2 == NULL) { - goto out; - } - srcFd = open(realPath1, O_RDONLY); - INIT_ERROR_CHECK(srcFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[0], errno); - INIT_ERROR_CHECK(stat(ctx->argv[0], &fileStat) == 0, goto out, "stat fail "); + + AssertArgcEqualTo(argc, DEFAULT_COPY_ARGS_CNT); + srcFd = open(argv[0], O_RDONLY); + INIT_ERROR_CHECK(srcFd >= 0, goto out, "copy open %s fail %d! ", argv[0], errno); + INIT_ERROR_CHECK(stat(argv[0], &fileStat) == 0, goto out, "stat fail "); mode = fileStat.st_mode; - dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode); - INIT_ERROR_CHECK(dstFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[1], errno); + dstFd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, mode); + INIT_ERROR_CHECK(dstFd >= 0, goto out, "copy open %s fail %d! ", argv[1], errno); while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) { rtLen = write(dstFd, buf, rdLen); - INIT_ERROR_CHECK(rtLen == rdLen, goto out, "write %s file fail %d! ", ctx->argv[1], errno); + INIT_ERROR_CHECK(rtLen == rdLen, goto out, "write %s file fail %d! ", argv[1], errno); } fsync(dstFd); out: - FreeCmd(&ctx); - ctx = NULL; INIT_CHECK(srcFd < 0, close(srcFd); srcFd = -1); INIT_CHECK(dstFd < 0, close(dstFd); dstFd = -1); - INIT_CHECK(realPath1 == NULL, free(realPath1); realPath1 = NULL); - INIT_CHECK(realPath2 == NULL, free(realPath2); realPath2 = NULL); return; } -static void DoChown(const char* cmdContent, int maxArg) +static void DoChown(int argc, char *argv[]) { // format: chown owner group /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoChown invalid arguments :%s", cmdContent); - goto out; + AssertArgcEqualTo(argc, 3); + uid_t owner = DecodeUid(argv[0]); + INIT_ERROR_CHECK(owner != (uid_t)-1, return, "DoChown invalid uid :%s.", argv[0]); + gid_t group = DecodeUid(argv[1]); + INIT_ERROR_CHECK(group != (gid_t)-1, return, "DoChown invalid gid :%s.", argv[1]); + if (chown(argv[2], owner, group) != 0) { + INIT_LOGE("DoChown, failed for %s, err %d.", argv[2], errno); } - - uid_t owner = DecodeUid(ctx->argv[0]); - INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoChown invalid uid :%s.", ctx->argv[0]); - - gid_t group = DecodeUid(ctx->argv[1]); - INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoChown invalid gid :%s.", ctx->argv[1]); - - int pathPos = 2; - if (chown(ctx->argv[pathPos], owner, group) != 0) { - INIT_LOGE("DoChown, failed for %s, err %d.", cmdContent, errno); - } -out: - FreeCmd(&ctx); - return; } -static void DoMkDir(const char* cmdContent, int maxArg) +static void DoMkDir(int argc, char *argv[]) { // 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("DoMkDir invalid arguments :%s", cmdContent); - goto out; - } - - const int withModeArg = 2; - if (ctx->argc != 1 && ctx->argc != maxArg && ctx->argc != withModeArg) { - INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent); - goto out; - } - - 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); - goto out; + AssertArgcGreaterEqual(argc, 1); + AssertArgcNotEqual(argc, 3); + AssertArgcLessEqual(argc, 4); + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH; + if (mkdir(argv[0], mode) != 0 && errno != EEXIST) { + INIT_LOGE("DoMkDir, failed for %s, err %d.", argv[0], errno); + return; } - - if (ctx->argc > 1) { - 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 (argc > 1) { + mode = strtoul(argv[1], NULL, OCTAL_BASE); + if (chmod(argv[0], mode) != 0) { + INIT_LOGE("DoMkDir failed for %s, err %d.", argv[0], errno); } - if (ctx->argc == withModeArg) { - goto out; - } - const int ownerPos = 2; - const int groupPos = 3; - - uid_t owner = DecodeUid(ctx->argv[ownerPos]); - INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoMkDir invalid uid :%s.", ctx->argv[ownerPos]); + } + if (argc == 4) { + uid_t owner = DecodeUid(argv[2]); + INIT_ERROR_CHECK(owner != (uid_t)-1, return, "DoMkDir invalid uid :%s.", argv[2]); - gid_t group = DecodeUid(ctx->argv[groupPos]); - INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoMkDir invalid gid :%s.", ctx->argv[groupPos]); + gid_t group = DecodeUid(argv[3]); + INIT_ERROR_CHECK(group != (gid_t)-1, return, "DoMkDir invalid gid :%s.", argv[3]); - if (chown(ctx->argv[0], owner, group) != 0) { - INIT_LOGE("DoMkDir, chown failed for %s, err %d.", cmdContent, errno); + if (chown(argv[0], owner, group) != 0) { + INIT_LOGE("DoMkDir, chown failed for %s, err %d.", argv[0], errno); } } -out: - FreeCmd(&ctx); - return; } -static void DoChmod(const char* cmdContent, int maxArg) +static void DoChmod(int argc, char *argv[]) { // format: chmod xxxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoChmod invalid arguments :%s", cmdContent); - goto out; - } - - mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE); + AssertArgcEqualTo(argc, 2); + mode_t mode = strtoul(argv[0], NULL, OCTAL_BASE); if (mode == 0) { - INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno); - goto out; - } - - if (chmod(ctx->argv[1], mode) != 0) { - INIT_LOGE("DoChmod, failed for %s, err %d.", cmdContent, errno); - } -out: - 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; + INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", argv[1], errno); + return; } - retStr[mallocLen - 1] = '\0'; - - // for example, source may be none - if (strncmp(retStr, "none", strlen("none")) == 0) { - retStr[0] = '\0'; + if (chmod(argv[1], mode) != 0) { + INIT_LOGE("DoChmod, failed for %s, err %d.", argv[1], errno); } - 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) { + if (strcmp(targetStr, "nodev") == 0) { (*mountflags) |= MS_NODEV; - } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) { + } else if (strcmp(targetStr, "noexec") == 0) { (*mountflags) |= MS_NOEXEC; - } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) { + } else if (strcmp(targetStr, "nosuid") == 0) { (*mountflags) |= MS_NOSUID; - } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) { + } else if (strcmp(targetStr, "rdonly") == 0) { (*mountflags) |= MS_RDONLY; - } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) { + } else if (strcmp(targetStr, "noatime") == 0) { (*mountflags) |= MS_NOATIME; - } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) { + } else if (strcmp(targetStr, "wait") == 0) { WaitForFile(source, WAIT_MAX_COUNT); } else { return 0; @@ -575,211 +615,62 @@ static int GetMountFlag(unsigned long* mountflags, const char* targetStr, const return 1; } -static int CountSpaces(const char* cmdContent, size_t* spaceCnt, size_t* spacePosArr, size_t spacePosArrLen) +static void DoMount(int argc, char *argv[]) { - *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 + AssertArgcGreaterEqual(argc, 3); 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; - + const char *dataStr = NULL; // 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) { + for (int i = 3; i < argc; ++i) { + if (!GetMountFlag(&mountflags, argv[i], argv[1])) { + if (argc - i > 1) { + INIT_LOGE("DoMount, Unknown mount flag: %s", argv[i]); + return; + } + dataStr = argv[i]; 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); + if (mount(argv[1], argv[2], argv[0], mountflags, dataStr ? dataStr : "") < 0) { + INIT_LOGE("DoMount, failed for %s, err %d.", argv[1], errno); } - - free(fileSysType); - free(source); - free(target); } #ifndef OHOS_LITE -#define OPTIONS_SIZE 128u -static void DoInsmodInternal(const char *fileName, char *secondPtr, char *restPtr, int flags) + +// format insmod [-f] [options] +static void DoInsmod(int argc, char *argv[]) { - 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) { + AssertArgcGreaterEqual(argc, 1); + char *options = NULL; + int flags = 0, options_index = 1, fd; + fd = open(argv[0], O_RDONLY | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) { + INIT_LOGE("failed to open %s: %d", argv[0], errno); return; } - char *realPath = realpath(fileName, NULL); - if (realPath == NULL) { - return; + if (argc > 1 && strcmp(argv[1], "-f") == 0) { + flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; + options_index = 2; } - 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; + if (argc - options_index > 0) { + options = ArgvToString(argc-options_index, argv+options_index); } - int rc = syscall(__NR_finit_module, fd, options, flags); - if (rc == -1) { - INIT_LOGE("finit_module for %s failed: %d", realPath, errno); + if (syscall(__NR_finit_module, fd, options ? options : "", flags) < 0) { + INIT_LOGE("finit_module for %s failed: %d", argv[0], errno); } if (fd >= 0) { close(fd); } - free(realPath); - realPath = NULL; - return; + free(options); } -// format insmod [-f] [options] -static void DoInsmod(const char *cmdContent, int maxArg) +static void DoSetParam(int argc, char *argv[]) { - 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("DoSetParam invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGE("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]); - SystemWriteParam(ctx->argv[0], ctx->argv[1]); -out: - FreeCmd(&ctx); - return; + AssertArgcGreaterEqual(argc, 2); + INIT_LOGD("param name: %s, value %s ", argv[0], argv[1]); + SystemWriteParam(argv[0], argv[1]); } #endif // OHOS_LITE @@ -788,11 +679,9 @@ static bool CheckValidCfg(const char *path) { size_t cfgCnt = sizeof(g_supportCfg) / sizeof(g_supportCfg[0]); 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; @@ -801,41 +690,24 @@ static bool CheckValidCfg(const char *path) return false; } -static void DoLoadCfg(const char *path, int maxArg) +static void DoLoadCfg(int argc, char *argv[]) { + AssertArgcEqualTo(argc, 1); + char *path = argv[0]; char buf[LOADCFG_BUF_SIZE] = {0}; FILE *fp = NULL; - size_t maxLoop = 0; - CmdLine *cmdLine = NULL; int len; - INIT_CHECK_ONLY_RETURN(path != NULL); - INIT_LOGI("DoLoadCfg cfg file %s", path); + INIT_LOGD("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"); + fp = fopen(path, "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++; + while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL) { len = strlen(buf); if (len < 1) { continue; @@ -843,128 +715,66 @@ static void DoLoadCfg(const char *path, int maxArg) 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); + DoCmdLine(buf); (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) +static void DoWrite(int argc, char *argv[]) { // 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("DoWrite: invalid arguments :%s", cmdContent); - goto out; - } - char *realPath = realpath(ctx->argv[0], NULL); - if (realPath == NULL) { - goto out; - } - int fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); - if (fd == -1) { - INIT_LOGE("DoWrite: open %s failed: %d", ctx->argv[0], errno); - free(realPath); - realPath = NULL; - goto out; - } - - 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); - goto out; + AssertArgcGreaterEqual(argc, 2); + if (argc == 2) { + WriteCommon(__func__, argv[0], argv[1], + O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); + } else { + char *value = ArgvToString(argc-1, argv+1); + WriteCommon(__func__, argv[0], value, + O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); + free(value); } - free(realPath); - realPath = NULL; - close(fd); -out: - FreeCmd(&ctx); - return; } -static void DoRmdir(const char *cmdContent, int maxArg) +static void DoRmdir(int argc, char *argv[]) { // format: rmdir path - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoRmdir: invalid arguments :%s", cmdContent); - goto out; - } - - int ret = rmdir(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno); - goto out; + AssertArgcEqualTo(argc, 1); + int ret = rmdir(argv[0]); + if (ret < 0) { + INIT_LOGE("DoRmdir: remove %s failed: %d.", argv[0], errno); } -out: - FreeCmd(&ctx); - return; } -static void DoRebootCmd(const char *cmdContent, int maxArg) +static void DoRebootCmd(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoReboot invalid arguments :%s", cmdContent); - goto out; - } - DoReboot(cmdContent); -out: - FreeCmd(&ctx); - return; + AssertArgcLessEqual(argc, 1); + DoReboot(argv[0]); } -static void DoLoadPersistParams(const char *cmdContent, int maxArg) +static void DoLoadPersistParams(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoLoadPersistParams invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("load persist params : %s", cmdContent); + AssertArgcLessEqual(argc, 1); + INIT_LOGD("load persist params : %s", argv[0]); LoadPersistParams(); -out: - FreeCmd(&ctx); - return; } -static void DoTriggerCmd(const char *cmdContent, int maxArg) +static void DoTriggerCmd(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoTrigger invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoTrigger :%s", cmdContent); - DoTriggerExec(cmdContent); -out: - FreeCmd(&ctx); - return; + AssertArgcEqualTo(argc, 1); + INIT_LOGD("DoTrigger :%s", argv[0]); + DoTriggerExec(argv[0]); } -static void DoLoadDefaultParams(const char *cmdContent, int maxArg) +static void DoLoadDefaultParams(int argc, char *argv[]) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoLoadDefaultParams invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("load persist params : %s", cmdContent); - LoadDefaultParams(cmdContent); -out: - FreeCmd(&ctx); + AssertArgcEqualTo(argc, 1); + INIT_LOGD("load persist params : %s", argv[0]); + LoadDefaultParams(argv[0]); return; } -static void DoSetrlimit(const char *cmdContent, int maxArg) +static void DoSetrlimit(int argc, char *argv[]) { char *resource[] = { "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS", @@ -972,123 +782,74 @@ static void DoSetrlimit(const char *cmdContent, int maxArg) "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("DoSetrlimit: invalid arguments :%s", cmdContent); - goto out; - } - + AssertArgcEqualTo(argc, 3); struct rlimit limit; - limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]); - limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]); - int rcs = -1; + limit.rlim_cur = (rlim_t)atoi(argv[1]); + limit.rlim_max = (rlim_t)atoi(argv[2]); for (unsigned int i = 0 ; i < sizeof(resource) / sizeof(char*); ++i) { - if (strcmp(ctx->argv[0], resource[i]) == 0) { - rcs = (int)i; + if (strcmp(argv[0], resource[i]) == 0) { + if (setrlimit(i, &limit)) { + INIT_LOGE("DoSetrlimit failed : %d", errno); + } + return; } } - if (rcs == -1) { - INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]); - goto out; - } - int ret = setrlimit(rcs, &limit); - if (ret) { - INIT_LOGE("DoSetrlimit failed : %d", errno); - goto out; - } -out: - FreeCmd(&ctx); - return; + INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", argv[0]); } -static void DoRm(const char *cmdContent, int maxArg) +static void DoRm(int argc, char *argv[]) { // format: rm /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoRm: invalid arguments :%s", cmdContent); - goto out; - } - int ret = unlink(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno); - goto out; + AssertArgcEqualTo(argc, 1); + if (unlink(argv[0]) < 0) { + INIT_LOGE("DoRm: unlink %s failed: %d.", argv[0], errno); } -out: - FreeCmd(&ctx); - return; } -static void DoExport(const char *cmdContent, int maxArg) +static void DoExport(int argc, char *argv[]) { // format: export xxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoExport: invalid arguments :%s", cmdContent); - goto out; - } - int ret = setenv(ctx->argv[0], ctx->argv[1], 1); + AssertArgcEqualTo(argc, 2); + int ret = setenv(argv[0], argv[1], 1); if (ret != 0) { - INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno); - goto out; + INIT_LOGE("DoExport: set %s with %s failed: %d", argv[0], argv[1], errno); } -out: - FreeCmd(&ctx); return; } -static void DoExec(const char *cmdContent, int maxArg) +static void DoExec(int argc, char *argv[]) { // format: exec /xxx/xxx/xxx xxx + AssertArgcGreaterEqual(argc, 1); pid_t pid = fork(); if (pid < 0) { - INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent); + INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", argv[0]); return; } if (pid == 0) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) { - INIT_LOGE("DoExec: invalid arguments :%s", cmdContent); - _exit(0x7f); - } #ifdef OHOS_LITE - int ret = execve(ctx->argv[0], ctx->argv, NULL); + execve(argv[0], argv, NULL); #else - int ret = execv(ctx->argv[0], ctx->argv); + execv(argv[0], argv); #endif - if (ret == -1) { - INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno); - } - FreeCmd(&ctx); + INIT_LOGE("DoExec: execute \"%s\" failed: %d.", argv[0], errno); _exit(0x7f); } - return; } #ifndef __LITEOS__ -static void DoSymlink(const char *cmdContent, int maxArg) +static void DoSymlink(int argc, char *argv[]) { // 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("DoSymlink: invalid arguments :%s", cmdContent); - goto out; + AssertArgcEqualTo(argc, 2); + if (symlink(argv[0], argv[1]) < 0) { + INIT_LOGE("DoSymlink: link %s to %s failed: %d", argv[0], argv[1], errno); } - - 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); - goto out; - } -out: - FreeCmd(&ctx); - return; } -static mode_t GetDeviceMode(const char *deviceStr) +static mode_t GetDeviceMode(char deviceChar) { - switch (*deviceStr) { + switch (deviceChar) { case 'b': case 'B': return S_IFBLK; @@ -1103,127 +864,116 @@ static mode_t GetDeviceMode(const char *deviceStr) } } -static void DoMakeNode(const char *cmdContent, int maxArg) +static void DoMakeNode(int argc, char *argv[]) { // 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; - const int decimal = 10; - const int octal = 8; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoMakeNode: invalid arguments :%s", cmdContent); - goto out; - } - - if (!access(ctx->argv[1], F_OK)) { + AssertArgcEqualTo(argc, 5); + if (!access(argv[0], F_OK)) { INIT_LOGE("DoMakeNode failed, path has not sexisted"); - goto out; + return; } - mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]); - unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal); - unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal); - mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal); - - 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); - goto out; + mode_t deviceMode = GetDeviceMode(*argv[1]); + unsigned int major = strtoul(argv[3], NULL, DECIMAL_BASE); + unsigned int minor = strtoul(argv[4], NULL, DECIMAL_BASE); + mode_t authority = strtoul(argv[2], NULL, OCTAL_BASE); + if (mknod(argv[0], deviceMode | authority, makedev(major, minor)) < 0) { + INIT_LOGE("DoMakeNode: path: %s failed: %d", argv[0], errno); } -out: - FreeCmd(&ctx); - return; } -static void DoMakeDevice(const char *cmdContent, int maxArg) +static void DoMakeDevice(int argc, char *argv[]) { + // why do nothing in the method // format: makedev major minor - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int decimal = 10; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoMakedevice: invalid arguments :%s", cmdContent); - goto out; - } - unsigned int major = strtoul(ctx->argv[0], NULL, decimal); - unsigned int minor = strtoul(ctx->argv[1], NULL, decimal); - dev_t deviceId = makedev(major, minor); - if (deviceId < 0) { - INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno); - goto out; - } -out: - FreeCmd(&ctx); - return; + AssertArgcEqualTo(argc, 2); + unsigned int major = strtoul(argv[0], NULL, DECIMAL_BASE); + unsigned int minor = strtoul(argv[1], NULL, DECIMAL_BASE); + (void)makedev(major, minor); } #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); -} +typedef void (CmdFunctionType)(int argc, char *argv[]); struct CmdTable { char name[MAX_CMD_NAME_LEN]; - int maxArg; - void (*DoFuncion)(const char *cmdContent, int maxArg); + CmdFunctionType *doFuncion; }; 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 }, + { "start", DoStart }, + { "mkdir", DoMkDir }, + { "chmod", DoChmod }, + { "chown", DoChown }, + { "mount", DoMount }, + { "export", DoExport }, + { "loadcfg ", DoLoadCfg }, + { "rm", DoRm }, + { "rmdir", DoRmdir }, + { "write", DoWrite }, + { "exec", 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 ", 1, DoLoadDefaultParams }, - { "ifup ", 1, DoIfup }, + { "mknode", DoMakeNode }, + { "makedev", DoMakeDevice }, + { "symlink", DoSymlink }, + { "trigger", DoTriggerCmd }, + { "insmod", DoInsmod }, + { "setparam", DoSetParam }, + { "load_persist_params", DoLoadPersistParams }, + { "load_param", DoLoadDefaultParams }, + { "ifup", 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 } + { "stop", DoStop }, + { "reset", DoReset }, + { "copy", DoCopy }, + { "reboot", DoRebootCmd }, + { "setrlimit", DoSetrlimit }, + { "sleep", DoSleep }, + { "hostname", DoSetHostname }, + { "domainname", DoSetDomainname } }; -void DoCmdByName(const char *name, const char *cmdContent) +static CmdFunctionType* GetCommandFunction(const char *name) { + for (size_t i = 0; i < sizeof(CMD_TABLE) / sizeof(struct CmdTable); ++i) { + if (strcmp(CMD_TABLE[i].name, name) == 0) { + return CMD_TABLE[i].doFuncion; + } + } + return NULL; +} + +void DoCmdLine(const char* cmdStr) { - if (name == NULL || cmdContent == NULL) { + CmdFunctionType *func; + struct CmdArgs *args = ParseCommand(cmdStr); + if (!args || args->argc == 0) { + FreeCmd(args); + return; + } + func = GetCommandFunction(args->argv[0]); + if (func == NULL) { + INIT_LOGE("%s: unknown cmd name %s.", __func__, args->argv[0]); return; } + func(args->argc+1, args->argv-1); + FreeCmd(args); +} - size_t cmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); - 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; - } +void DoCmdByName(const char *name, const char *cmdContent) +{ + CmdFunctionType *func; + struct CmdArgs *args; + func = GetCommandFunction(name); + if (func == NULL) { + INIT_LOGE("%s: unknown cmd name %s.", __func__, name); + return; } - if (i == cmdCnt) { - INIT_LOGE("DoCmd, unknown cmd name %s.", name); + args = ParseCommand(cmdContent); + if (args == NULL) { + INIT_LOGE("%s: parse cmdContent fail: %s", __func__, cmdContent); + return; } + func(args->argc, args->argv); + FreeCmd(args); } const char *GetMatchCmd(const char *cmdStr) @@ -1240,39 +990,3 @@ const char *GetMatchCmd(const char *cmdStr) } return NULL; } - -void ParseCmdLine(const char* cmdStr, CmdLine* resCmd) -{ - size_t cmdLineLen = 0; - if (cmdStr == NULL || resCmd == NULL || (cmdLineLen = strlen(cmdStr)) == 0) { - return; - } - - size_t supportCmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); - 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)); - } -} - diff --git a/services/src/init_jobs.c b/services/src/init_jobs.c index 563a5065dc73e069bf0c3b2e3608114a952366d1..45c6ca2b06933cba221affb0e815f8af34d6036c 100644 --- a/services/src/init_jobs.c +++ b/services/src/init_jobs.c @@ -44,8 +44,7 @@ void DumpAllJobs() INIT_LOGD("\tjob name: %s", g_jobs[i].name); INIT_LOGD("\tlist all commands:"); for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) { - INIT_LOGD("\t\tcommand name : %s, command options: %s", - g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent); + INIT_LOGD("\t\tcommand : %s", g_jobs[i].cmdLines[j]); } } INIT_LOGD("To dump all jobs finished"); @@ -93,13 +92,13 @@ static void ParseJob(const cJSON* jobItem, Job* resJob) return; } - resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine)); + resJob->cmdLines = malloc(cmdLinesCnt * sizeof(char*)); if (resJob->cmdLines == NULL) { INIT_LOGE("allocate memory for command line failed"); return; } - if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(CmdLine), 0, cmdLinesCnt * sizeof(CmdLine)) != EOK) { + if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(char*), 0, cmdLinesCnt * sizeof(char*)) != EOK) { free(resJob->cmdLines); resJob->cmdLines = NULL; return; @@ -108,7 +107,7 @@ static void ParseJob(const cJSON* jobItem, Job* resJob) for (int i = 0; i < cmdLinesCnt; ++i) { char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); - ParseCmdLine(cmdLineStr, &(resJob->cmdLines[i])); + resJob->cmdLines[i] = strdup(cmdLineStr); } } @@ -164,9 +163,8 @@ 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])); + DoCmdLine(g_jobs[i].cmdLines[j]); } // Walk through all jobs // break; @@ -181,11 +179,10 @@ void ReleaseAllJobs() } 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; + for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) { + free(&g_jobs[i].cmdLines[j]); } + free(g_jobs[i].cmdLines); } free(g_jobs); diff --git a/services/src/init_service.c b/services/src/init_service.c index 248c1962d75f4ab7d9b6888592a36f895f3ee0d7..b0b850f6aadfea6da5e2afb7016d968b0233d4a6 100644 --- a/services/src/init_service.c +++ b/services/src/init_service.c @@ -322,12 +322,11 @@ static int ExecRestartCmd(const Service *service) } 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]); + INIT_LOGI("SetOnRestart cmdLine %s", service->onRestart->cmdLine[i]); + DoCmdLine(service->onRestart->cmdLine[i]); + free(service->onRestart->cmdLine[i]); } free(service->onRestart->cmdLine); - service->onRestart->cmdLine = NULL; free(service->onRestart); return SERVICE_SUCCESS; } diff --git a/services/src/init_service_manager.c b/services/src/init_service_manager.c index 8079fbe8cb7c529689003a245e9d2d720eba9e41..87228fcf844c611fc05db3a23c8aeccc8d75b49e 100644 --- a/services/src/init_service_manager.c +++ b/services/src/init_service_manager.c @@ -608,7 +608,7 @@ static int GetServiceOnRestart(const cJSON* curArrItem, Service* curServ) if (curServ->onRestart == NULL) { return SERVICE_FAILURE; } - curServ->onRestart->cmdLine = (CmdLine *)calloc(cmdCnt, sizeof(CmdLine)); + curServ->onRestart->cmdLine = calloc(cmdCnt, sizeof(char*)); if (curServ->onRestart->cmdLine == NULL) { free(curServ->onRestart); curServ->onRestart = NULL; @@ -618,6 +618,9 @@ static int GetServiceOnRestart(const cJSON* curArrItem, Service* curServ) for (int i = 0; i < cmdCnt; ++i) { cJSON* cmdJ = cJSON_GetArrayItem(filedJ, i); if (!cJSON_IsString(cmdJ) || !cJSON_GetStringValue(cmdJ)) { + for (int j = 0; j < i; ++j) { + free(curServ->onRestart->cmdLine[j]); + } free(curServ->onRestart->cmdLine); curServ->onRestart->cmdLine = NULL; free(curServ->onRestart); @@ -625,7 +628,7 @@ static int GetServiceOnRestart(const cJSON* curArrItem, Service* curServ) return SERVICE_FAILURE; } char *cmdStr = cJSON_GetStringValue(cmdJ); - ParseCmdLine(cmdStr, &curServ->onRestart->cmdLine[i]); + curServ->onRestart->cmdLine[i] = strdup(cmdStr); } return SERVICE_SUCCESS; } diff --git a/services/test/unittest/common/cmd_func_test.cpp b/services/test/unittest/common/cmd_func_test.cpp index 28cf07f5e4948dd15f301a4d508fb72bbfcfac31..c28fed891efad4abf254117c04d456c9dc74cad1 100644 --- a/services/test/unittest/common/cmd_func_test.cpp +++ b/services/test/unittest/common/cmd_func_test.cpp @@ -28,7 +28,6 @@ using namespace testing::ext; namespace OHOS { -std::vector g_supportedCmds; const std::string ROOT_DIR = "/storage/data/"; const std::string TEST_DRI = ROOT_DIR + "StartInitTestDir"; const std::string TEST_FILE = TEST_DRI + "/test.txt"; @@ -66,13 +65,6 @@ class StartupInitUTest : public testing::Test { public: static void SetUpTestCase() { - g_supportedCmds.push_back(std::string("start ")); - g_supportedCmds.push_back(std::string("mkdir ")); - g_supportedCmds.push_back(std::string("chmod ")); - g_supportedCmds.push_back(std::string("chown ")); - g_supportedCmds.push_back(std::string("mount ")); - g_supportedCmds.push_back(std::string("loadcfg ")); - mode_t mode = DEFAULT_DIR_MODE; if (mkdir(TEST_DRI.c_str(), mode) != 0) { if (errno != EEXIST) { @@ -129,364 +121,6 @@ public: void TearDown() {} }; -/* - ** @tc.name: cmdFuncParseCmdTest_001 - ** @tc.desc: parse function, nullptr test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_001, TestSize.Level1) -{ - // do not crash - ParseCmdLine(nullptr, nullptr); -}; - -/* - ** @tc.name: cmdFuncParseCmdTest_002 - ** @tc.desc: parse function, invalid strings test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - ParseCmdLine(nullptr, &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); - - ParseCmdLine("", &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); - - ParseCmdLine("xxxxxxxx", &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); - - ParseCmdLine("asdnkawdqw4145a45sdqw_-+\\\\sdqwdasd", &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); -} - -/* - ** @tc.name: cmdFuncParseCmdTest_003 - ** @tc.desc: parse function, cmd content empty test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - for (size_t i = 0; i < g_supportedCmds.size(); ++i) { - ParseCmdLine(g_supportedCmds[i].c_str(), &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); - } -} - -/* - ** @tc.name: cmdFuncParseCmdTest_004 - ** @tc.desc: parse function, cmd content too long test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - char toLongContent[MAX_CMD_CONTENT_LEN + 10]; - memset_s(toLongContent, MAX_CMD_CONTENT_LEN + 10, 'x', MAX_CMD_CONTENT_LEN + 9); - toLongContent[MAX_CMD_CONTENT_LEN + 9] = '\0'; - for (size_t i = 0; i < g_supportedCmds.size(); ++i) { - size_t curCmdLen = g_supportedCmds[i].length(); - char* curCmd = (char*)malloc(curCmdLen + MAX_CMD_CONTENT_LEN + 10); - if (curCmd == nullptr) { - printf("[----------] StartupInitUTest, cmdFuncParseCmdTest004, malloc failed.\n"); - break; - } - errno_t ret = memcpy_s(curCmd, curCmdLen + MAX_CMD_CONTENT_LEN + 10, \ - g_supportedCmds[i].c_str(), curCmdLen); - errno_t ret2 = memcpy_s(curCmd + curCmdLen, MAX_CMD_CONTENT_LEN + 10, \ - toLongContent, strlen(toLongContent)); - if (ret != EOK || ret2 != EOK) { - printf("[----------] StartupInitUTest, cmdFuncParseCmdTest004, memcpy_s failed.\n"); - free(curCmd); - curCmd = nullptr; - break; - } - curCmd[curCmdLen + MAX_CMD_CONTENT_LEN + 9] = '\0'; - - ParseCmdLine(curCmd, &curCmdLine); - EXPECT_EQ(0, strlen(curCmdLine.name)); - EXPECT_EQ(0, strlen(curCmdLine.cmdContent)); - free(curCmd); - curCmd = nullptr; - } -} - -/* - ** @tc.name: cmdFuncParseCmdTest_005 - ** @tc.desc: parse function, parse success test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_005, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - ParseCmdLine("start InitTestService", &curCmdLine); - EXPECT_EQ(0, strcmp("start ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("InitTestService", curCmdLine.cmdContent)); - - ParseCmdLine("mkdir InitTestDir", &curCmdLine); - EXPECT_EQ(0, strcmp("mkdir ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("InitTestDir", curCmdLine.cmdContent)); - - ParseCmdLine("chmod 0500 /bin/InitTestBin", &curCmdLine); - EXPECT_EQ(0, strcmp("chmod ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("0500 /bin/InitTestBin", curCmdLine.cmdContent)); - - ParseCmdLine("chown 1000 1000 /bin/InitTestBin", &curCmdLine); - EXPECT_EQ(0, strcmp("chown ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("1000 1000 /bin/InitTestBin", curCmdLine.cmdContent)); - - ParseCmdLine("mount vfat /dev/mmcblk1 /sdcard rw,umask=000", &curCmdLine); - EXPECT_EQ(0, strcmp("mount ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("vfat /dev/mmcblk1 /sdcard rw,umask=000", curCmdLine.cmdContent)); -}; - -/* - ** @tc.name: cmdFuncDoCmdTest_001 - ** @tc.desc: do cmd function, nullptr test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_001, TestSize.Level1) -{ - // do not crash here - DoCmd(nullptr); -} - -/* - ** @tc.name: cmdFuncDoCmdTest_002 - ** @tc.desc: do cmd function, do start fail test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_002, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - std::string cmdStr = "start "; - std::string cmdContentStr = "NameNotExist"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); -} - -/* - ** @tc.name: cmdFuncDoCmdTest_003 - ** @tc.desc: do cmd function, do mkdir fail test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - std::string cmdStr = "mkdir "; - std::string cmdContentStr = "/DirNotExist/DirNotExist/DirNotExist"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - // make sure that the directory does not exist - DIR* dirTmp = opendir(cmdContentStr.c_str()); - EXPECT_TRUE(dirTmp == nullptr); - EXPECT_TRUE(errno == ENOENT); - if (dirTmp != nullptr) { // just in case - closedir(dirTmp); - dirTmp = nullptr; - } - - // error argument count, bad format - cmdContentStr = " /storage/data/cmdFuncDoCmdTest003 0755 system"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - // make sure that the directory does not exist - dirTmp = opendir("/storage/data/cmdFuncDoCmdTest003"); - EXPECT_TRUE(dirTmp == nullptr); - EXPECT_TRUE(errno == ENOENT); - if (dirTmp != nullptr) { // just in case - closedir(dirTmp); - dirTmp = nullptr; - } -} - -/* - ** @tc.name: cmdFuncDoCmdTest_004 - ** @tc.desc: do cmd function, do chmod fail test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - std::string cmdStr = "chmod "; - std::string cmdContentStr = "755 " + TEST_FILE; // should be 0755, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - cmdContentStr = "0855 " + TEST_FILE; // should not exceed 0777, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - cmdContentStr = "07b5 " + TEST_FILE; // non-digital character, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - cmdContentStr = "075 " + TEST_FILE; // should be 0xxx, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - cmdContentStr = "0755 " + TEST_FILE; // too many spaces, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - struct stat testFileStat = {0}; - EXPECT_EQ(0, stat(TEST_FILE.c_str(), &testFileStat)); - -#ifndef USE_EMMC_STORAGE // emmc storage does not support chmod/chown - - EXPECT_EQ(TEST_FILE_MODE, testFileStat.st_mode & TEST_FILE_MODE); // file mode is not changed - -#endif // USE_EMMC_STORAGE -} - -/* - ** @tc.name: cmdFuncDoCmdTest_005 - ** @tc.desc: do cmd function, do chown fail test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - std::string cmdStr = "chown "; - std::string cmdContentStr = "888 " + TEST_FILE; // uid or gid missing, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - cmdContentStr = "888 8b9 " + TEST_FILE; // non-digital character, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - DoCmd(&curCmdLine); - - struct stat testFileStat = {0}; - EXPECT_EQ(0, stat(TEST_FILE.c_str(), &testFileStat)); - -#ifndef USE_EMMC_STORAGE // emmc storage does not support chmod/chown - - EXPECT_EQ(testFileStat.st_uid, TEST_FILE_UID); // uid not changed - EXPECT_EQ(testFileStat.st_gid, TEST_FILE_GID); // gid not changed - -#endif // USE_EMMC_STORAGE -} - -/* - ** @tc.name: cmdFuncDoCmdTest_006 - ** @tc.desc: do cmd function, do success test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level1) -{ - CmdLine curCmdLine; - - // mkdir success - std::string cmdStr = "mkdir "; - std::string cmdContentStr = TEST_DRI + "/cmdFuncDoCmdTest006"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - - DoCmd(&curCmdLine); - DIR* dirTmp = opendir(cmdContentStr.c_str()); - EXPECT_TRUE(dirTmp != nullptr); - if (dirTmp != nullptr) { - closedir(dirTmp); - dirTmp = nullptr; - } - - // delete dir - if (remove(cmdContentStr.c_str()) != 0) { - printf("[----------] StartupInitUTest, cmdFuncDoCmdTest006 remove %s failed, error %d.\n",\ - TEST_DRI.c_str(), errno); - } - - // chmod success - cmdStr = "chmod "; - cmdContentStr = "0440 " + TEST_FILE; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - -#ifndef USE_EMMC_STORAGE // emmc storage does not support chmod/chown - - DoCmd(&curCmdLine); - struct stat testFileStat = {0}; - EXPECT_EQ(0, stat(TEST_FILE.c_str(), &testFileStat)); - mode_t targetMode = S_IRUSR | S_IRGRP; - EXPECT_EQ(targetMode, testFileStat.st_mode & targetMode); // changed - -#endif // USE_EMMC_STORAGE - - // chown success - cmdStr = "chown "; - cmdContentStr = "888 888 " + TEST_FILE; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - -#ifndef USE_EMMC_STORAGE // emmc storage does not support chmod/chown - - DoCmd(&curCmdLine); - EXPECT_EQ(0, stat(TEST_FILE.c_str(), &testFileStat)); - EXPECT_EQ(testFileStat.st_uid, 888); // changed - EXPECT_EQ(testFileStat.st_gid, 888); // changed - -#endif // USE_EMMC_STORAGE -} - /* ** @tc.name: cfgCheckStat_001 ** @tc.desc: init.cfg file state check @@ -645,56 +279,6 @@ static void CheckServices(const cJSON* fileRoot) } } -static void CheckCmd(const CmdLine* resCmd) -{ - EXPECT_TRUE(strlen(resCmd->name) > 0); - EXPECT_TRUE(strlen(resCmd->cmdContent) > 0); - - if (strcmp("start ", resCmd->name) == 0) { - for (size_t i = 0; i < strlen(resCmd->cmdContent); ++i) { - EXPECT_NE(' ', resCmd->cmdContent[i]); // no spaces in service name - } - } else if (strcmp("mkdir ", resCmd->name) == 0) { - for (size_t i = 0; i < strlen(resCmd->cmdContent); ++i) { - EXPECT_NE(' ', resCmd->cmdContent[i]); // no spaces in path string - EXPECT_NE('.', resCmd->cmdContent[i]); // no dots in path string - } - } else if (strcmp("chmod ", resCmd->name) == 0) { - EXPECT_TRUE(strlen(resCmd->cmdContent) >= 6); // 0xxx x at least 6 characters - EXPECT_EQ('0', resCmd->cmdContent[0]); - EXPECT_EQ(' ', resCmd->cmdContent[4]); // 4 bytes, after 0xxx must be space - for (int i = 1; i < 4; ++i) { // 4 bytes, 0xxx, xxx must be digits - EXPECT_TRUE(resCmd->cmdContent[i] >= '0' && resCmd->cmdContent[i] <= '7'); - } - for (size_t i = 5; i < strlen(resCmd->cmdContent); ++i) { // target starts from index 5 - EXPECT_NE(' ', resCmd->cmdContent[i]); // no spaces allowed - EXPECT_NE('.', resCmd->cmdContent[i]); // no dots allowed - } - } else if (strcmp("chown ", resCmd->name) == 0) { - EXPECT_TRUE(strlen(resCmd->cmdContent) >= 5); // x y z at least 5 characters - EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space - EXPECT_NE(' ', resCmd->cmdContent[strlen(resCmd->cmdContent) - 1]); // should not end with space - size_t spacePos = 0; - size_t spaceCnt = 0; - for (size_t i = 1; i < strlen(resCmd->cmdContent); ++i) { - if (resCmd->cmdContent[i] == ' ') { - ++spaceCnt; - if (spacePos != 0) { - EXPECT_NE(spacePos + 1, i); // consecutive spaces should not appear - } - spacePos = i; - } - } - EXPECT_EQ(spaceCnt, 2); // 2 spaces allowed in cmd content - } else if (strcmp("mount ", resCmd->name) == 0) { - EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space - } else if (strcmp("loadcfg ", resCmd->name) == 0) { - EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space - } else { // unknown cmd - EXPECT_TRUE(false); - } -} - static void CheckJob(const cJSON* jobItem) { if (jobItem == nullptr) { @@ -712,11 +296,6 @@ static void CheckJob(const cJSON* jobItem) char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); EXPECT_TRUE(cmdLineStr != nullptr); EXPECT_TRUE(strlen(cmdLineStr) > 0); - - CmdLine resCmd; - (void)memset_s(&resCmd, sizeof(resCmd), 0, sizeof(resCmd)); - ParseCmdLine(cmdLineStr, &resCmd); - CheckCmd(&resCmd); } } @@ -802,22 +381,6 @@ static void CreateIllegalCfg() fclose(testCfgFile); } -/* - * @tc.name: cmdFuncDoLoadCfgTest_001 - * @tc.desc: parse function, parse success test - * @tc.type: FUNC - * @tc.require: AR000F861Q - */ -HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level1) -{ - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - - ParseCmdLine("loadcfg /patch/fstab.cfg", &curCmdLine); - EXPECT_EQ(0, strcmp("loadcfg ", curCmdLine.name)); - EXPECT_EQ(0, strcmp("/patch/fstab.cfg", curCmdLine.cmdContent)); -}; - /* * @tc.name: cmdFuncDoLoadCfgTest_002 * @tc.desc: fstab.cfg file fail test @@ -826,33 +389,28 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level1) */ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level1) { - CmdLine curCmdLine; - std::string cmdStr = "loadcfg "; - std::string cmdContentStr = "/patch/file_not_exist.cfg"; + std::string cmdStr; + std::string confStr; struct stat testCfgStat = {0}; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - stat(cmdContentStr.c_str(), &testCfgStat); + confStr = "/patch/file_not_exist.cfg"; + cmdStr = "loadcfg "; + cmdStr += confStr; + stat(confStr.c_str(), &testCfgStat); EXPECT_TRUE(testCfgStat.st_size == 0); - DoCmd(&curCmdLine); + DoCmdLine(cmdStr.c_str()); - cmdContentStr = TEST_CFG_ILLEGAL; + confStr = TEST_CFG_ILLEGAL; + cmdStr = "loadcfg "; + cmdStr += confStr; CreateIllegalCfg(); - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - EXPECT_EQ(0, stat(cmdContentStr.c_str(), &testCfgStat)); EXPECT_TRUE(testCfgStat.st_size > 0); - DoCmd(&curCmdLine); + DoCmdLine(cmdStr.c_str()); // remove tmp file - if (remove(TEST_CFG_ILLEGAL.c_str()) != 0) { + if (remove(confStr.c_str()) != 0) { printf("[----------] StartupInitUTest, remove %s failed, error %d.\n",\ - TEST_CFG_ILLEGAL.c_str(), errno); + confStr.c_str(), errno); } } @@ -864,22 +422,15 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level1) */ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level1) { - CmdLine curCmdLine; - std::string cmdStr = "loadcfg "; - std::string cmdContentStr = "/patch/fstab.cfg"; char buf[CAT_BUF_SIZE] = {0}; struct stat testCfgStat = {0}; FILE* fd = nullptr; size_t size; bool hasZpfs = false; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); - EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); - EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); - - DoCmd(&curCmdLine); + DoCmdLine("loadcfg /patch/fstab.cfg"); - stat(cmdContentStr.c_str(), &testCfgStat); + stat("/patch/fstab.cfg", &testCfgStat); if (testCfgStat.st_size > 0) { fd = fopen(TEST_PROC_MOUNTS.c_str(), "r");