init_cmds.c 40.1 KB
Newer Older
W
wenjun 已提交
1
/*
Z
zhong_ning 已提交
2
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
W
wenjun 已提交
3 4 5 6 7 8 9 10 11 12 13 14
 * 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.
 */
15

W
wenjun 已提交
16
#include "init_cmds.h"
Z
zhong_ning 已提交
17

W
wenjun 已提交
18 19
#include <ctype.h>
#include <errno.h>
S
sun_fan 已提交
20 21 22 23 24
#include <fcntl.h>
#ifndef OHOS_LITE
#include <linux/module.h>
#endif
#include <net/if.h>
25
#include <stdbool.h>
W
wenjun 已提交
26 27 28
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Z
zhong_ning 已提交
29
#include <sys/ioctl.h>
W
wenjun 已提交
30
#include <sys/mount.h>
Z
zhong_ning 已提交
31
#include <sys/resource.h>
W
wenjun 已提交
32
#include <sys/stat.h>
S
sun_fan 已提交
33
#include <sys/syscall.h>
Z
zhong_ning 已提交
34 35
#include <sys/sysmacros.h>
#include <sys/wait.h>
W
wenjun 已提交
36
#include <unistd.h>
Z
zhong_ning 已提交
37 38
#include "init_jobs.h"
#include "init_log.h"
Z
zhong_ning 已提交
39 40 41
#ifndef OHOS_LITE
#include "init_param.h"
#endif
Z
zhong_ning 已提交
42
#include "init_reboot.h"
W
wenjun 已提交
43
#include "init_service_manager.h"
Z
zhong_ning 已提交
44
#include "init_utils.h"
W
wenjun 已提交
45 46
#include "securec.h"

Z
zhong_ning 已提交
47
#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH)  // mkdir, default mode
W
wenjun 已提交
48 49 50
#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

M
mamingshuai 已提交
51 52 53
#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
L
leon 已提交
54
#define OCTAL_TYPE 8  // 8 means octal to decimal
S
sun_fan 已提交
55
#define MAX_BUFFER 256UL
Z
zhong_ning 已提交
56
#define AUTHORITY_MAX_SIZE 128
Z
zhong_ning 已提交
57
#define WAIT_MAX_COUNT 10
Z
zhong_ning 已提交
58

M
mamingshuai 已提交
59
static const char *g_supportCfg[] = {
J
jason_gitee 已提交
60
    "/etc/patch.cfg",
M
mamingshuai 已提交
61 62 63
    "/patch/fstab.cfg",
};

Z
zhong_ning 已提交
64
#ifndef OHOS_LITE
S
sun_fan 已提交
65
int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen)
Z
zhong_ning 已提交
66 67 68 69 70 71 72 73 74 75 76
{
    if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) {
        return -1;
    }
    char tmpName[MAX_PARAM_NAME_LEN] = {0};
    char tmpValue[MAX_PARAM_VALUE_LEN] = {0};
    unsigned int tmpLen = 0;
    char *p = NULL;
    char *tmpptr = NULL;
    p = strchr(symValue, '$');
    if (p == NULL) { // not has '$' copy the original string
Z
zhong_ning 已提交
77
        INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, paramLen - 1) == EOK, -1);
Z
zhong_ning 已提交
78 79 80 81
        return 0;
    }
    tmpLen = p - symValue;
    if (tmpLen > 0) { // copy '$' front string
Z
zhong_ning 已提交
82
        INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, tmpLen) == EOK, -1);
Z
zhong_ning 已提交
83 84 85 86 87 88
    }
    p++;
    if (*p == '{') {
        p++;
        char *right = strchr(p, '}');
        if (right == NULL) {
Z
zhong_ning 已提交
89
            INIT_LOGE("Invalid cfg file name, miss '}'.");
Z
zhong_ning 已提交
90 91 92 93
            return -1;
        }
        tmpLen = right - p;
        if (tmpLen > MAX_PARAM_NAME_LEN) {
Z
zhong_ning 已提交
94
            INIT_LOGE("Parameter name longer than %d", MAX_PARAM_NAME_LEN);
Z
zhong_ning 已提交
95 96
            return -1;
        }
Z
zhong_ning 已提交
97
        INIT_CHECK_RETURN_VALUE(strncpy_s(tmpName, MAX_PARAM_NAME_LEN, p, tmpLen) == EOK, -1);
Z
zhong_ning 已提交
98 99
        int ret = SystemReadParam(tmpName, tmpValue, &tmpLen); // get param
        if (ret != 0) {
Z
zhong_ning 已提交
100
            INIT_LOGE("Failed to read parameter \" %s \"", tmpName);
Z
zhong_ning 已提交
101 102 103
            return -1;
        }
        // change param to new string
Z
zhong_ning 已提交
104
        INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpValue, MAX_PARAM_VALUE_LEN) == EOK, -1);
Z
zhong_ning 已提交
105 106 107
        tmpptr = right + 1;
        tmpLen = paramLen - (tmpptr - symValue);
        if (*tmpptr != '\0') { // copy last string
Z
zhong_ning 已提交
108
            INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpptr, tmpLen) == EOK, -1);
Z
zhong_ning 已提交
109
        }
Z
zhong_ning 已提交
110
        INIT_LOGI("paramValue is %s ", paramValue);
