1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include <ctype.h> 17d9f0492fSopenharmony_ci#include <libgen.h> 18d9f0492fSopenharmony_ci#include <limits.h> 19d9f0492fSopenharmony_ci#include <stdio.h> 20d9f0492fSopenharmony_ci#include <string.h> 21d9f0492fSopenharmony_ci#include <stdbool.h> 22d9f0492fSopenharmony_ci#include <sys/mount.h> 23d9f0492fSopenharmony_ci#include <sys/types.h> 24d9f0492fSopenharmony_ci#include "beget_ext.h" 25d9f0492fSopenharmony_ci#include "fs_manager/fs_manager.h" 26d9f0492fSopenharmony_ci#include "init_utils.h" 27d9f0492fSopenharmony_ci#include "securec.h" 28d9f0492fSopenharmony_ci 29d9f0492fSopenharmony_ci#ifdef __cplusplus 30d9f0492fSopenharmony_ci#if __cplusplus 31d9f0492fSopenharmony_ciextern "C" { 32d9f0492fSopenharmony_ci#endif 33d9f0492fSopenharmony_ci#endif 34d9f0492fSopenharmony_ci 35d9f0492fSopenharmony_ci#define CMDLINE_LABEL_FSCRYPT_DISABLE "ohos.init.fscrypt.disable" 36d9f0492fSopenharmony_ci#define CMDLINE_VALUE_FSCRYPT_DISABLE "disabled" 37d9f0492fSopenharmony_ci#define CMDLINE_VALUE_LEN (sizeof(CMDLINE_VALUE_FSCRYPT_DISABLE) - 1) 38d9f0492fSopenharmony_cistruct FsManagerFlags { 39d9f0492fSopenharmony_ci char *name; 40d9f0492fSopenharmony_ci unsigned int flags; 41d9f0492fSopenharmony_ci}; 42d9f0492fSopenharmony_ci 43d9f0492fSopenharmony_cistruct MountFlags { 44d9f0492fSopenharmony_ci char *name; 45d9f0492fSopenharmony_ci unsigned long flags; 46d9f0492fSopenharmony_ci}; 47d9f0492fSopenharmony_ci 48d9f0492fSopenharmony_cistatic char *g_fscryptPolicy = NULL; 49d9f0492fSopenharmony_ci 50d9f0492fSopenharmony_cistatic unsigned int ConvertFlags(char *flagBuffer) 51d9f0492fSopenharmony_ci{ 52d9f0492fSopenharmony_ci static struct FsManagerFlags fsFlags[] = { 53d9f0492fSopenharmony_ci {"check", FS_MANAGER_CHECK}, 54d9f0492fSopenharmony_ci {"wait", FS_MANAGER_WAIT}, 55d9f0492fSopenharmony_ci {"required", FS_MANAGER_REQUIRED}, 56d9f0492fSopenharmony_ci {"nofail", FS_MANAGER_NOFAIL}, 57d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB 58d9f0492fSopenharmony_ci {"hvb", FS_MANAGER_HVB}, 59d9f0492fSopenharmony_ci#endif 60d9f0492fSopenharmony_ci {"fsprojquota", FS_MANAGER_PROJQUOTA}, 61d9f0492fSopenharmony_ci {"fscasefold", FS_MANAGER_CASEFOLD}, 62d9f0492fSopenharmony_ci {"fscompression", FS_MANAGER_COMPRESSION}, 63d9f0492fSopenharmony_ci {"fsdedup", FS_MANAGER_DEDUP}, 64d9f0492fSopenharmony_ci {"formattable", FS_MANAGER_FORMATTABLE}, 65d9f0492fSopenharmony_ci }; 66d9f0492fSopenharmony_ci 67d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(flagBuffer != NULL && *flagBuffer != '\0', 0); // No valid flags. 68d9f0492fSopenharmony_ci int flagCount = 0; 69d9f0492fSopenharmony_ci unsigned int flags = 0; 70d9f0492fSopenharmony_ci const int maxCount = 3; 71d9f0492fSopenharmony_ci char **vector = SplitStringExt(flagBuffer, ",", &flagCount, maxCount); 72d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(vector != NULL && flagCount != 0, 0); 73d9f0492fSopenharmony_ci for (size_t i = 0; i < ARRAY_LENGTH(fsFlags); i++) { 74d9f0492fSopenharmony_ci for (int j = 0; j < flagCount; j++) { 75d9f0492fSopenharmony_ci if (strcmp(fsFlags[i].name, vector[j]) == 0) { 76d9f0492fSopenharmony_ci flags |= fsFlags[i].flags; 77d9f0492fSopenharmony_ci } 78d9f0492fSopenharmony_ci } 79d9f0492fSopenharmony_ci } 80d9f0492fSopenharmony_ci FreeStringVector(vector, flagCount); 81d9f0492fSopenharmony_ci return flags; 82d9f0492fSopenharmony_ci} 83d9f0492fSopenharmony_ci 84d9f0492fSopenharmony_cistatic int AddToFstab(Fstab *fstab, FstabItem *item) 85d9f0492fSopenharmony_ci{ 86d9f0492fSopenharmony_ci if (fstab == NULL || item == NULL) { 87d9f0492fSopenharmony_ci return -1; 88d9f0492fSopenharmony_ci } 89d9f0492fSopenharmony_ci if (fstab->tail == NULL) { 90d9f0492fSopenharmony_ci fstab->head = fstab->tail = item; 91d9f0492fSopenharmony_ci } else { 92d9f0492fSopenharmony_ci fstab->tail->next = item; 93d9f0492fSopenharmony_ci fstab->tail = item; 94d9f0492fSopenharmony_ci } 95d9f0492fSopenharmony_ci return 0; 96d9f0492fSopenharmony_ci} 97d9f0492fSopenharmony_ci 98d9f0492fSopenharmony_civoid ReleaseFstabItem(FstabItem *item) 99d9f0492fSopenharmony_ci{ 100d9f0492fSopenharmony_ci if (item != NULL) { 101d9f0492fSopenharmony_ci if (item->deviceName != NULL) { 102d9f0492fSopenharmony_ci free(item->deviceName); 103d9f0492fSopenharmony_ci item->deviceName = NULL; 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci 106d9f0492fSopenharmony_ci if (item->mountPoint != NULL) { 107d9f0492fSopenharmony_ci free(item->mountPoint); 108d9f0492fSopenharmony_ci item->mountPoint = NULL; 109d9f0492fSopenharmony_ci } 110d9f0492fSopenharmony_ci 111d9f0492fSopenharmony_ci if (item->fsType != NULL) { 112d9f0492fSopenharmony_ci free(item->fsType); 113d9f0492fSopenharmony_ci item->fsType = NULL; 114d9f0492fSopenharmony_ci } 115d9f0492fSopenharmony_ci 116d9f0492fSopenharmony_ci if (item->mountOptions != NULL) { 117d9f0492fSopenharmony_ci free(item->mountOptions); 118d9f0492fSopenharmony_ci item->mountOptions = NULL; 119d9f0492fSopenharmony_ci } 120d9f0492fSopenharmony_ci 121d9f0492fSopenharmony_ci free(item); 122d9f0492fSopenharmony_ci } 123d9f0492fSopenharmony_ci} 124d9f0492fSopenharmony_ci 125d9f0492fSopenharmony_civoid ReleaseFstab(Fstab *fstab) 126d9f0492fSopenharmony_ci{ 127d9f0492fSopenharmony_ci if (fstab != NULL) { 128d9f0492fSopenharmony_ci FstabItem *item = fstab->head; 129d9f0492fSopenharmony_ci while (item != NULL) { 130d9f0492fSopenharmony_ci FstabItem *tmp = item->next; 131d9f0492fSopenharmony_ci ReleaseFstabItem(item); 132d9f0492fSopenharmony_ci item = tmp; 133d9f0492fSopenharmony_ci } 134d9f0492fSopenharmony_ci fstab->head = fstab->tail = NULL; 135d9f0492fSopenharmony_ci free(fstab); 136d9f0492fSopenharmony_ci fstab = NULL; 137d9f0492fSopenharmony_ci } 138d9f0492fSopenharmony_ci} 139d9f0492fSopenharmony_ci 140d9f0492fSopenharmony_ciint ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator) 141d9f0492fSopenharmony_ci{ 142d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(str != NULL && fstab != NULL, -1); 143d9f0492fSopenharmony_ci char *rest = NULL; 144d9f0492fSopenharmony_ci FstabItem *item = NULL; 145d9f0492fSopenharmony_ci char *p = NULL; 146d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(separator != NULL && *separator != '\0', return -1, "Invalid separator for parsing fstab"); 147d9f0492fSopenharmony_ci 148d9f0492fSopenharmony_ci if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) { 149d9f0492fSopenharmony_ci errno = ENOMEM; 150d9f0492fSopenharmony_ci BEGET_LOGE("Allocate memory for FS table item failed, err = %d", errno); 151d9f0492fSopenharmony_ci return -1; 152d9f0492fSopenharmony_ci } 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_ci do { 155d9f0492fSopenharmony_ci BEGET_ERROR_CHECK((p = strtok_r(str, separator, &rest)) != NULL, break, "Failed to parse block device."); 156d9f0492fSopenharmony_ci item->deviceName = strdup(p); 157d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(item->deviceName != NULL, break, "strdup deviceName failed."); 158d9f0492fSopenharmony_ci 159d9f0492fSopenharmony_ci BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount point."); 160d9f0492fSopenharmony_ci item->mountPoint = strdup(p); 161d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(item->mountPoint != NULL, break, "strdup mountPoint failed."); 162d9f0492fSopenharmony_ci 163d9f0492fSopenharmony_ci BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse fs type."); 164d9f0492fSopenharmony_ci item->fsType = strdup(p); 165d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(item->fsType != NULL, break, "strdup fsType failed."); 166d9f0492fSopenharmony_ci 167d9f0492fSopenharmony_ci BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount options."); 168d9f0492fSopenharmony_ci item->mountOptions = strdup(p); 169d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(item->mountOptions != NULL, break, "strdup mountOptions failed."); 170d9f0492fSopenharmony_ci 171d9f0492fSopenharmony_ci if ((p = strtok_r(NULL, separator, &rest)) == NULL) { 172d9f0492fSopenharmony_ci BEGET_LOGE("Failed to parse fs manager flags."); 173d9f0492fSopenharmony_ci break; 174d9f0492fSopenharmony_ci } 175d9f0492fSopenharmony_ci // @fsManagerFlags only for fstab 176d9f0492fSopenharmony_ci // Ignore it if we read from /proc/mounts 177d9f0492fSopenharmony_ci if (!procMounts) { 178d9f0492fSopenharmony_ci item->fsManagerFlags = ConvertFlags(p); 179d9f0492fSopenharmony_ci } else { 180d9f0492fSopenharmony_ci item->fsManagerFlags = 0; 181d9f0492fSopenharmony_ci } 182d9f0492fSopenharmony_ci return AddToFstab(fstab, item); 183d9f0492fSopenharmony_ci } while (0); 184d9f0492fSopenharmony_ci 185d9f0492fSopenharmony_ci ReleaseFstabItem(item); 186d9f0492fSopenharmony_ci item = NULL; 187d9f0492fSopenharmony_ci return -1; 188d9f0492fSopenharmony_ci} 189d9f0492fSopenharmony_ci 190d9f0492fSopenharmony_ciFstab *ReadFstabFromFile(const char *file, bool procMounts) 191d9f0492fSopenharmony_ci{ 192d9f0492fSopenharmony_ci char *line = NULL; 193d9f0492fSopenharmony_ci size_t allocn = 0; 194d9f0492fSopenharmony_ci ssize_t readn = 0; 195d9f0492fSopenharmony_ci Fstab *fstab = NULL; 196d9f0492fSopenharmony_ci 197d9f0492fSopenharmony_ci FILE *fp = NULL; 198d9f0492fSopenharmony_ci char *realPath = GetRealPath(file); 199d9f0492fSopenharmony_ci if (realPath != NULL) { 200d9f0492fSopenharmony_ci fp = fopen(realPath, "r"); 201d9f0492fSopenharmony_ci free(realPath); 202d9f0492fSopenharmony_ci } else { 203d9f0492fSopenharmony_ci fp = fopen(file, "r"); // no file system, can not get real path 204d9f0492fSopenharmony_ci } 205d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(fp != NULL, return NULL, "Open %s failed, err = %d", file, errno); 206d9f0492fSopenharmony_ci 207d9f0492fSopenharmony_ci if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) { 208d9f0492fSopenharmony_ci BEGET_LOGE("Allocate memory for FS table failed, err = %d", errno); 209d9f0492fSopenharmony_ci fclose(fp); 210d9f0492fSopenharmony_ci fp = NULL; 211d9f0492fSopenharmony_ci return NULL; 212d9f0492fSopenharmony_ci } 213d9f0492fSopenharmony_ci 214d9f0492fSopenharmony_ci // Record line number of fstab file 215d9f0492fSopenharmony_ci size_t ln = 0; 216d9f0492fSopenharmony_ci while ((readn = getline(&line, &allocn, fp)) != -1) { 217d9f0492fSopenharmony_ci char *p = NULL; 218d9f0492fSopenharmony_ci ln++; 219d9f0492fSopenharmony_ci if (line[readn - 1] == '\n') { 220d9f0492fSopenharmony_ci line[readn - 1] = '\0'; 221d9f0492fSopenharmony_ci } 222d9f0492fSopenharmony_ci p = line; 223d9f0492fSopenharmony_ci while (isspace(*p)) { 224d9f0492fSopenharmony_ci p++; 225d9f0492fSopenharmony_ci } 226d9f0492fSopenharmony_ci 227d9f0492fSopenharmony_ci if (*p == '\0' || *p == '#') { 228d9f0492fSopenharmony_ci continue; 229d9f0492fSopenharmony_ci } 230d9f0492fSopenharmony_ci 231d9f0492fSopenharmony_ci if (ParseFstabPerLine(p, fstab, procMounts, " \t") < 0) { 232d9f0492fSopenharmony_ci if (errno == ENOMEM) { 233d9f0492fSopenharmony_ci // Ran out of memory, there is no reason to continue. 234d9f0492fSopenharmony_ci break; 235d9f0492fSopenharmony_ci } 236d9f0492fSopenharmony_ci // If one line in fstab file parsed with a failure. just give a warning 237d9f0492fSopenharmony_ci // and skip it. 238d9f0492fSopenharmony_ci BEGET_LOGW("Cannot parse file \" %s \" at line %zu. skip it", file, ln); 239d9f0492fSopenharmony_ci continue; 240d9f0492fSopenharmony_ci } 241d9f0492fSopenharmony_ci } 242d9f0492fSopenharmony_ci if (line != NULL) { 243d9f0492fSopenharmony_ci free(line); 244d9f0492fSopenharmony_ci } 245d9f0492fSopenharmony_ci (void)fclose(fp); 246d9f0492fSopenharmony_ci fp = NULL; 247d9f0492fSopenharmony_ci return fstab; 248d9f0492fSopenharmony_ci} 249d9f0492fSopenharmony_ci 250d9f0492fSopenharmony_ciFstabItem *FindFstabItemForMountPoint(Fstab fstab, const char *mp) 251d9f0492fSopenharmony_ci{ 252d9f0492fSopenharmony_ci FstabItem *item = NULL; 253d9f0492fSopenharmony_ci if (mp != NULL) { 254d9f0492fSopenharmony_ci for (item = fstab.head; item != NULL; item = item->next) { 255d9f0492fSopenharmony_ci if ((item->mountPoint != NULL) && (strcmp(item->mountPoint, mp) == 0)) { 256d9f0492fSopenharmony_ci break; 257d9f0492fSopenharmony_ci } 258d9f0492fSopenharmony_ci } 259d9f0492fSopenharmony_ci } 260d9f0492fSopenharmony_ci return item; 261d9f0492fSopenharmony_ci} 262d9f0492fSopenharmony_ci 263d9f0492fSopenharmony_ciFstabItem *FindFstabItemForPath(Fstab fstab, const char *path) 264d9f0492fSopenharmony_ci{ 265d9f0492fSopenharmony_ci FstabItem *item = NULL; 266d9f0492fSopenharmony_ci 267d9f0492fSopenharmony_ci if (path == NULL || *path != '/') { 268d9f0492fSopenharmony_ci return NULL; 269d9f0492fSopenharmony_ci } 270d9f0492fSopenharmony_ci 271d9f0492fSopenharmony_ci char tmp[PATH_MAX] = {0}; 272d9f0492fSopenharmony_ci char *dir = NULL; 273d9f0492fSopenharmony_ci if (strncpy_s(tmp, PATH_MAX - 1, path, strlen(path)) != EOK) { 274d9f0492fSopenharmony_ci BEGET_LOGE("Failed to copy path."); 275d9f0492fSopenharmony_ci return NULL; 276d9f0492fSopenharmony_ci } 277d9f0492fSopenharmony_ci 278d9f0492fSopenharmony_ci dir = tmp; 279d9f0492fSopenharmony_ci while (true) { 280d9f0492fSopenharmony_ci item = FindFstabItemForMountPoint(fstab, dir); 281d9f0492fSopenharmony_ci if (item != NULL) { 282d9f0492fSopenharmony_ci break; 283d9f0492fSopenharmony_ci } 284d9f0492fSopenharmony_ci dir = dirname(dir); 285d9f0492fSopenharmony_ci // Reverse walk through path and met "/", just quit. 286d9f0492fSopenharmony_ci if (dir == NULL || strcmp(dir, "/") == 0) { 287d9f0492fSopenharmony_ci break; 288d9f0492fSopenharmony_ci } 289d9f0492fSopenharmony_ci } 290d9f0492fSopenharmony_ci return item; 291d9f0492fSopenharmony_ci} 292d9f0492fSopenharmony_ci 293d9f0492fSopenharmony_cistatic char *GetFstabFile(char *fileName, size_t size) 294d9f0492fSopenharmony_ci{ 295d9f0492fSopenharmony_ci if (InUpdaterMode() == 1) { 296d9f0492fSopenharmony_ci if (strncpy_s(fileName, size, "/etc/fstab.updater", strlen("/etc/fstab.updater")) != 0) { 297d9f0492fSopenharmony_ci BEGET_LOGE("Failed strncpy_s err=%d", errno); 298d9f0492fSopenharmony_ci return NULL; 299d9f0492fSopenharmony_ci } 300d9f0492fSopenharmony_ci } else { 301d9f0492fSopenharmony_ci char hardware[MAX_BUFFER_LEN] = {0}; 302d9f0492fSopenharmony_ci int ret = GetParameterFromCmdLine("hardware", hardware, MAX_BUFFER_LEN); 303d9f0492fSopenharmony_ci if (ret != 0) { 304d9f0492fSopenharmony_ci BEGET_LOGE("Failed get hardware from cmdline"); 305d9f0492fSopenharmony_ci return NULL; 306d9f0492fSopenharmony_ci } 307d9f0492fSopenharmony_ci if (snprintf_s(fileName, size, size - 1, "/vendor/etc/fstab.%s", hardware) == -1) { 308d9f0492fSopenharmony_ci BEGET_LOGE("Failed to build fstab file, err=%d", errno); 309d9f0492fSopenharmony_ci return NULL; 310d9f0492fSopenharmony_ci } 311d9f0492fSopenharmony_ci } 312d9f0492fSopenharmony_ci BEGET_LOGI("fstab file is %s", fileName); 313d9f0492fSopenharmony_ci return fileName; 314d9f0492fSopenharmony_ci} 315d9f0492fSopenharmony_ci 316d9f0492fSopenharmony_ciint GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen) 317d9f0492fSopenharmony_ci{ 318d9f0492fSopenharmony_ci if (fstab == NULL || mountPoint == NULL || *mountPoint == '\0' || deviceName == NULL) { 319d9f0492fSopenharmony_ci return -1; 320d9f0492fSopenharmony_ci } 321d9f0492fSopenharmony_ci FstabItem *item = FindFstabItemForMountPoint(*fstab, mountPoint); 322d9f0492fSopenharmony_ci if (item == NULL) { 323d9f0492fSopenharmony_ci BEGET_LOGE("Failed to get fstab item from mount point \" %s \"", mountPoint); 324d9f0492fSopenharmony_ci return -1; 325d9f0492fSopenharmony_ci } 326d9f0492fSopenharmony_ci if (strncpy_s(deviceName, nameLen, item->deviceName, strlen(item->deviceName)) != 0) { 327d9f0492fSopenharmony_ci BEGET_LOGE("Failed to copy block device name, err=%d", errno); 328d9f0492fSopenharmony_ci return -1; 329d9f0492fSopenharmony_ci } 330d9f0492fSopenharmony_ci return 0; 331d9f0492fSopenharmony_ci} 332d9f0492fSopenharmony_ci 333d9f0492fSopenharmony_ciint GetBlockDeviceByName(const char *deviceName, const Fstab *fstab, char* miscDev, size_t size) 334d9f0492fSopenharmony_ci{ 335d9f0492fSopenharmony_ci for (FstabItem *item = fstab->head; item != NULL; item = item->next) { 336d9f0492fSopenharmony_ci if (strstr(item->deviceName, deviceName) != NULL) { 337d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(strcpy_s(miscDev, size, item->deviceName) != 0, 0); 338d9f0492fSopenharmony_ci } 339d9f0492fSopenharmony_ci } 340d9f0492fSopenharmony_ci return -1; 341d9f0492fSopenharmony_ci} 342d9f0492fSopenharmony_ci 343d9f0492fSopenharmony_cistatic const struct MountFlags MOUNT_FLAGS[] = { 344d9f0492fSopenharmony_ci { "noatime", MS_NOATIME }, 345d9f0492fSopenharmony_ci { "noexec", MS_NOEXEC }, 346d9f0492fSopenharmony_ci { "nosuid", MS_NOSUID }, 347d9f0492fSopenharmony_ci { "nodev", MS_NODEV }, 348d9f0492fSopenharmony_ci { "nodiratime", MS_NODIRATIME }, 349d9f0492fSopenharmony_ci { "ro", MS_RDONLY }, 350d9f0492fSopenharmony_ci { "rw", 0 }, 351d9f0492fSopenharmony_ci { "sync", MS_SYNCHRONOUS }, 352d9f0492fSopenharmony_ci { "remount", MS_REMOUNT }, 353d9f0492fSopenharmony_ci { "bind", MS_BIND }, 354d9f0492fSopenharmony_ci { "rec", MS_REC }, 355d9f0492fSopenharmony_ci { "unbindable", MS_UNBINDABLE }, 356d9f0492fSopenharmony_ci { "private", MS_PRIVATE }, 357d9f0492fSopenharmony_ci { "slave", MS_SLAVE }, 358d9f0492fSopenharmony_ci { "shared", MS_SHARED }, 359d9f0492fSopenharmony_ci { "defaults", 0 }, 360d9f0492fSopenharmony_ci}; 361d9f0492fSopenharmony_ci 362d9f0492fSopenharmony_cistatic bool IsDefaultMountFlags(const char *str) 363d9f0492fSopenharmony_ci{ 364d9f0492fSopenharmony_ci bool isDefault = false; 365d9f0492fSopenharmony_ci 366d9f0492fSopenharmony_ci if (str != NULL) { 367d9f0492fSopenharmony_ci for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) { 368d9f0492fSopenharmony_ci if (strcmp(str, MOUNT_FLAGS[i].name) == 0) { 369d9f0492fSopenharmony_ci isDefault = true; 370d9f0492fSopenharmony_ci } 371d9f0492fSopenharmony_ci } 372d9f0492fSopenharmony_ci } 373d9f0492fSopenharmony_ci return isDefault; 374d9f0492fSopenharmony_ci} 375d9f0492fSopenharmony_ci 376d9f0492fSopenharmony_cistatic unsigned long ParseDefaultMountFlag(const char *str) 377d9f0492fSopenharmony_ci{ 378d9f0492fSopenharmony_ci unsigned long flags = 0; 379d9f0492fSopenharmony_ci 380d9f0492fSopenharmony_ci if (str != NULL) { 381d9f0492fSopenharmony_ci for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) { 382d9f0492fSopenharmony_ci if (strcmp(str, MOUNT_FLAGS[i].name) == 0) { 383d9f0492fSopenharmony_ci flags = MOUNT_FLAGS[i].flags; 384d9f0492fSopenharmony_ci break; 385d9f0492fSopenharmony_ci } 386d9f0492fSopenharmony_ci } 387d9f0492fSopenharmony_ci } 388d9f0492fSopenharmony_ci return flags; 389d9f0492fSopenharmony_ci} 390d9f0492fSopenharmony_ci 391d9f0492fSopenharmony_cistatic bool IsFscryptOption(const char *option) 392d9f0492fSopenharmony_ci{ 393d9f0492fSopenharmony_ci if (!option) { 394d9f0492fSopenharmony_ci return false; 395d9f0492fSopenharmony_ci } 396d9f0492fSopenharmony_ci char *fscryptPre = "fscrypt="; 397d9f0492fSopenharmony_ci if (strncmp(option, fscryptPre, strlen(fscryptPre)) == 0) { 398d9f0492fSopenharmony_ci return true; 399d9f0492fSopenharmony_ci } 400d9f0492fSopenharmony_ci return false; 401d9f0492fSopenharmony_ci} 402d9f0492fSopenharmony_ci 403d9f0492fSopenharmony_cistatic void StoreFscryptPolicy(const char *option) 404d9f0492fSopenharmony_ci{ 405d9f0492fSopenharmony_ci if (option == NULL) { 406d9f0492fSopenharmony_ci return; 407d9f0492fSopenharmony_ci } 408d9f0492fSopenharmony_ci 409d9f0492fSopenharmony_ci char fscryptDisable[CMDLINE_VALUE_LEN_MAX] = {0}; 410d9f0492fSopenharmony_ci int ret = GetParameterFromCmdLine(CMDLINE_LABEL_FSCRYPT_DISABLE, fscryptDisable, sizeof(fscryptDisable)); 411d9f0492fSopenharmony_ci if (ret == 0 && strncmp(fscryptDisable, 412d9f0492fSopenharmony_ci CMDLINE_VALUE_FSCRYPT_DISABLE, CMDLINE_VALUE_LEN) == 0) { 413d9f0492fSopenharmony_ci BEGET_LOGE("fscrypt policy is disabled by cmdline"); 414d9f0492fSopenharmony_ci return; 415d9f0492fSopenharmony_ci } 416d9f0492fSopenharmony_ci 417d9f0492fSopenharmony_ci if (g_fscryptPolicy != NULL) { 418d9f0492fSopenharmony_ci BEGET_LOGW("StoreFscryptPolicy:inited policy is not empty"); 419d9f0492fSopenharmony_ci free(g_fscryptPolicy); 420d9f0492fSopenharmony_ci } 421d9f0492fSopenharmony_ci g_fscryptPolicy = strdup(option); 422d9f0492fSopenharmony_ci if (g_fscryptPolicy == NULL) { 423d9f0492fSopenharmony_ci BEGET_LOGE("StoreFscryptPolicy:no memory"); 424d9f0492fSopenharmony_ci return; 425d9f0492fSopenharmony_ci } 426d9f0492fSopenharmony_ci BEGET_LOGI("StoreFscryptPolicy:store fscrypt policy, %s", option); 427d9f0492fSopenharmony_ci} 428d9f0492fSopenharmony_ci 429d9f0492fSopenharmony_ciint LoadFscryptPolicy(char *buf, size_t size) 430d9f0492fSopenharmony_ci{ 431d9f0492fSopenharmony_ci BEGET_LOGI("LoadFscryptPolicy start"); 432d9f0492fSopenharmony_ci if (buf == NULL || g_fscryptPolicy == NULL) { 433d9f0492fSopenharmony_ci BEGET_LOGE("LoadFscryptPolicy:buf or fscrypt policy is empty"); 434d9f0492fSopenharmony_ci return -ENOMEM; 435d9f0492fSopenharmony_ci } 436d9f0492fSopenharmony_ci if (size == 0) { 437d9f0492fSopenharmony_ci BEGET_LOGE("LoadFscryptPloicy:size is invalid"); 438d9f0492fSopenharmony_ci return -EINVAL; 439d9f0492fSopenharmony_ci } 440d9f0492fSopenharmony_ci if (strcpy_s(buf, size, g_fscryptPolicy) != 0) { 441d9f0492fSopenharmony_ci BEGET_LOGE("loadFscryptPolicy:strcmp failed, error = %d", errno); 442d9f0492fSopenharmony_ci return -EFAULT; 443d9f0492fSopenharmony_ci } 444d9f0492fSopenharmony_ci free(g_fscryptPolicy); 445d9f0492fSopenharmony_ci g_fscryptPolicy = NULL; 446d9f0492fSopenharmony_ci BEGET_LOGI("LoadFscryptPolicy success"); 447d9f0492fSopenharmony_ci 448d9f0492fSopenharmony_ci return 0; 449d9f0492fSopenharmony_ci} 450d9f0492fSopenharmony_ci 451d9f0492fSopenharmony_ciunsigned long GetMountFlags(char *mountFlag, char *fsSpecificData, size_t fsSpecificDataSize, 452d9f0492fSopenharmony_ci const char *mountPoint) 453d9f0492fSopenharmony_ci{ 454d9f0492fSopenharmony_ci unsigned long flags = 0; 455d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(mountFlag != NULL && fsSpecificData != NULL, 0); 456d9f0492fSopenharmony_ci int flagCount = 0; 457d9f0492fSopenharmony_ci // Why max count of mount flags is 15? 458d9f0492fSopenharmony_ci // There are lots for mount flags defined in sys/mount.h 459d9f0492fSopenharmony_ci // But we only support to parse 15 in @ParseDefaultMountFlags() function 460d9f0492fSopenharmony_ci // So set default mount flag number to 15. 461d9f0492fSopenharmony_ci // If the item configured in fstab contains flag over than 15, 462d9f0492fSopenharmony_ci // @SplitStringExt can handle it and parse them all. but the parse function will drop it. 463d9f0492fSopenharmony_ci const int maxCount = 15; 464d9f0492fSopenharmony_ci char **flagsVector = SplitStringExt(mountFlag, ",", &flagCount, maxCount); 465d9f0492fSopenharmony_ci 466d9f0492fSopenharmony_ci if (flagsVector == NULL || flagCount == 0) { 467d9f0492fSopenharmony_ci // No flags or something wrong in SplitStringExt,just return. 468d9f0492fSopenharmony_ci return 0; 469d9f0492fSopenharmony_ci } 470d9f0492fSopenharmony_ci 471d9f0492fSopenharmony_ci for (int i = 0; i < flagCount; i++) { 472d9f0492fSopenharmony_ci char *p = flagsVector[i]; 473d9f0492fSopenharmony_ci if (IsDefaultMountFlags(p)) { 474d9f0492fSopenharmony_ci flags |= ParseDefaultMountFlag(p); 475d9f0492fSopenharmony_ci } else { 476d9f0492fSopenharmony_ci if (IsFscryptOption(p) && 477d9f0492fSopenharmony_ci !strncmp(mountPoint, "/data", strlen("/data"))) { 478d9f0492fSopenharmony_ci StoreFscryptPolicy(p + strlen("fscrypt=")); 479d9f0492fSopenharmony_ci continue; 480d9f0492fSopenharmony_ci } 481d9f0492fSopenharmony_ci if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) { 482d9f0492fSopenharmony_ci BEGET_LOGW("Failed to append mount flag \" %s \", ignore it.", p); 483d9f0492fSopenharmony_ci continue; 484d9f0492fSopenharmony_ci } 485d9f0492fSopenharmony_ci if (i == flagCount - 1) { // last flags, do not need to append ',' 486d9f0492fSopenharmony_ci break; 487d9f0492fSopenharmony_ci } 488d9f0492fSopenharmony_ci // Combined each mount flag with ',' 489d9f0492fSopenharmony_ci if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) { 490d9f0492fSopenharmony_ci BEGET_LOGW("Failed to append comma"); 491d9f0492fSopenharmony_ci break; // If cannot add ',' to the end of flags, there is not reason to continue. 492d9f0492fSopenharmony_ci } 493d9f0492fSopenharmony_ci } 494d9f0492fSopenharmony_ci } 495d9f0492fSopenharmony_ci 496d9f0492fSopenharmony_ci FreeStringVector(flagsVector, flagCount); 497d9f0492fSopenharmony_ci return flags; 498d9f0492fSopenharmony_ci} 499d9f0492fSopenharmony_ci 500d9f0492fSopenharmony_ciint GetBlockDevicePath(const char *partName, char *path, size_t size) 501d9f0492fSopenharmony_ci{ 502d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(partName != NULL && path != NULL, -1); 503d9f0492fSopenharmony_ci Fstab *fstab = LoadFstabFromCommandLine(); 504d9f0492fSopenharmony_ci if (fstab == NULL) { 505d9f0492fSopenharmony_ci BEGET_LOGI("fstab not found from cmdline, try to get it from file"); 506d9f0492fSopenharmony_ci char *fstabFile = GetFstabFile(path, size); 507d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(fstabFile != NULL, -1); 508d9f0492fSopenharmony_ci fstab = ReadFstabFromFile(fstabFile, false); 509d9f0492fSopenharmony_ci } 510d9f0492fSopenharmony_ci BEGET_CHECK_RETURN_VALUE(fstab != NULL, -1); 511d9f0492fSopenharmony_ci int ret = GetBlockDeviceByMountPoint(partName, fstab, path, size); 512d9f0492fSopenharmony_ci BEGET_INFO_CHECK(ret == 0, ret = GetBlockDeviceByName(partName, fstab, path, size), 513d9f0492fSopenharmony_ci "Mount point not found, try to get path by device name."); 514d9f0492fSopenharmony_ci ReleaseFstab(fstab); 515d9f0492fSopenharmony_ci return ret; 516d9f0492fSopenharmony_ci} 517d9f0492fSopenharmony_ci 518d9f0492fSopenharmony_ci#define OHOS_REQUIRED_MOUNT_PREFIX "ohos.required_mount." 519d9f0492fSopenharmony_ci/* 520d9f0492fSopenharmony_ci * Fstab includes block device node, mount point, file system type, MNT_ Flags and options. 521d9f0492fSopenharmony_ci * We separate them by spaces in fstab.required file, but the separator is '@' in CmdLine. 522d9f0492fSopenharmony_ci * The prefix "ohos.required_mount." is the flag of required fstab information in CmdLine. 523d9f0492fSopenharmony_ci * Format as shown below: 524d9f0492fSopenharmony_ci * <block device>@<mount point>@<fstype>@<mount options>@<fstab options> 525d9f0492fSopenharmony_ci * e.g. 526d9f0492fSopenharmony_ci * ohos.required_mount.system=/dev/block/xxx/by-name/system@/usr@ext4@ro,barrier=1@wait,required 527d9f0492fSopenharmony_ci */ 528d9f0492fSopenharmony_cistatic int ParseRequiredMountInfo(const char *item, Fstab *fstab) 529d9f0492fSopenharmony_ci{ 530d9f0492fSopenharmony_ci char mountOptions[MAX_BUFFER_LEN] = {}; 531d9f0492fSopenharmony_ci char partName[NAME_SIZE] = {}; 532d9f0492fSopenharmony_ci // Sanity checks 533d9f0492fSopenharmony_ci BEGET_CHECK(!(item == NULL || *item == '\0' || fstab == NULL), return -1); 534d9f0492fSopenharmony_ci 535d9f0492fSopenharmony_ci char *p = NULL; 536d9f0492fSopenharmony_ci if ((p = strstr(item, "=")) != NULL) { 537d9f0492fSopenharmony_ci const char *q = item + strlen(OHOS_REQUIRED_MOUNT_PREFIX); // Get partition name 538d9f0492fSopenharmony_ci BEGET_CHECK(!(q == NULL || *q == '\0' || (p - q) <= 0), return -1); 539d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(strncpy_s(partName, NAME_SIZE -1, q, p - q) == EOK, 540d9f0492fSopenharmony_ci return -1, "Failed to copy required partition name"); 541d9f0492fSopenharmony_ci p++; // skip '=' 542d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(strncpy_s(mountOptions, MAX_BUFFER_LEN -1, p, strlen(p)) == EOK, 543d9f0492fSopenharmony_ci return -1, "Failed to copy required mount info: %s", item); 544d9f0492fSopenharmony_ci } 545d9f0492fSopenharmony_ci BEGET_LOGV("Config mount option of partition %s is [%s]", partName, mountOptions); 546d9f0492fSopenharmony_ci if (ParseFstabPerLine(mountOptions, fstab, false, "@") < 0) { 547d9f0492fSopenharmony_ci BEGET_LOGE("Failed to parse mount options of partition \' %s \', options: %s", partName, mountOptions); 548d9f0492fSopenharmony_ci return -1; 549d9f0492fSopenharmony_ci } 550d9f0492fSopenharmony_ci return 0; 551d9f0492fSopenharmony_ci} 552d9f0492fSopenharmony_ci 553d9f0492fSopenharmony_ciFstab* LoadFstabFromCommandLine(void) 554d9f0492fSopenharmony_ci{ 555d9f0492fSopenharmony_ci Fstab *fstab = NULL; 556d9f0492fSopenharmony_ci char *cmdline = ReadFileData(BOOT_CMD_LINE); 557d9f0492fSopenharmony_ci bool isDone = false; 558d9f0492fSopenharmony_ci 559d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(cmdline != NULL, return NULL, "Read from \'%s\' failed, err = %d", BOOT_CMD_LINE, errno); 560d9f0492fSopenharmony_ci TrimTail(cmdline, '\n'); 561d9f0492fSopenharmony_ci fstab = (Fstab *)calloc(1, sizeof(Fstab)); 562d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(fstab != NULL, free(cmdline); return NULL, 563d9f0492fSopenharmony_ci "Allocate memory for FS table failed, err = %d", errno); 564d9f0492fSopenharmony_ci char *start = cmdline; 565d9f0492fSopenharmony_ci char *end = start + strlen(cmdline); 566d9f0492fSopenharmony_ci while (start < end) { 567d9f0492fSopenharmony_ci char *token = strstr(start, " "); 568d9f0492fSopenharmony_ci if (token == NULL) { 569d9f0492fSopenharmony_ci break; 570d9f0492fSopenharmony_ci } 571d9f0492fSopenharmony_ci 572d9f0492fSopenharmony_ci // Startswith " " 573d9f0492fSopenharmony_ci if (token == start) { 574d9f0492fSopenharmony_ci start++; 575d9f0492fSopenharmony_ci continue; 576d9f0492fSopenharmony_ci } 577d9f0492fSopenharmony_ci *token = '\0'; 578d9f0492fSopenharmony_ci if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, 579d9f0492fSopenharmony_ci strlen(OHOS_REQUIRED_MOUNT_PREFIX)) != 0) { 580d9f0492fSopenharmony_ci start = token + 1; 581d9f0492fSopenharmony_ci continue; 582d9f0492fSopenharmony_ci } 583d9f0492fSopenharmony_ci isDone = true; 584d9f0492fSopenharmony_ci if (ParseRequiredMountInfo(start, fstab) < 0) { 585d9f0492fSopenharmony_ci BEGET_LOGE("Failed to parse \' %s \'", start); 586d9f0492fSopenharmony_ci isDone = false; 587d9f0492fSopenharmony_ci break; 588d9f0492fSopenharmony_ci } 589d9f0492fSopenharmony_ci start = token + 1; 590d9f0492fSopenharmony_ci } 591d9f0492fSopenharmony_ci 592d9f0492fSopenharmony_ci // handle last one 593d9f0492fSopenharmony_ci if (start < end) { 594d9f0492fSopenharmony_ci if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, 595d9f0492fSopenharmony_ci strlen(OHOS_REQUIRED_MOUNT_PREFIX)) == 0 && 596d9f0492fSopenharmony_ci ParseRequiredMountInfo(start, fstab) < 0) { 597d9f0492fSopenharmony_ci BEGET_LOGE("Failed to parse \' %s \'", start); 598d9f0492fSopenharmony_ci isDone = false; 599d9f0492fSopenharmony_ci } 600d9f0492fSopenharmony_ci } 601d9f0492fSopenharmony_ci 602d9f0492fSopenharmony_ci if (!isDone) { 603d9f0492fSopenharmony_ci ReleaseFstab(fstab); 604d9f0492fSopenharmony_ci fstab = NULL; 605d9f0492fSopenharmony_ci } 606d9f0492fSopenharmony_ci free(cmdline); 607d9f0492fSopenharmony_ci return fstab; 608d9f0492fSopenharmony_ci} 609d9f0492fSopenharmony_ci#ifdef __cplusplus 610d9f0492fSopenharmony_ci#if __cplusplus 611d9f0492fSopenharmony_ci} 612d9f0492fSopenharmony_ci#endif 613d9f0492fSopenharmony_ci#endif 614