init_cmds.c 9.9 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
 * 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 <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <stdbool.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 已提交
32
#include <linux/module.h>
S
sun_fan 已提交
33
#include "fs_manager/fs_manager.h"
X
xionglei6 已提交
34
#include "fs_manager/fs_manager_log.h"
Z
zhong_ning 已提交
35
#include "init_jobs_internal.h"
36 37 38 39 40 41 42 43
#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 已提交
44
    INIT_CHECK_RETURN_VALUE((symValue != NULL) && (paramValue != NULL) && (paramLen != 0), -1);
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
    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 已提交
66 67
        INIT_CHECK_RETURN_VALUE(left != NULL, -1);

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        // 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 已提交
84
static void DoIfup(const struct CmdArgs *ctx)
85 86
{
    struct ifreq interface;
X
add ut  
xionglei6 已提交
87 88
    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");
89
    INIT_LOGD("interface name: %s", interface.ifr_name);
X
add ut  
xionglei6 已提交
90

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

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

// format insmod <ko name> [-f] [options]
X
add ut  
xionglei6 已提交
104
static void DoInsmod(const struct CmdArgs *ctx)
105 106 107 108 109 110 111 112
{
    int index = 0;
    int flags = 0;
    char *fileName = NULL;
    if (ctx->argc > index) {
        fileName = ctx->argv[index];
        index++;
    }
X
add ut  
xionglei6 已提交
113
    INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", ctx->argv[0]);
114 115
    INIT_LOGD("Install mode %s ", fileName);
    char *realPath = GetRealPath(fileName);
X
add ut  
xionglei6 已提交
116
    INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", ctx->argv[0]);
X
xionglei6 已提交
117
    if (ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f") == 0) { // [-f]
118
        flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
X
xionglei6 已提交
119 120
        index++;
    }
121 122 123 124 125
    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) {
X
xionglei6 已提交
126
            INIT_LOGE("Failed to install kernel module for %s failed options %s err: %d", realPath, options, errno);
127 128 129 130 131 132 133 134 135 136 137 138
        }
    }
    if (options != NULL) {
        free(options);
    }
    if (fd >= 0) {
        close(fd);
    }
    free(realPath);
    return;
}

X
add ut  
xionglei6 已提交
139
static void DoSetParam(const struct CmdArgs *ctx)
140 141 142 143 144
{
    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 已提交
145
static void DoLoadPersistParams(const struct CmdArgs *ctx)
146
{
X
add ut  
xionglei6 已提交
147
    INIT_LOGD("load persist params : %s", ctx->argv[0]);
148 149 150
    LoadPersistParams();
}

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

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

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

173
    if (pid == 0) {
X
add ut  
xionglei6 已提交
174 175 176
        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);
177
        if (ret == -1) {
X
add ut  
xionglei6 已提交
178
            INIT_LOGE("DoExec: execute \"%s\" failed: %d.", ctx->argv[0], errno);
179 180 181 182 183 184
        }
        _exit(0x7f);
    }
    return;
}

X
add ut  
xionglei6 已提交
185
static void DoSymlink(const struct CmdArgs *ctx)
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
{
    // 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 已提交
211
static void DoMakeNode(const struct CmdArgs *ctx)
212 213 214 215 216 217 218 219
{
    // 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 已提交
220
    INIT_ERROR_CHECK(access(ctx->argv[1], F_OK), return, "DoMakeNode failed, path has sexisted");
221 222 223 224 225 226 227 228 229 230 231 232 233 234
    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 已提交
235
static void DoMakeDevice(const struct CmdArgs *ctx)
236 237 238 239 240 241 242 243 244
{
    // 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 已提交
245 246 247
    INIT_CHECK_ONLY_ELOG(deviceId >= 0, "DoMakedevice \" major:%s, minor:%s \" failed :%d ", ctx->argv[0],
        ctx->argv[1], errno);
    return;
248 249
}

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

X
add ut  
xionglei6 已提交
257
static void DoUmountFstabFile(const struct CmdArgs *ctx)
258 259
{
    INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]);
X
xionglei6 已提交
260
    FsManagerLogInit(LOG_TO_KERNEL, "");
261 262 263 264 265 266 267 268
    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
}