Z
zhong_ning 已提交
111 112
        return 0;
    } else {
Z
zhong_ning 已提交
113
        INIT_LOGE("Invalid cfg file name, miss '{'.");
Z
zhong_ning 已提交
114 115 116
        return -1;
    }
}
S
sun_fan 已提交
117 118
#else
// For ite ohos, do not support parameter operation. just do string copy
S
sun_fan 已提交
119
inline int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen)
S
sun_fan 已提交
120
{
Z
zhong_ning 已提交
121
    return (strncpy_s(paramValue, paramLen, symValue, strlen(symValue)) == EOK) ? 0 : -1;
S
sun_fan 已提交
122
}
Z
zhong_ning 已提交
123 124
#endif

S
sun_fan 已提交
125
struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount)
Z
zhong_ning 已提交
126
{
Z
zhong_ning 已提交
127
    INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL);
Z
zhong_ning 已提交
128
    struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs));
Z
zhong_ning 已提交
129
    INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL);
Z
zhong_ning 已提交
130

S
sun_fan 已提交
131 132 133 134 135
    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;
    }
    ctx->argv = (char**)malloc(sizeof(char*) * (size_t)argsCount + 1);
Z
zhong_ning 已提交
136
    INIT_CHECK(ctx->argv != NULL, FreeCmd(&ctx); return NULL);
Z
zhong_ning 已提交
137 138

    char tmpCmd[MAX_BUFFER];
S
sun_fan 已提交
139 140 141 142 143 144 145
    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;
    }

Z
zhong_ning 已提交
146
    INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK,
Z
zhong_ning 已提交
147 148 149 150
        FreeCmd(&ctx);
        return NULL);
    tmpCmd[strlen(cmdContent)] = '\0';

S
sun_fan 已提交
151 152 153 154 155 156 157 158
    char *p = tmpCmd;
    char *token = NULL;
    size_t allocSize = 0;

    // Skip lead whitespaces
    while (isspace(*p)) {
        p++;
    }
Z
zhong_ning 已提交
159
    ctx->argc = 0;
S
sun_fan 已提交
160 161 162
    token = strstr(p, delim);
    if (token == NULL) { // No whitespaces
        // Make surce there is enough memory to store parameter value
S
sun_fan 已提交
163
        allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1);
S
sun_fan 已提交
164
        ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize);
Z
zhong_ning 已提交
165 166
        INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(&ctx); return NULL);
        INIT_CHECK(GetParamValue(p, ctx->argv[ctx->argc], allocSize) == 0,
S
sun_fan 已提交
167
            FreeCmd(&ctx); return NULL);
Z
zhong_ning 已提交
168
        ctx->argc += 1;
S
sun_fan 已提交
169 170 171 172 173 174 175
        ctx->argv[ctx->argc] = NULL;
        return ctx;
    }

    int index = ctx->argc;
    while (token != NULL) {
        // Too more arguments, treat rest of data as one argument
Z
zhong_ning 已提交
176
        if (index == (argsCount - 1)) {
S
sun_fan 已提交
177 178 179
            break;
        }
        *token = '\0'; // replace it with '\0';
S
sun_fan 已提交
180
        allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1);
S
sun_fan 已提交
181
        ctx->argv[index] = calloc(sizeof(char), allocSize);
Z
zhong_ning 已提交
182 183
        INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL);
        INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0,
S
sun_fan 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197
            FreeCmd(&ctx); return NULL);
        p = token + 1; // skip '\0'
        // Skip lead whitespaces
        while (isspace(*p)) {
            p++;
        }
        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;
S
sun_fan 已提交
198
        allocSize = restSize + MAX_PARAM_VALUE_LEN + 1;
S
sun_fan 已提交
199
        ctx->argv[index] = calloc(sizeof(char),  allocSize);
Z
zhong_ning 已提交
200 201
        INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL);
        INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0,
S
sun_fan 已提交
202 203
            FreeCmd(&ctx); return NULL);
        ctx->argc = index + 1;
Z
zhong_ning 已提交
204
    }
S
sun_fan 已提交
205

Z
zhong_ning 已提交
206 207 208 209 210 211 212
    ctx->argv[ctx->argc] = NULL;
    return ctx;
}

void FreeCmd(struct CmdArgs **cmd)
{
    struct CmdArgs *tmpCmd = *cmd;
Z
zhong_ning 已提交
213
    INIT_CHECK_ONLY_RETURN(tmpCmd != NULL);
Z
zhong_ning 已提交
214
    for (int i = 0; i < tmpCmd->argc; ++i) {
Z
zhong_ning 已提交
215
        INIT_CHECK(tmpCmd->argv[i] == NULL, free(tmpCmd->argv[i]));
Z
zhong_ning 已提交
216
    }
Z
zhong_ning 已提交
217
    INIT_CHECK(tmpCmd->argv == NULL, free(tmpCmd->argv));
Z
zhong_ning 已提交
218 219 220 221
    free(tmpCmd);
    return;
}

Z
zhong_ning 已提交
222 223
#define EXTRACT_ARGS(cmdname, cmdContent, args) \
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", args); \
S
sun_fan 已提交
224
    if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != args)) { \
Z
zhong_ning 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
        INIT_LOGE("Command \"%s\" with invalid arguments: %s", #cmdname, cmdContent); \
        goto out; \
    } \

static void DoSetDomainname(const char *cmdContent, int maxArg)
{
    EXTRACT_ARGS(domainname, cmdContent, maxArg)
    int fd = open("/proc/sys/kernel/domainname", O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC,
        S_IRUSR | S_IWUSR);
    if (fd < 0) {
        INIT_LOGE("DoSetDomainame failed to open \"/proc/sys/kernel/domainname\". 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/domainname\". err = %d", errno);
    }

S
sun_fan 已提交
245 246
    close(fd);
    fd = -1;
Z
zhong_ning 已提交
247 248
out:
    FreeCmd(&ctx);
S
sun_fan 已提交
249
    fd = -1;
Z
zhong_ning 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    return;
}

static void DoSetHostname(const char *cmdContent, int maxArg)
{
    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);
    }

