init_cmds.c 9.8 KB
Newer Older
1
/*
Z
zhong_ning 已提交
2
 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "init_cmds.h"

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/wait.h>
#include <unistd.h>

4
411148299@qq.com 已提交
34
#include <linux/module.h>
S
sun_fan 已提交
35
#include "fs_manager/fs_manager.h"
36
#include "init.h"
Z
zhong_ning 已提交
37
#include "init_jobs_internal.h"
38 39 40 41 42 43 44 45
#include "init_log.h"
#include "init_param.h"
#include "init_service_manager.h"
#include "init_utils.h"
#include "securec.h"

int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
{
X
add ut  
xionglei6 已提交
46
    INIT_CHECK_RETURN_VALUE((symValue != NULL) && (paramValue != NULL) && (paramLen != 0), -1);
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
    char tmpName[PARAM_NAME_LEN_MAX] = { 0 };
    int ret = 0;
    uint32_t curr = 0;
    char *start = (char *)symValue;
    char *end = (char *)symValue + symLen;
    do {
        char *begin = strchr(start, '$');
        if (begin == NULL || begin >= end) { // not has '$' copy the original string
            ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen);
            INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start);
            break;
        } else {
            ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start);
            INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue);
            curr += begin - start;
        }
        while (*begin != '{') {
            begin++;
        }
        begin++;
        char *left = strchr(begin, '}');
X
add ut  
xionglei6 已提交
68 69
        INIT_CHECK_RETURN_VALUE(left != NULL, -1);

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
        // copy param name
        ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, left - begin);
        INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue);
        uint32_t valueLen = paramLen - curr;
        ret = SystemReadParam(tmpName, paramValue + curr, &valueLen);
        INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName);
        curr += valueLen;
        left++;
        if ((unsigned int)(left - symValue) >= symLen) {
            break;
        }
        start = left;
    } while (1);
    return 0;
}

X
add ut  
xionglei6 已提交
86
static void DoIfup(const struct CmdArgs *ctx)
87 88
{
    struct ifreq interface;
X
add ut  
xionglei6 已提交
89 90
    INIT_ERROR_CHECK(strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) == EOK,
        return, "DoIfup failed to copy interface name");
91
    INIT_LOGD("interface name: %s", interface.ifr_name);
X
add ut  
xionglei6 已提交
92

93
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
X
add ut  
xionglei6 已提交
94
    INIT_ERROR_CHECK(fd >= 0, return, "DoIfup failed to create socket, err = %d", errno);
95 96 97

    if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) {
        interface.ifr_flags |= IFF_UP;
X
add ut  
xionglei6 已提交
98 99
        INIT_CHECK_ONLY_ELOG(ioctl(fd, SIOCSIFFLAGS, &interface) >= 0,
            "DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
100 101
    }
    close(fd);
X
add ut  
xionglei6 已提交
102
    fd = -1;
103 104 105
}

// format insmod <ko name> [-f] [options]
X
add ut  
xionglei6 已提交
106
static void DoInsmod(const struct CmdArgs *ctx)
107 108 109 110 111 112 113 114
{
    int index = 0;
    int flags = 0;
    char *fileName = NULL;
    if (ctx->argc > index) {
        fileName = ctx->argv[index];
        index++;
    }
X
add ut  
xionglei6 已提交
115
    INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", ctx->argv[0]);
116 117
    INIT_LOGD("Install mode %s ", fileName);
    char *realPath = GetRealPath(fileName);
X
add ut  
xionglei6 已提交
118 119
    INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", ctx->argv[0]);
    INIT_CHECK((ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f")) != 0, // [-f]
120
        flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
X
add ut  
xionglei6 已提交
121 122
        index++);

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    char *options = BuildStringFromCmdArg(ctx, index); // [options]
    int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
    if (fd >= 0) {
        int rc = syscall(__NR_finit_module, fd, options, flags);
        if (rc == -1) {
            INIT_LOGE("Failed to install mode for %s failed options %s err: %d", realPath, options, errno);
        }
    }
    if (options != NULL) {
        free(options);
    }
    if (fd >= 0) {
        close(fd);
    }
    free(realPath);
    return;
}

X
add ut  
xionglei6 已提交
141
static void DoSetParam(const struct CmdArgs *ctx)
142 143 144 145 146
{
    INIT_LOGD("set param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
    SystemWriteParam(ctx->argv[0], ctx->argv[1]);
}

X
add ut  
xionglei6 已提交
147
static void DoLoadPersistParams(const struct CmdArgs *ctx)
148
{
X
add ut  
xionglei6 已提交
149
    INIT_LOGD("load persist params : %s", ctx->argv[0]);
150 151 152
    LoadPersistParams();
}

X
add ut  
xionglei6 已提交
153
static void DoTriggerCmd(const struct CmdArgs *ctx)
154
{
X
add ut  
xionglei6 已提交
155 156
    INIT_LOGD("DoTrigger :%s", ctx->argv[0]);
    DoTriggerExec(ctx->argv[0]);
157 158
}

X
add ut  
xionglei6 已提交
159
static void DoLoadDefaultParams(const struct CmdArgs *ctx)
160 161 162 163 164
{
    int mode = 0;
    if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) {
        mode = LOAD_PARAM_ONLY_ADD;
    }
X
add ut  
xionglei6 已提交
165
    INIT_LOGD("DoLoadDefaultParams args : %s %d", ctx->argv[0], mode);
166 167 168
    LoadDefaultParams(ctx->argv[0], mode);
}

X
add ut  
xionglei6 已提交
169
static void DoExec(const struct CmdArgs *ctx)
170 171 172
{
    // format: exec /xxx/xxx/xxx xxx
    pid_t pid = fork();
X
add ut  
xionglei6 已提交
173 174
    INIT_ERROR_CHECK(pid >= 0, return, "DoExec: failed to fork child process to exec \"%s\"", ctx->argv[0]);

175
    if (pid == 0) {
X
add ut  
xionglei6 已提交
176 177 178
        INIT_ERROR_CHECK(ctx != NULL && ctx->argv[0] != NULL, _exit(0x7f),
            "DoExec: invalid arguments to exec \"%s\"", ctx->argv[0]);
        int ret = execv(ctx->argv[0], ctx->argv);
179
        if (ret == -1) {
X
add ut  
xionglei6 已提交
180
            INIT_LOGE("DoExec: execute \"%s\" failed: %d.", ctx->argv[0], errno);
181 182 183 184 185 186
        }
        _exit(0x7f);
    }
    return;
}

X
add ut  
xionglei6 已提交
187
static void DoSymlink(const struct CmdArgs *ctx)
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
{
    // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
    int ret = symlink(ctx->argv[0], ctx->argv[1]);
    if (ret != 0 && errno != EEXIST) {
        INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
    }
}

static mode_t GetDeviceMode(const char *deviceStr)
{
    switch (*deviceStr) {
        case 'b':
        case 'B':
            return S_IFBLK;
        case 'c':
        case 'C':
            return S_IFCHR;
        case 'f':
        case 'F':
            return S_IFIFO;
        default:
            return -1;
    }
}

X
add ut  
xionglei6 已提交
213
static void DoMakeNode(const struct CmdArgs *ctx)
214 215 216 217 218 219 220 221
{
    // format: mknod path b 0644 1 9
    const int deviceTypePos = 1;
    const int authorityPos = 2;
    const int majorDevicePos = 3;
    const int minorDevicePos = 4;
    const int decimal = 10;
    const int octal = 8;
X
add ut  
xionglei6 已提交
222
    INIT_ERROR_CHECK(access(ctx->argv[1], F_OK), return, "DoMakeNode failed, path has sexisted");
223 224 225 226 227 228 229 230 231 232 233 234 235 236
    mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
    errno = 0;
    unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal);
    INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]);
    unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal);
    INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]);
    mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal);
    INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]);
    int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor));
    if (ret != 0) {
        INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
    }
}

X
add ut  
xionglei6 已提交
237
static void DoMakeDevice(const struct CmdArgs *ctx)
238 239 240 241 242 243 244 245 246
{
    // format: makedev major minor
    const int decimal = 10;
    errno = 0;
    unsigned int major = strtoul(ctx->argv[0], NULL, decimal);
    INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]);
    unsigned int minor = strtoul(ctx->argv[1], NULL, decimal);
    INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]);
    dev_t deviceId = makedev(major, minor);
X
add ut  
xionglei6 已提交
247 248 249
    INIT_CHECK_ONLY_ELOG(deviceId >= 0, "DoMakedevice \" major:%s, minor:%s \" failed :%d ", ctx->argv[0],
        ctx->argv[1], errno);
    return;
250 251
}

X
add ut  
xionglei6 已提交
252
static void DoMountFstabFile(const struct CmdArgs *ctx)
253 254
{
    INIT_LOGI("Mount partitions from fstab file \" %s \"", ctx->argv[0]);
S
sun_fan 已提交
255
    (void)MountAllWithFstabFile(ctx->argv[0], 0);
256 257
}

X
add ut  
xionglei6 已提交
258
static void DoUmountFstabFile(const struct CmdArgs *ctx)
259 260 261 262 263 264 265 266 267 268
{
    INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]);
    int rc = UmountAllWithFstabFile(ctx->argv[0]);
    if (rc < 0) {
        INIT_LOGE("Run command umount_fstab failed");
    } else {
        INIT_LOGI("Umount partitions from fstab done");
    }
}

4
411148299@qq.com 已提交
269
static const struct CmdTable g_cmdTable[] = {
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    { "exec ", 1, 10, DoExec },
    { "mknode ", 1, 5, DoMakeNode },
    { "makedev ", 2, 2, DoMakeDevice },
    { "symlink ", 2, 2, DoSymlink },
    { "trigger ", 1, 1, DoTriggerCmd },
    { "insmod ", 1, 10, DoInsmod },
    { "setparam ", 2, 2, DoSetParam },
    { "load_persist_params ", 1, 1, DoLoadPersistParams },
    { "load_param ", 1, 2, DoLoadDefaultParams },
    { "ifup ", 1, 1, DoIfup },
    { "mount_fstab ", 1, 1, DoMountFstabFile },
    { "umount_fstab ", 1, 1, DoUmountFstabFile },
};

const struct CmdTable *GetCmdTable(int *number)
{
4
411148299@qq.com 已提交
286 287
    *number = (int)ARRAY_LENGTH(g_cmdTable);
    return g_cmdTable;
288
}