From cd60797dc1cd5eb336796342082d35861b0ba293 Mon Sep 17 00:00:00 2001 From: Mupceet Date: Fri, 29 Apr 2022 14:43:05 +0800 Subject: [PATCH] add: read fstab from cmdline Signed-off-by: Mupceet --- interfaces/innerkits/fs_manager/fstab.c | 32 +++-- .../innerkits/include/fs_manager/fs_manager.h | 3 +- services/init/standard/init.c | 13 +- services/init/standard/init_mount.c | 122 +++++++++++++++++- services/init/standard/init_mount.h | 4 +- 5 files changed, 146 insertions(+), 28 deletions(-) diff --git a/interfaces/innerkits/fs_manager/fstab.c b/interfaces/innerkits/fs_manager/fstab.c index 3d07e44c..c776f0c5 100644 --- a/interfaces/innerkits/fs_manager/fstab.c +++ b/interfaces/innerkits/fs_manager/fstab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -70,10 +70,10 @@ unsigned int ConvertFlags(char *flagBuffer) return flags; } -static void AddToFstab(Fstab *fstab, FstabItem *item) +static int AddToFstab(Fstab *fstab, FstabItem *item) { if (fstab == NULL || item == NULL) { - return; + return -1; } if (fstab->head != NULL) { item->next = fstab->head->next; @@ -81,6 +81,7 @@ static void AddToFstab(Fstab *fstab, FstabItem *item) } else { fstab->head = item; } + return 0; } void ReleaseFstabItem(FstabItem *item) @@ -124,14 +125,18 @@ void ReleaseFstab(Fstab *fstab) } } -static int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts) +int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator) { BEGET_CHECK_RETURN_VALUE(str != NULL && fstab != NULL, -1); - const char *separator = " \t"; char *rest = NULL; FstabItem *item = NULL; char *p = NULL; + if (separator == NULL || *separator == '\0') { + BEGET_LOGE("Invalid separator for parsing fstab"); + return -1; + } + if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) { errno = ENOMEM; BEGET_LOGE("Allocate memory for FS table item failed, err = %d", errno); @@ -174,8 +179,7 @@ static int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts) } else { item->fsManagerFlags = 0; } - AddToFstab(fstab, item); - return 0; + return AddToFstab(fstab, item); } while (0); ReleaseFstabItem(item); @@ -227,7 +231,7 @@ Fstab *ReadFstabFromFile(const char *file, bool procMounts) continue; } - if (ParseFstabPerLine(p, fstab, procMounts) < 0) { + if (ParseFstabPerLine(p, fstab, procMounts, " \t") < 0) { if (errno == ENOMEM) { // Ran out of memory, there is no reason to continue. break; @@ -300,7 +304,7 @@ static char *GetFstabFile(char *fileName, int size) char hardware[MAX_BUFFER_LEN] = {0}; char *buffer = ReadFileData("/proc/cmdline"); if (buffer == NULL) { - BEGET_LOGE("Failed read \"/proc/cmdline\""); + BEGET_LOGE("Failed to read \"/proc/cmdline\""); return NULL; } int ret = GetProcCmdlineValue("hardware", buffer, hardware, MAX_BUFFER_LEN); @@ -310,11 +314,11 @@ static char *GetFstabFile(char *fileName, int size) return NULL; } if (snprintf_s(fileName, size, size - 1, "/vendor/etc/fstab.%s", hardware) == -1) { - BEGET_LOGE("Fail snprintf_s err=%d", errno); + BEGET_LOGE("Failed to build fstab file, err=%d", errno); return NULL; } } - BEGET_LOGI("file is %s", fileName); + BEGET_LOGI("fstab file is %s", fileName); return fileName; } @@ -325,11 +329,11 @@ int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char } FstabItem *item = FindFstabItemForMountPoint(*fstab, mountPoint); if (item == NULL) { - BEGET_LOGE("Failed get fstab item from point \" %s \"", mountPoint); + BEGET_LOGE("Failed to get fstab item from point \" %s \"", mountPoint); return -1; } if (strncpy_s(deviceName, nameLen, item->deviceName, strlen(item->deviceName)) != 0) { - BEGET_LOGE("Failed strncpy_s err=%d", errno); + BEGET_LOGE("Failed to copy block device name, err=%d", errno); return -1; } return 0; @@ -416,7 +420,7 @@ unsigned long GetMountFlags(char *mountFlag, char *fsSpecificData, size_t fsSpec } // Combined each mount flag with ',' if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) { - BEGET_LOGW("Failed to append comma."); + BEGET_LOGW("Failed to append comma"); break; // If cannot add ',' to the end of flags, there is not reason to continue. } } diff --git a/interfaces/innerkits/include/fs_manager/fs_manager.h b/interfaces/innerkits/include/fs_manager/fs_manager.h index 2ce826e7..bb078cf7 100644 --- a/interfaces/innerkits/include/fs_manager/fs_manager.h +++ b/interfaces/innerkits/include/fs_manager/fs_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -60,6 +60,7 @@ void ReleaseFstab(Fstab *fstab); Fstab *ReadFstabFromFile(const char *file, bool procMounts); FstabItem *FindFstabItemForPath(Fstab fstab, const char *path); FstabItem* FindFstabItemForMountPoint(Fstab fstab, const char *mp); +int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator); int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen); bool IsSupportedFilesystem(const char *fsType); diff --git a/services/init/standard/init.c b/services/init/standard/init.c index a35b7ca8..faf8a298 100644 --- a/services/init/standard/init.c +++ b/services/init/standard/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -173,16 +173,9 @@ static int StartUeventd(char **requiredDevices, int num) static void StartInitSecondStage(void) { - const char *fstabFile = "/etc/fstab.required"; - Fstab *fstab = NULL; - if (access(fstabFile, F_OK) != 0) { - fstabFile = "/system/etc/fstab.required"; - } - INIT_ERROR_CHECK(access(fstabFile, F_OK) == 0, abort(), "Failed get fstab.required"); - fstab = ReadFstabFromFile(fstabFile, false); - INIT_ERROR_CHECK(fstab != NULL, abort(), "Read fstab file \" %s \" failed\n", fstabFile); - int requiredNum = 0; + Fstab* fstab = LoadRequiredFstab(); + INIT_ERROR_CHECK(fstab != NULL, abort(), "Failed to load required fstab"); char **devices = GetRequiredDevices(*fstab, &requiredNum); if (devices != NULL && requiredNum > 0) { int ret = StartUeventd(devices, requiredNum); diff --git a/services/init/standard/init_mount.c b/services/init/standard/init_mount.c index 5782dcc7..620b5391 100644 --- a/services/init/standard/init_mount.c +++ b/services/init/standard/init_mount.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,15 +13,133 @@ * limitations under the License. */ +#include "init_mount.h" + +#include +#include #include "fs_manager/fs_manager.h" #include "init_cmds.h" #include "init_log.h" +#include "init_utils.h" +#include "securec.h" int MountRequriedPartitions(const Fstab *fstab) { - INIT_ERROR_CHECK(fstab != NULL, return -1, "Failed fstab is NULL"); + INIT_ERROR_CHECK(fstab != NULL, return -1, "fstab is NULL"); int rc; INIT_LOGI("Mount required partitions"); rc = MountAllWithFstab(fstab, 1); return rc; } + +#define OHOS_REQUIRED_MOUNT_PREFIX "ohos.required_mount." +static int ParseRequiredMountInfo(const char *item, Fstab *fstab) +{ + char mountOptions[MAX_BUFFER_LEN] = {}; + char partName[PARTITION_NAME_SIZE] = {}; + // Sanity checks + if (item == NULL || *item == '\0' || fstab == NULL) { + return -1; + } + + char *p = NULL; + const char *q = item; + if ((p = strstr(item, "=")) != NULL) { + q = item + strlen(OHOS_REQUIRED_MOUNT_PREFIX); // Get partition name + if (q == NULL || *q == '\0' || (p - q) <= 0) { + return -1; + } + if (strncpy_s(partName, PARTITION_NAME_SIZE -1, q, p - q) != EOK) { + INIT_LOGE("Failed to copy requried partition name"); + return -1; + } + p++; // skip '=' + if (strncpy_s(mountOptions, MAX_BUFFER_LEN -1, p, strlen(p)) != EOK) { + INIT_LOGE("Failed to copy requried mount info: %s", item); + return -1; + } + } + INIT_LOGV("Mount option of partition %s is [%s]", partName, mountOptions); + if (ParseFstabPerLine(mountOptions, fstab, false, "@") < 0) { + INIT_LOGE("Failed to parse mount options of partition \' %s \', options: %s", partName, mountOptions); + return -1; + } + return 0; +} + +static Fstab* LoadFstabFromCommandLine(void) +{ + Fstab *fstab = NULL; + char *cmdline = ReadFileData("/proc/cmdline"); + bool isDone = false; + + if (cmdline == NULL) { + INIT_LOGE("Read from \'/proc/cmdline\' failed, err = %d", errno); + return NULL; + } + if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) { + INIT_LOGE("Allocate memory for FS table failed, err = %d", errno); + return NULL; + } + + char *start = cmdline; + char *end = start + strlen(cmdline); + while (start < end) { + char *token = strstr(start, " "); + if (token == NULL) { + break; + } + + // Startswith " " + if (token == start) { + start++; + continue; + } + *token = '\0'; + if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, + strlen(OHOS_REQUIRED_MOUNT_PREFIX)) != 0) { + start = token + 1; + continue; + } + isDone = true; + if (ParseRequiredMountInfo(start, fstab) < 0) { + INIT_LOGE("Failed to parse \' %s \'", start); + isDone = false; + break; + } + start = token + 1; + } + + // handle last one + if (start < end) { + if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, + strlen(OHOS_REQUIRED_MOUNT_PREFIX)) == 0 && + ParseRequiredMountInfo(start, fstab) < 0) { + INIT_LOGE("Failed to parse \' %s \'", start); + isDone = false; + } + } + + if (!isDone) { + ReleaseFstab(fstab); + fstab = NULL; + } + free(cmdline); + return fstab; +} + +Fstab* LoadRequiredFstab(void) +{ + Fstab *fstab = NULL; + fstab = LoadFstabFromCommandLine(); + if (fstab == NULL) { + INIT_LOGI("Cannot load fstab from command line, try read from fstab.required"); + const char *fstabFile = "/etc/fstab.required"; + if (access(fstabFile, F_OK) != 0) { + fstabFile = "/system/etc/fstab.required"; + } + INIT_ERROR_CHECK(access(fstabFile, F_OK) == 0, abort(), "Failed get fstab.required"); + fstab = ReadFstabFromFile(fstabFile, false); + } + return fstab; +} diff --git a/services/init/standard/init_mount.h b/services/init/standard/init_mount.h index 8c652f70..a3b0173c 100644 --- a/services/init/standard/init_mount.h +++ b/services/init/standard/init_mount.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -23,6 +23,8 @@ extern "C" { #endif #endif +#define PARTITION_NAME_SIZE 32 +Fstab* LoadRequiredFstab(void); int MountRequriedPartitions(const Fstab *fstab); #ifdef __cplusplus #if __cplusplus -- GitLab