S
sun_fan 已提交
269 270
    close(fd);
    fd = -1;
Z
zhong_ning 已提交
271 272
out:
    FreeCmd(&ctx);
S
sun_fan 已提交
273
    fd = -1;
Z
zhong_ning 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    return;
}

#ifndef OHOS_LITE
static void DoIfup(const char *cmdContent, int maxArg)
{
    EXTRACT_ARGS(ifup, cmdContent, maxArg)
    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");
        goto out;
    }

    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;
    }

    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;
    }
    interface.ifr_flags |= IFF_UP;

    if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) {
        INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
    }

S
sun_fan 已提交
306 307
    close(fd);
    fd = -1;
Z
zhong_ning 已提交
308 309
out:
    FreeCmd(&ctx);
S
sun_fan 已提交
310
    fd = -1;
Z
zhong_ning 已提交
311 312 313 314
    return;
}
#endif

Z
zhong_ning 已提交
315
static void DoSleep(const char *cmdContent, int maxArg)
W
wenjun 已提交
316
{
Z
zhong_ning 已提交
317 318 319
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
        INIT_LOGE("DoSleep invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
320 321 322 323
        goto out;
    }

    errno = 0;
Z
zhong_ning 已提交
324
    unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE);
Z
zhong_ning 已提交
325 326 327 328 329 330
    if (errno != 0) {
        INIT_LOGE("cannot covert sleep time in command \" sleep \"");
        goto out;
    }

    // Limit sleep time in 5 seconds
Z
zhong_ning 已提交
331 332 333
    const unsigned long sleepTimeLimit = 5;
    if (sleepTime > sleepTimeLimit) {
        sleepTime = sleepTimeLimit;
Z
zhong_ning 已提交
334 335 336 337 338 339 340 341
    }
    INIT_LOGI("Sleeping %d second(s)", sleepTime);
    sleep((unsigned int)sleepTime);
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
342
static void DoStart(const char* cmdContent, int maxArg)
W
wenjun 已提交
343
{
Z
zhong_ning 已提交
344 345 346 347 348 349
    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);
W
wenjun 已提交
350
    StartServiceByName(cmdContent);
Z
zhong_ning 已提交
351 352 353
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
354 355
}

Z
zhong_ning 已提交
356
static void DoStop(const char* cmdContent, int maxArg)
W
wenjun 已提交
357
{
Z
zhong_ning 已提交
358 359 360 361 362 363
    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);
Z
zhong_ning 已提交
364
    StopServiceByName(cmdContent);
Z
zhong_ning 已提交
365 366 367
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
368 369
}

Z
zhong_ning 已提交
370
static void DoReset(const char* cmdContent, int maxArg)
W
wenjun 已提交
371
{
Z
zhong_ning 已提交
372 373 374 375 376 377 378 379 380 381 382
    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;
Z
zhong_ning 已提交
383
}
W
wenjun 已提交
384

Z
zhong_ning 已提交
385
static void DoCopy(const char* cmdContent, int maxArg)
Z
zhong_ning 已提交
386 387 388 389 390 391
{
    int srcFd = -1;
    int dstFd = -1;
    int rdLen = 0;
    int rtLen = 0;
    char buf[MAX_COPY_BUF_SIZE] = {0};
S
sun_fan 已提交
392 393
    char *realPath1 = NULL;
    char *realPath2 = NULL;
Z
zhong_ning 已提交
394 395
    mode_t mode = 0;
    struct stat fileStat = {0};
Z
zhong_ning 已提交
396
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
S
sun_fan 已提交
397 398
    if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argv[1] == NULL ||
        ctx->argc != DEFAULT_COPY_ARGS_CNT) {
Z
zhong_ning 已提交
399
        INIT_LOGE("DoCopy invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
400 401
        goto out;
    }
S
sun_fan 已提交
402 403 404 405 406 407 408 409 410
    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);
Z
zhong_ning 已提交
411 412
    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 ");
Z
zhong_ning 已提交
413
    mode = fileStat.st_mode;
S
sun_fan 已提交
414
    dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode);
Z
zhong_ning 已提交
415
    INIT_ERROR_CHECK(dstFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[1], errno);
Z
zhong_ning 已提交
416 417
    while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) {
        rtLen = write(dstFd, buf, rdLen);
Z
zhong_ning 已提交
418
        INIT_ERROR_CHECK(rtLen == rdLen, goto out, "write %s file fail %d! ", ctx->argv[1], errno);
Z
zhong_ning 已提交
419 420 421 422 423
    }
    fsync(dstFd);
out:
    FreeCmd(&ctx);
    ctx = NULL;
Z
zhong_ning 已提交
424 425 426 427
    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);
Z
zhong_ning 已提交
428 429 430
    return;
}

Z
zhong_ning 已提交
431
static void DoChown(const char* cmdContent, int maxArg)
Z
zhong_ning 已提交
432 433
{
    // format: chown owner group /xxx/xxx/xxx
Z
zhong_ning 已提交
434 435
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
436
        INIT_LOGE("DoChown invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
437 438 439
        goto out;
    }

Z
zhong_ning 已提交
440 441
    uid_t owner = DecodeUid(ctx->argv[0]);
    INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoChown invalid uid :%s.", ctx->argv[0]);
W
wenjun 已提交
442

Z
zhong_ning 已提交
443 444
    gid_t group = DecodeUid(ctx->argv[1]);
    INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoChown invalid gid :%s.", ctx->argv[1]);
W
wenjun 已提交
445

Z
zhong_ning 已提交
446 447
    int pathPos = 2;
    if (chown(ctx->argv[pathPos], owner, group) != 0) {
Z
zhong_ning 已提交
448
        INIT_LOGE("DoChown, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
449
    }
Z
zhong_ning 已提交
450 451 452
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
453 454
}

Z
zhong_ning 已提交
455
static void DoMkDir(const char* cmdContent, int maxArg)
W
wenjun 已提交
456
{
Z
zhong_ning 已提交
457 458 459 460
    // mkdir support format:
    //    1.mkdir path
    //    2.mkdir path mode
    //    3.mkdir path mode owner group
Z
zhong_ning 已提交
461
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
Z
zhong_ning 已提交
462
    if (ctx == NULL || ctx->argv == NULL || ctx->argc < 1) {
Z
zhong_ning 已提交
463
        INIT_LOGE("DoMkDir invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
464 465 466
        goto out;
    }

Z
zhong_ning 已提交
467 468
    const int withModeArg = 2;
    if (ctx->argc != 1 && ctx->argc != maxArg && ctx->argc != withModeArg) {
Z
zhong_ning 已提交
469
        INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent);
Z
zhong_ning 已提交
470
        goto out;
W
wenjun 已提交
471 472
    }

Z
zhong_ning 已提交
473 474 475
    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);
Z
zhong_ning 已提交
476 477 478
        goto out;
    }

Z
zhong_ning 已提交
479 480 481
    if (ctx->argc > 1) {
        mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE);
        if (chmod(ctx->argv[0], mode) != 0) {
Z
zhong_ning 已提交
482
            INIT_LOGE("DoMkDir failed for %s, err %d.", cmdContent, errno);
Z
zhong_ning 已提交
483
        }
Z
zhong_ning 已提交
484 485 486
        if (ctx->argc == withModeArg) {
            goto out;
        }
S
sun_fan 已提交
487 488
        const int ownerPos = 2;
        const int groupPos = 3;
Z
zhong_ning 已提交
489 490 491 492 493 494 495 496 497

        uid_t owner = DecodeUid(ctx->argv[ownerPos]);
        INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoMkDir invalid uid :%s.", ctx->argv[ownerPos]);

        gid_t group = DecodeUid(ctx->argv[groupPos]);
        INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "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);
W
wenjun 已提交
498
        }
Z
zhong_ning 已提交
499 500 501 502 503 504
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
505
static void DoChmod(const char* cmdContent, int maxArg)
Z
zhong_ning 已提交
506 507
{
    // format: chmod xxxx /xxx/xxx/xxx
Z
zhong_ning 已提交
508 509
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
510
        INIT_LOGE("DoChmod invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
511
        goto out;
W
wenjun 已提交
512 513
    }

Z
zhong_ning 已提交
514 515
    mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE);
    if (mode == 0) {
Z
zhong_ning 已提交
516
        INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno);
Z
zhong_ning 已提交
517 518 519 520
        goto out;
    }

    if (chmod(ctx->argv[1], mode) != 0) {
Z
zhong_ning 已提交
521
        INIT_LOGE("DoChmod, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
522
    }
Z
zhong_ning 已提交
523 524 525
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
526 527 528 529 530
}

static char* CopySubStr(const char* srcStr, size_t startPos, size_t endPos)
{
    if (endPos <= startPos) {
Z
zhong_ning 已提交
531
        INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr);
W
wenjun 已提交
532 533 534 535 536 537
        return NULL;
    }

    size_t mallocLen = endPos - startPos + 1;
    char* retStr = (char*)malloc(mallocLen);
    if (retStr == NULL) {
Z
zhong_ning 已提交
538
        INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr);
W
wenjun 已提交
539 540 541 542 543
        return NULL;
    }

    const char* copyStart = srcStr + startPos;
    if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) {
Z
zhong_ning 已提交
544
        INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr);
W
wenjun 已提交
545 546 547 548 549 550 551 552 553 554 555 556
        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;
}

Z
zhong_ning 已提交
557
static int GetMountFlag(unsigned long* mountflags, const char* targetStr, const char *source)
W
wenjun 已提交
558 559 560 561 562 563 564
{
    if (targetStr == NULL) {
        return 0;
    }

    if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) {
        (*mountflags) |= MS_NODEV;
G
Gymee 已提交
565
    } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) {
W
wenjun 已提交
566
        (*mountflags) |= MS_NOEXEC;
G
Gymee 已提交
567
    } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) {
W
wenjun 已提交
568
        (*mountflags) |= MS_NOSUID;
G
Gymee 已提交
569
    } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) {
W
wenjun 已提交
570
        (*mountflags) |= MS_RDONLY;
Z
zhong_ning 已提交
571 572 573
    } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) {
        (*mountflags) |= MS_NOATIME;
    } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) {
Z
zhong_ning 已提交
574
        WaitForFile(source, WAIT_MAX_COUNT);
G
Gymee 已提交
575 576
    } else {
        return 0;
W
wenjun 已提交
577
    }
G
Gymee 已提交
578
    return 1;
W
wenjun 已提交
579 580 581 582
}

static int CountSpaces(const char* cmdContent, size_t* spaceCnt, size_t* spacePosArr, size_t spacePosArrLen)
{
M
mamingshuai 已提交
583 584
    *spaceCnt = 0;
    size_t strLen = strlen(cmdContent);
W
wenjun 已提交
585
    for (size_t i = 0; i < strLen; ++i) {
M
mamingshuai 已提交
586 587 588
        if (cmdContent[i] == ' ') {
            ++(*spaceCnt);
            if ((*spaceCnt) > spacePosArrLen) {
Z
zhong_ning 已提交
589
                INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent);
M
mamingshuai 已提交
590 591 592
                return 0;
            }
            spacePosArr[(*spaceCnt) - 1] = i;
W
wenjun 已提交
593 594 595
        }
    }

M
mamingshuai 已提交
596 597 598
    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
Z
zhong_ning 已提交
599
        INIT_LOGE("DoMount, bad format for %s.", cmdContent);
W
wenjun 已提交
600 601 602 603
        return 0;
    }

    // spaces should not be adjacent
M
mamingshuai 已提交
604 605
    for (size_t i = 1; i < (*spaceCnt); ++i) {
        if (spacePosArr[i] == spacePosArr[i - 1] + 1) {
Z
zhong_ning 已提交
606
            INIT_LOGE("DoMount, bad format for %s.", cmdContent);
W
wenjun 已提交
607 608 609 610 611 612
            return 0;
        }
    }
    return 1;
}

Z
zhong_ning 已提交
613
static void DoMount(const char* cmdContent, int maxArg)
W
wenjun 已提交
614 615 616 617 618 619 620
{
    size_t spaceCnt = 0;
    size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = {0};
    if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) {
        return;
    }

621 622 623
    // format: fileSystemType source target mountFlag1 mountFlag2... data
    unsigned long mountflags = 0;
    size_t strLen = strlen(cmdContent);
W
wenjun 已提交
624 625
    size_t indexOffset = 0;
    char* fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]);
M
mamingshuai 已提交
626 627 628 629
    if (fileSysType == NULL) {
        return;
    }

W
wenjun 已提交
630
    char* source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]);
M
mamingshuai 已提交
631 632 633 634
    if (source == NULL) {
        free(fileSysType);
        return;
    }
W
wenjun 已提交
635 636 637 638 639
    ++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);
M
mamingshuai 已提交
640 641 642 643 644
    if (target == NULL) {
        free(fileSysType);
        free(source);
        return;
    }
W
wenjun 已提交
645 646 647 648 649 650
    ++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);
Z
zhong_ning 已提交
651
        int ret = GetMountFlag(&mountflags, tmpStr, source);
W
wenjun 已提交
652 653 654 655 656 657 658 659 660 661
        free(tmpStr);
        tmpStr = NULL;

        // get flag failed, the rest part of string will be data
        if (ret == 0) {
            break;
        }
        ++indexOffset;
    }

M
mamingshuai 已提交
662 663 664
    int mountRet;
    if (indexOffset >= spaceCnt) {    // no data
        mountRet = mount(source, target, fileSysType, mountflags, NULL);
W
wenjun 已提交
665
    } else {
M
mamingshuai 已提交
666 667 668 669 670
        const char* dataStr = cmdContent + spacePosArr[indexOffset] + 1;
        mountRet = mount(source, target, fileSysType, mountflags, dataStr);
    }

    if (mountRet != 0) {
Z
zhong_ning 已提交
671
        INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
672 673 674 675 676 677 678
    }

    free(fileSysType);
    free(source);
    free(target);
}

Z
zhong_ning 已提交
679
#ifndef OHOS_LITE
L
leon 已提交
680
#define OPTIONS_SIZE 128u
L
leon 已提交
681 682 683 684 685 686
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) {
Z
zhong_ning 已提交
687
                return;
L
leon 已提交
688
            }
L
leon 已提交
689
        } else if (secondPtr != NULL) {
L
leon 已提交
690
            if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) {
Z
zhong_ning 已提交
691
                return;
L
leon 已提交
692 693 694 695
            }
        }
    } else { // Only restPtr is option
        if (restPtr != NULL) {
Z
zhong_ning 已提交
696
            if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) {
Z
zhong_ning 已提交
697
                return;
Z
zhong_ning 已提交
698
            }
L
leon 已提交
699 700
        }
    }
S
sun_fan 已提交
701
    if (fileName == NULL) {
Z
zhong_ning 已提交
702
        return;
Z
zhong_ning 已提交
703
    }
S
sun_fan 已提交
704
    char *realPath = realpath(fileName, NULL);
Z
zhong_ning 已提交
705 706 707 708
    if (realPath == NULL) {
        return;
    }
    int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
L
leon 已提交
709
    if (fd < 0) {
Z
zhong_ning 已提交
710
        INIT_LOGE("failed to open %s: %d", realPath, errno);
Z
zhong_ning 已提交
711
        free(realPath);
S
sun_fan 已提交
712
        realPath = NULL;
Z
zhong_ning 已提交
713
        return;
L
leon 已提交
714 715 716
    }
    int rc = syscall(__NR_finit_module, fd, options, flags);
    if (rc == -1) {
Z
zhong_ning 已提交
717
        INIT_LOGE("finit_module for %s failed: %d", realPath, errno);
L
leon 已提交
718
    }
Z
zhong_ning 已提交
719
    if (fd >= 0) {
L
leon 已提交
720 721
        close(fd);
    }
Z
zhong_ning 已提交
722
    free(realPath);
S
sun_fan 已提交
723
    realPath = NULL;
L
leon 已提交
724 725 726
    return;
}

Z
zhong_ning 已提交
727
// format insmod <ko name> [-f] [options]
Z
zhong_ning 已提交
728
static void DoInsmod(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
729 730 731 732
{
    char *p = NULL;
    char *restPtr = NULL;
    char *fileName = NULL;
L
leon 已提交
733
    char *line = NULL;
Z
zhong_ning 已提交
734 735 736 737
    int flags = 0;

    size_t count = strlen(cmdContent);
    if (count > OPTIONS_SIZE) {
Z
zhong_ning 已提交
738
        INIT_LOGE("DoInsmod options too long, maybe lost some of options");
Z
zhong_ning 已提交
739 740 741
    }
    line = (char *)malloc(count + 1);
    if (line == NULL) {
Z
zhong_ning 已提交
742
        INIT_LOGE("DoInsmod allocate memory failed.");
Z
zhong_ning 已提交
743 744
        return;
    }
L
leon 已提交
745

S
sun_fan 已提交
746
    if (memcpy_s(line, count + 1, cmdContent, count) != EOK) {
Z
zhong_ning 已提交
747
        INIT_LOGE("DoInsmod memcpy failed");
Z
zhong_ning 已提交
748
        free(line);
L
leon 已提交
749
        return;
Z
zhong_ning 已提交
750 751 752 753
    }
    line[count] = '\0';
    do {
        if ((p = strtok_r(line, " ", &restPtr)) == NULL) {
Z
zhong_ning 已提交
754
            INIT_LOGE("DoInsmod cannot get filename.");
Z
zhong_ning 已提交
755
            free(line);
Z
zhong_ning 已提交
756 757 758
            return;
        }
        fileName = p;
Z
zhong_ning 已提交
759
        INIT_LOGI("DoInsmod fileName is [%s].", fileName);
Z
zhong_ning 已提交
760 761 762 763 764 765 766
        if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) {
            break;
        }
        if (!strcmp(p, "-f")) {
            flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
        }
    } while (0);
L
leon 已提交
767
    DoInsmodInternal(fileName, p, restPtr, flags);
Z
zhong_ning 已提交
768 769 770
    if (line != NULL) {
        free(line);
    }
L
leon 已提交
771
    return;
Z
zhong_ning 已提交
772
}
Z
zhong_ning 已提交
773

Z
zhong_ning 已提交
774
static void DoSetParam(const char* cmdContent, int maxArg)
Z
zhong_ning 已提交
775
{
Z
zhong_ning 已提交
776 777 778
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
        INIT_LOGE("DoSetParam invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
779 780
        goto out;
    }
Z
zhong_ning 已提交
781
    INIT_LOGE("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
Z
zhong_ning 已提交
782
    SystemWriteParam(ctx->argv[0], ctx->argv[1]);
Z
zhong_ning 已提交
783 784 785 786 787
out:
    FreeCmd(&ctx);
    return;
}

L
leon 已提交
788
#endif // OHOS_LITE
Z
zhong_ning 已提交
789

M
mamingshuai 已提交
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
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;
        }
    }
    return false;
}

Z
zhong_ning 已提交
807
static void DoLoadCfg(const char *path, int maxArg)
M
mamingshuai 已提交
808 809 810 811 812 813
{
    char buf[LOADCFG_BUF_SIZE] = {0};
    FILE *fp = NULL;
    size_t maxLoop = 0;
    CmdLine *cmdLine = NULL;
    int len;
Z
zhong_ning 已提交
814
    INIT_CHECK_ONLY_RETURN(path != NULL);
Z
zhong_ning 已提交
815
    INIT_LOGI("DoLoadCfg cfg file %s", path);
M
mamingshuai 已提交
816
    if (!CheckValidCfg(path)) {
Z
zhong_ning 已提交
817
        INIT_LOGE("CheckCfg file %s Failed", path);
M
mamingshuai 已提交
818 819
        return;
    }
Z
zhong_ning 已提交
820
    INIT_ERROR_CHECK(path != NULL, return, "CheckCfg path is NULL.");
S
sun_fan 已提交
821
    char *realPath = realpath(path, NULL);
Z
zhong_ning 已提交
822
    INIT_CHECK_ONLY_RETURN(realPath != NULL);
S
sun_fan 已提交
823
    fp = fopen(realPath, "r");
M
mamingshuai 已提交
824
    if (fp == NULL) {
Z
zhong_ning 已提交
825
        INIT_LOGE("open cfg error = %d", errno);
S
sun_fan 已提交
826 827
        free(realPath);
        realPath = NULL;
M
mamingshuai 已提交
828 829 830 831 832
        return;
    }

    cmdLine = (CmdLine *)malloc(sizeof(CmdLine));
    if (cmdLine == NULL) {
Z
zhong_ning 已提交
833
        INIT_LOGE("malloc cmdline error");
M
mamingshuai 已提交
834
        fclose(fp);
S
sun_fan 已提交
835 836
        free(realPath);
        realPath = NULL;
M
mamingshuai 已提交
837 838 839
        return;
    }

S
sun_fan 已提交
840
    while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) {
M
mamingshuai 已提交
841 842 843 844 845 846 847 848 849 850 851 852 853
        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);
    }
S
sun_fan 已提交
854 855
    free(realPath);
    realPath = NULL;
M
mamingshuai 已提交
856 857 858 859
    free(cmdLine);
    fclose(fp);
}

Z
zhong_ning 已提交
860
static void DoWrite(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
861 862
{
    // format: write path content
Z
zhong_ning 已提交
863 864
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
865
        INIT_LOGE("DoWrite: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
866 867
        goto out;
    }
S
sun_fan 已提交
868 869 870 871
    char *realPath = realpath(ctx->argv[0], NULL);
    if (realPath == NULL) {
        goto out;
    }
Z
zhong_ning 已提交
872
    int fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
Z
zhong_ning 已提交
873
    if (fd == -1) {
Z
zhong_ning 已提交
874
        INIT_LOGE("DoWrite: open %s failed: %d", ctx->argv[0], errno);
S
sun_fan 已提交
875 876
        free(realPath);
        realPath = NULL;
Z
zhong_ning 已提交
877 878 879 880 881
        goto out;
    }

    size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1]));
    if (ret < 0) {
Z
zhong_ning 已提交
882
        INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno);
S
sun_fan 已提交
883 884
        free(realPath);
        realPath = NULL;
Z
zhong_ning 已提交
885 886 887
        close(fd);
        goto out;
    }
S
sun_fan 已提交
888 889
    free(realPath);
    realPath = NULL;
Z
zhong_ning 已提交
890 891 892 893 894 895
    close(fd);
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
896
static void DoRmdir(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
897 898
{
    // format: rmdir path
Z
zhong_ning 已提交
899 900
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
901
        INIT_LOGE("DoRmdir: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
902 903 904 905 906
        goto out;
    }

    int ret = rmdir(ctx->argv[0]);
    if (ret == -1) {
Z
zhong_ning 已提交
907
        INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno);
Z
zhong_ning 已提交
908 909 910 911 912 913 914
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
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("DoReboot invalid arguments :%s", cmdContent);
        goto out;
    }
    DoReboot(cmdContent);
out:
    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("DoLoadPersistParams invalid arguments :%s", cmdContent);
        goto out;
    }
    INIT_LOGD("load persist params : %s", cmdContent);
    LoadPersistParams();
out:
    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("DoTrigger invalid arguments :%s", cmdContent);
        goto out;
    }
    INIT_LOGD("DoTrigger :%s", cmdContent);
    DoTriggerExec(cmdContent);
out:
    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("DoLoadDefaultParams invalid arguments :%s", cmdContent);
        goto out;
    }
    INIT_LOGD("load persist params : %s", cmdContent);
    LoadDefaultParams(cmdContent);
out:
    FreeCmd(&ctx);
    return;
}

static void DoSetrlimit(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
971 972 973 974 975 976 977
{
    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
Z
zhong_ning 已提交
978
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
S
sun_fan 已提交
979
    const int rlimMaxPos = 2;
Z
zhong_ning 已提交
980
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
981
        INIT_LOGE("DoSetrlimit: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
982 983 984 985
        goto out;
    }

    struct rlimit limit;
S
sun_fan 已提交
986
    limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]);
Z
zhong_ning 已提交
987
    limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]);
Z
zhong_ning 已提交
988 989 990 991 992 993 994
    int rcs = -1;
    for (unsigned int i = 0 ; i < sizeof(resource) / sizeof(char*); ++i) {
        if (strcmp(ctx->argv[0], resource[i]) == 0) {
            rcs = (int)i;
        }
    }
    if (rcs == -1) {
Z
zhong_ning 已提交
995
        INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]);
Z
zhong_ning 已提交
996 997 998 999
        goto out;
    }
    int ret = setrlimit(rcs, &limit);
    if (ret) {
Z
zhong_ning 已提交
1000
        INIT_LOGE("DoSetrlimit failed : %d", errno);
Z
zhong_ning 已提交
1001 1002 1003 1004 1005 1006 1007
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
1008
static void DoRm(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1009 1010
{
    // format: rm /xxx/xxx/xxx
Z
zhong_ning 已提交
1011 1012
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
1013
        INIT_LOGE("DoRm: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1014 1015 1016 1017
        goto out;
    }
    int ret = unlink(ctx->argv[0]);
    if (ret == -1) {
Z
zhong_ning 已提交
1018
        INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno);
Z
zhong_ning 已提交
1019 1020 1021 1022 1023 1024 1025
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
1026
static void DoExport(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1027 1028
{
    // format: export xxx /xxx/xxx/xxx
Z
zhong_ning 已提交
1029 1030
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
1031
        INIT_LOGE("DoExport: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1032 1033 1034 1035
        goto out;
    }
    int ret = setenv(ctx->argv[0], ctx->argv[1], 1);
    if (ret != 0) {
Z
zhong_ning 已提交
1036
        INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
Z
zhong_ning 已提交
1037 1038 1039 1040 1041 1042 1043
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
1044
static void DoExec(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1045 1046 1047
{
    // format: exec /xxx/xxx/xxx xxx
    pid_t pid = fork();
Z
zhong_ning 已提交
1048
    if (pid < 0) {
Z
zhong_ning 已提交
1049
        INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
Z
zhong_ning 已提交
1050 1051
        return;
    }
Z
zhong_ning 已提交
1052
    if (pid == 0) {
Z
zhong_ning 已提交
1053
        struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
S
sun_fan 已提交
1054
        if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) {
Z
zhong_ning 已提交
1055
            INIT_LOGE("DoExec: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1056 1057
            _exit(0x7f);
        }
Z
zhong_ning 已提交
1058 1059 1060 1061 1062 1063
#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) {
Z
zhong_ning 已提交
1064
            INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
Z
zhong_ning 已提交
1065
        }
Z
zhong_ning 已提交
1066 1067
        FreeCmd(&ctx);
        _exit(0x7f);
Z
zhong_ning 已提交
1068 1069 1070 1071 1072
    }
    return;
}

#ifndef __LITEOS__
Z
zhong_ning 已提交
1073
static void DoSymlink(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1074 1075
{
    // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
Z
zhong_ning 已提交
1076 1077
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
1078
        INIT_LOGE("DoSymlink: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1079 1080 1081 1082 1083
        goto out;
    }

    int ret = symlink(ctx->argv[0], ctx->argv[1]);
    if (ret != 0) {
Z
zhong_ning 已提交
1084
        INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
Z
zhong_ning 已提交
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
        goto out;
    }
out:
    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;
    }
}

Z
zhong_ning 已提交
1109
static void DoMakeNode(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1110 1111
{
    // format: mknod path b 0644 1 9
Z
zhong_ning 已提交
1112
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
S
sun_fan 已提交
1113 1114 1115 1116 1117 1118
    const int deviceTypePos = 1;
    const int authorityPos = 2;
    const int majorDevicePos = 3;
    const int minorDevicePos = 4;
    const int decimal = 10;
    const int octal = 8;
Z
zhong_ning 已提交
1119
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
1120
        INIT_LOGE("DoMakeNode: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1121 1122 1123 1124
        goto out;
    }

    if (!access(ctx->argv[1], F_OK)) {
Z
zhong_ning 已提交
1125
        INIT_LOGE("DoMakeNode failed, path has not sexisted");
Z
zhong_ning 已提交
1126 1127 1128 1129 1130 1131 1132 1133 1134
        goto out;
    }
    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) {
Z
zhong_ning 已提交
1135
        INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
Z
zhong_ning 已提交
1136 1137 1138 1139 1140 1141 1142
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
1143
static void DoMakeDevice(const char *cmdContent, int maxArg)
Z
zhong_ning 已提交
1144 1145
{
    // format: makedev major minor
Z
zhong_ning 已提交
1146
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
S
sun_fan 已提交
1147
    const int decimal = 10;
Z
zhong_ning 已提交
1148
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
Z
zhong_ning 已提交
1149
        INIT_LOGE("DoMakedevice: invalid arguments :%s", cmdContent);
Z
zhong_ning 已提交
1150 1151 1152 1153 1154 1155
        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) {
Z
zhong_ning 已提交
1156
        INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno);
Z
zhong_ning 已提交
1157 1158 1159 1160 1161 1162 1163 1164
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}
#endif // __LITEOS__

W
wenjun 已提交
1165 1166
void DoCmd(const CmdLine* curCmd)
{
Z
zhong_ning 已提交
1167 1168
    // null curCmd or empty command, just quit.
    if (curCmd == NULL || curCmd->name[0] == '\0') {
W
wenjun 已提交
1169 1170
        return;
    }
Z
zhong_ning 已提交
1171 1172
    DoCmdByName(curCmd->name, curCmd->cmdContent);
}
W
wenjun 已提交
1173

Z
zhong_ning 已提交
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
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 ", 1, DoLoadDefaultParams },
Z
zhong_ning 已提交
1201
    { "ifup ", 1, DoIfup },
Z
zhong_ning 已提交
1202 1203 1204 1205 1206 1207
#endif
    { "stop ", 1, DoStop },
    { "reset ", 1, DoReset },
    { "copy ", 2, DoCopy },
    { "reboot ", 1, DoRebootCmd },
    { "setrlimit ", 3, DoSetrlimit },
Z
zhong_ning 已提交
1208 1209 1210
    { "sleep ", 1, DoSleep },
    { "hostname ", 1, DoSetHostname },
    { "domainname ", 1, DoSetDomainname }
Z
zhong_ning 已提交
1211 1212
};

Z
zhong_ning 已提交
1213 1214 1215 1216 1217
void DoCmdByName(const char *name, const char *cmdContent)
{
    if (name == NULL || cmdContent == NULL) {
        return;
    }
Z
zhong_ning 已提交
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227

    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;
        }
    }
    if (i == cmdCnt) {
Z
zhong_ning 已提交
1228
        INIT_LOGE("DoCmd, unknown cmd name %s.", name);
W
wenjun 已提交
1229 1230
    }
}
M
mamingshuai 已提交
1231

Z
zhong_ning 已提交
1232 1233 1234 1235 1236
const char *GetMatchCmd(const char *cmdStr)
{
    if (cmdStr == NULL) {
        return NULL;
    }
Z
zhong_ning 已提交
1237
    size_t supportCmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]);
Z
zhong_ning 已提交
1238
    for (size_t i = 0; i < supportCmdCnt; ++i) {
Z
zhong_ning 已提交
1239 1240 1241
        size_t curCmdNameLen = strlen(CMD_TABLE[i].name);
        if (strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) {
            return CMD_TABLE[i].name;
Z
zhong_ning 已提交
1242 1243 1244 1245
        }
    }
    return NULL;
}
Z
zhong_ning 已提交
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281

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));
    }
}