Merge changes I6bffe1cd,I0984ba01
* changes: fs_mgr: split fstab parsing into separate file fs_mgr: update ext4_parse_sb to match change in ext4_utils
This commit is contained in:
commit
1686784a37
|
@ -3,7 +3,7 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c
|
||||
LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
|
||||
|
|
380
fs_mgr/fs_mgr.c
380
fs_mgr/fs_mgr.c
|
@ -54,55 +54,6 @@
|
|||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
struct flag_list {
|
||||
const char *name;
|
||||
unsigned flag;
|
||||
};
|
||||
|
||||
static struct flag_list mount_flags[] = {
|
||||
{ "noatime", MS_NOATIME },
|
||||
{ "noexec", MS_NOEXEC },
|
||||
{ "nosuid", MS_NOSUID },
|
||||
{ "nodev", MS_NODEV },
|
||||
{ "nodiratime", MS_NODIRATIME },
|
||||
{ "ro", MS_RDONLY },
|
||||
{ "rw", 0 },
|
||||
{ "remount", MS_REMOUNT },
|
||||
{ "bind", MS_BIND },
|
||||
{ "rec", MS_REC },
|
||||
{ "unbindable", MS_UNBINDABLE },
|
||||
{ "private", MS_PRIVATE },
|
||||
{ "slave", MS_SLAVE },
|
||||
{ "shared", MS_SHARED },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static struct flag_list fs_mgr_flags[] = {
|
||||
{ "wait", MF_WAIT },
|
||||
{ "check", MF_CHECK },
|
||||
{ "encryptable=",MF_CRYPT },
|
||||
{ "nonremovable",MF_NONREMOVABLE },
|
||||
{ "voldmanaged=",MF_VOLDMANAGED},
|
||||
{ "length=", MF_LENGTH },
|
||||
{ "recoveryonly",MF_RECOVERYONLY },
|
||||
{ "swapprio=", MF_SWAPPRIO },
|
||||
{ "zramsize=", MF_ZRAMSIZE },
|
||||
{ "verify", MF_VERIFY },
|
||||
{ "noemulatedsd", MF_NOEMULATEDSD },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
struct fs_mgr_flag_values {
|
||||
char *key_loc;
|
||||
long long part_length;
|
||||
char *label;
|
||||
int partnum;
|
||||
int swap_prio;
|
||||
unsigned int zram_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* gettime() - returns the time in seconds of the system's monotonic clock or
|
||||
* zero on error.
|
||||
|
@ -133,269 +84,6 @@ static int wait_for_file(const char *filename, int timeout)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int parse_flags(char *flags, struct flag_list *fl,
|
||||
struct fs_mgr_flag_values *flag_vals,
|
||||
char *fs_options, int fs_options_len)
|
||||
{
|
||||
int f = 0;
|
||||
int i;
|
||||
char *p;
|
||||
char *savep;
|
||||
|
||||
/* initialize flag values. If we find a relevant flag, we'll
|
||||
* update the value */
|
||||
if (flag_vals) {
|
||||
memset(flag_vals, 0, sizeof(*flag_vals));
|
||||
flag_vals->partnum = -1;
|
||||
flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
|
||||
}
|
||||
|
||||
/* initialize fs_options to the null string */
|
||||
if (fs_options && (fs_options_len > 0)) {
|
||||
fs_options[0] = '\0';
|
||||
}
|
||||
|
||||
p = strtok_r(flags, ",", &savep);
|
||||
while (p) {
|
||||
/* Look for the flag "p" in the flag list "fl"
|
||||
* If not found, the loop exits with fl[i].name being null.
|
||||
*/
|
||||
for (i = 0; fl[i].name; i++) {
|
||||
if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
|
||||
f |= fl[i].flag;
|
||||
if ((fl[i].flag == MF_CRYPT) && flag_vals) {
|
||||
/* The encryptable flag is followed by an = and the
|
||||
* location of the keys. Get it and return it.
|
||||
*/
|
||||
flag_vals->key_loc = strdup(strchr(p, '=') + 1);
|
||||
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
|
||||
/* The length flag is followed by an = and the
|
||||
* size of the partition. Get it and return it.
|
||||
*/
|
||||
flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
|
||||
/* The voldmanaged flag is followed by an = and the
|
||||
* label, a colon and the partition number or the
|
||||
* word "auto", e.g.
|
||||
* voldmanaged=sdcard:3
|
||||
* Get and return them.
|
||||
*/
|
||||
char *label_start;
|
||||
char *label_end;
|
||||
char *part_start;
|
||||
|
||||
label_start = strchr(p, '=') + 1;
|
||||
label_end = strchr(p, ':');
|
||||
if (label_end) {
|
||||
flag_vals->label = strndup(label_start,
|
||||
(int) (label_end - label_start));
|
||||
part_start = strchr(p, ':') + 1;
|
||||
if (!strcmp(part_start, "auto")) {
|
||||
flag_vals->partnum = -1;
|
||||
} else {
|
||||
flag_vals->partnum = strtol(part_start, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
ERROR("Warning: voldmanaged= flag malformed\n");
|
||||
}
|
||||
} else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
|
||||
flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
|
||||
flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fl[i].name) {
|
||||
if (fs_options) {
|
||||
/* It's not a known flag, so it must be a filesystem specific
|
||||
* option. Add it to fs_options if it was passed in.
|
||||
*/
|
||||
strlcat(fs_options, p, fs_options_len);
|
||||
strlcat(fs_options, ",", fs_options_len);
|
||||
} else {
|
||||
/* fs_options was not passed in, so if the flag is unknown
|
||||
* it's an error.
|
||||
*/
|
||||
ERROR("Warning: unknown flag %s\n", p);
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, ",", &savep);
|
||||
}
|
||||
|
||||
out:
|
||||
if (fs_options && fs_options[0]) {
|
||||
/* remove the last trailing comma from the list of options */
|
||||
fs_options[strlen(fs_options) - 1] = '\0';
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
||||
{
|
||||
FILE *fstab_file;
|
||||
int cnt, entries;
|
||||
ssize_t len;
|
||||
size_t alloc_len = 0;
|
||||
char *line = NULL;
|
||||
const char *delim = " \t";
|
||||
char *save_ptr, *p;
|
||||
struct fstab *fstab = NULL;
|
||||
struct fstab_rec *recs;
|
||||
struct fs_mgr_flag_values flag_vals;
|
||||
#define FS_OPTIONS_LEN 1024
|
||||
char tmp_fs_options[FS_OPTIONS_LEN];
|
||||
|
||||
fstab_file = fopen(fstab_path, "r");
|
||||
if (!fstab_file) {
|
||||
ERROR("Cannot open file %s\n", fstab_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
entries = 0;
|
||||
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
if (line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
/* Skip any leading whitespace */
|
||||
p = line;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* ignore comments or empty lines */
|
||||
if (*p == '#' || *p == '\0')
|
||||
continue;
|
||||
entries++;
|
||||
}
|
||||
|
||||
if (!entries) {
|
||||
ERROR("No entries found in fstab\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate and init the fstab structure */
|
||||
fstab = calloc(1, sizeof(struct fstab));
|
||||
fstab->num_entries = entries;
|
||||
fstab->fstab_filename = strdup(fstab_path);
|
||||
fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
|
||||
|
||||
fseek(fstab_file, 0, SEEK_SET);
|
||||
|
||||
cnt = 0;
|
||||
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
if (line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/* Skip any leading whitespace */
|
||||
p = line;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* ignore comments or empty lines */
|
||||
if (*p == '#' || *p == '\0')
|
||||
continue;
|
||||
|
||||
/* If a non-comment entry is greater than the size we allocated, give an
|
||||
* error and quit. This can happen in the unlikely case the file changes
|
||||
* between the two reads.
|
||||
*/
|
||||
if (cnt >= entries) {
|
||||
ERROR("Tried to process more entries than counted\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(p = strtok_r(line, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount source\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].blk_device = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount_point\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].mount_point = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_type\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].fs_type = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount_flags\n");
|
||||
goto err;
|
||||
}
|
||||
tmp_fs_options[0] = '\0';
|
||||
fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
|
||||
tmp_fs_options, FS_OPTIONS_LEN);
|
||||
|
||||
/* fs_options are optional */
|
||||
if (tmp_fs_options[0]) {
|
||||
fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
|
||||
} else {
|
||||
fstab->recs[cnt].fs_options = NULL;
|
||||
}
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_mgr_options\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
|
||||
&flag_vals, NULL, 0);
|
||||
fstab->recs[cnt].key_loc = flag_vals.key_loc;
|
||||
fstab->recs[cnt].length = flag_vals.part_length;
|
||||
fstab->recs[cnt].label = flag_vals.label;
|
||||
fstab->recs[cnt].partnum = flag_vals.partnum;
|
||||
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
|
||||
fstab->recs[cnt].zram_size = flag_vals.zram_size;
|
||||
cnt++;
|
||||
}
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
return fstab;
|
||||
|
||||
err:
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
if (fstab)
|
||||
fs_mgr_free_fstab(fstab);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fs_mgr_free_fstab(struct fstab *fstab)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fstab) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Free the pointers return by strdup(3) */
|
||||
free(fstab->recs[i].blk_device);
|
||||
free(fstab->recs[i].mount_point);
|
||||
free(fstab->recs[i].fs_type);
|
||||
free(fstab->recs[i].fs_options);
|
||||
free(fstab->recs[i].key_loc);
|
||||
free(fstab->recs[i].label);
|
||||
}
|
||||
|
||||
/* Free the fstab_recs array created by calloc(3) */
|
||||
free(fstab->recs);
|
||||
|
||||
/* Free the fstab filename */
|
||||
free(fstab->fstab_filename);
|
||||
|
||||
/* Free fstab */
|
||||
free(fstab);
|
||||
}
|
||||
|
||||
static void check_fs(char *blk_device, char *fs_type, char *target)
|
||||
{
|
||||
int status;
|
||||
|
@ -823,71 +511,3 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add an entry to the fstab, and return 0 on success or -1 on error */
|
||||
int fs_mgr_add_entry(struct fstab *fstab,
|
||||
const char *mount_point, const char *fs_type,
|
||||
const char *blk_device, long long length)
|
||||
{
|
||||
struct fstab_rec *new_fstab_recs;
|
||||
int n = fstab->num_entries;
|
||||
|
||||
new_fstab_recs = (struct fstab_rec *)
|
||||
realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
|
||||
|
||||
if (!new_fstab_recs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A new entry was added, so initialize it */
|
||||
memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
|
||||
new_fstab_recs[n].mount_point = strdup(mount_point);
|
||||
new_fstab_recs[n].fs_type = strdup(fs_type);
|
||||
new_fstab_recs[n].blk_device = strdup(blk_device);
|
||||
new_fstab_recs[n].length = 0;
|
||||
|
||||
/* Update the fstab struct */
|
||||
fstab->recs = new_fstab_recs;
|
||||
fstab->num_entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fstab) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
int len = strlen(fstab->recs[i].mount_point);
|
||||
if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
|
||||
(path[len] == '\0' || path[len] == '/')) {
|
||||
return &fstab->recs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_VOLDMANAGED;
|
||||
}
|
||||
|
||||
int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NONREMOVABLE;
|
||||
}
|
||||
|
||||
int fs_mgr_is_encryptable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_CRYPT;
|
||||
}
|
||||
|
||||
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "fs_mgr_priv.h"
|
||||
|
||||
struct fs_mgr_flag_values {
|
||||
char *key_loc;
|
||||
long long part_length;
|
||||
char *label;
|
||||
int partnum;
|
||||
int swap_prio;
|
||||
unsigned int zram_size;
|
||||
};
|
||||
|
||||
struct flag_list {
|
||||
const char *name;
|
||||
unsigned flag;
|
||||
};
|
||||
|
||||
static struct flag_list mount_flags[] = {
|
||||
{ "noatime", MS_NOATIME },
|
||||
{ "noexec", MS_NOEXEC },
|
||||
{ "nosuid", MS_NOSUID },
|
||||
{ "nodev", MS_NODEV },
|
||||
{ "nodiratime", MS_NODIRATIME },
|
||||
{ "ro", MS_RDONLY },
|
||||
{ "rw", 0 },
|
||||
{ "remount", MS_REMOUNT },
|
||||
{ "bind", MS_BIND },
|
||||
{ "rec", MS_REC },
|
||||
{ "unbindable", MS_UNBINDABLE },
|
||||
{ "private", MS_PRIVATE },
|
||||
{ "slave", MS_SLAVE },
|
||||
{ "shared", MS_SHARED },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static struct flag_list fs_mgr_flags[] = {
|
||||
{ "wait", MF_WAIT },
|
||||
{ "check", MF_CHECK },
|
||||
{ "encryptable=",MF_CRYPT },
|
||||
{ "nonremovable",MF_NONREMOVABLE },
|
||||
{ "voldmanaged=",MF_VOLDMANAGED},
|
||||
{ "length=", MF_LENGTH },
|
||||
{ "recoveryonly",MF_RECOVERYONLY },
|
||||
{ "swapprio=", MF_SWAPPRIO },
|
||||
{ "zramsize=", MF_ZRAMSIZE },
|
||||
{ "verify", MF_VERIFY },
|
||||
{ "noemulatedsd", MF_NOEMULATEDSD },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static int parse_flags(char *flags, struct flag_list *fl,
|
||||
struct fs_mgr_flag_values *flag_vals,
|
||||
char *fs_options, int fs_options_len)
|
||||
{
|
||||
int f = 0;
|
||||
int i;
|
||||
char *p;
|
||||
char *savep;
|
||||
|
||||
/* initialize flag values. If we find a relevant flag, we'll
|
||||
* update the value */
|
||||
if (flag_vals) {
|
||||
memset(flag_vals, 0, sizeof(*flag_vals));
|
||||
flag_vals->partnum = -1;
|
||||
flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
|
||||
}
|
||||
|
||||
/* initialize fs_options to the null string */
|
||||
if (fs_options && (fs_options_len > 0)) {
|
||||
fs_options[0] = '\0';
|
||||
}
|
||||
|
||||
p = strtok_r(flags, ",", &savep);
|
||||
while (p) {
|
||||
/* Look for the flag "p" in the flag list "fl"
|
||||
* If not found, the loop exits with fl[i].name being null.
|
||||
*/
|
||||
for (i = 0; fl[i].name; i++) {
|
||||
if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
|
||||
f |= fl[i].flag;
|
||||
if ((fl[i].flag == MF_CRYPT) && flag_vals) {
|
||||
/* The encryptable flag is followed by an = and the
|
||||
* location of the keys. Get it and return it.
|
||||
*/
|
||||
flag_vals->key_loc = strdup(strchr(p, '=') + 1);
|
||||
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
|
||||
/* The length flag is followed by an = and the
|
||||
* size of the partition. Get it and return it.
|
||||
*/
|
||||
flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
|
||||
/* The voldmanaged flag is followed by an = and the
|
||||
* label, a colon and the partition number or the
|
||||
* word "auto", e.g.
|
||||
* voldmanaged=sdcard:3
|
||||
* Get and return them.
|
||||
*/
|
||||
char *label_start;
|
||||
char *label_end;
|
||||
char *part_start;
|
||||
|
||||
label_start = strchr(p, '=') + 1;
|
||||
label_end = strchr(p, ':');
|
||||
if (label_end) {
|
||||
flag_vals->label = strndup(label_start,
|
||||
(int) (label_end - label_start));
|
||||
part_start = strchr(p, ':') + 1;
|
||||
if (!strcmp(part_start, "auto")) {
|
||||
flag_vals->partnum = -1;
|
||||
} else {
|
||||
flag_vals->partnum = strtol(part_start, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
ERROR("Warning: voldmanaged= flag malformed\n");
|
||||
}
|
||||
} else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
|
||||
flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
|
||||
flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fl[i].name) {
|
||||
if (fs_options) {
|
||||
/* It's not a known flag, so it must be a filesystem specific
|
||||
* option. Add it to fs_options if it was passed in.
|
||||
*/
|
||||
strlcat(fs_options, p, fs_options_len);
|
||||
strlcat(fs_options, ",", fs_options_len);
|
||||
} else {
|
||||
/* fs_options was not passed in, so if the flag is unknown
|
||||
* it's an error.
|
||||
*/
|
||||
ERROR("Warning: unknown flag %s\n", p);
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, ",", &savep);
|
||||
}
|
||||
|
||||
out:
|
||||
if (fs_options && fs_options[0]) {
|
||||
/* remove the last trailing comma from the list of options */
|
||||
fs_options[strlen(fs_options) - 1] = '\0';
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
||||
{
|
||||
FILE *fstab_file;
|
||||
int cnt, entries;
|
||||
ssize_t len;
|
||||
size_t alloc_len = 0;
|
||||
char *line = NULL;
|
||||
const char *delim = " \t";
|
||||
char *save_ptr, *p;
|
||||
struct fstab *fstab = NULL;
|
||||
struct fstab_rec *recs;
|
||||
struct fs_mgr_flag_values flag_vals;
|
||||
#define FS_OPTIONS_LEN 1024
|
||||
char tmp_fs_options[FS_OPTIONS_LEN];
|
||||
|
||||
fstab_file = fopen(fstab_path, "r");
|
||||
if (!fstab_file) {
|
||||
ERROR("Cannot open file %s\n", fstab_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
entries = 0;
|
||||
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
if (line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
/* Skip any leading whitespace */
|
||||
p = line;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* ignore comments or empty lines */
|
||||
if (*p == '#' || *p == '\0')
|
||||
continue;
|
||||
entries++;
|
||||
}
|
||||
|
||||
if (!entries) {
|
||||
ERROR("No entries found in fstab\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate and init the fstab structure */
|
||||
fstab = calloc(1, sizeof(struct fstab));
|
||||
fstab->num_entries = entries;
|
||||
fstab->fstab_filename = strdup(fstab_path);
|
||||
fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
|
||||
|
||||
fseek(fstab_file, 0, SEEK_SET);
|
||||
|
||||
cnt = 0;
|
||||
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
if (line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/* Skip any leading whitespace */
|
||||
p = line;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* ignore comments or empty lines */
|
||||
if (*p == '#' || *p == '\0')
|
||||
continue;
|
||||
|
||||
/* If a non-comment entry is greater than the size we allocated, give an
|
||||
* error and quit. This can happen in the unlikely case the file changes
|
||||
* between the two reads.
|
||||
*/
|
||||
if (cnt >= entries) {
|
||||
ERROR("Tried to process more entries than counted\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(p = strtok_r(line, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount source\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].blk_device = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount_point\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].mount_point = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_type\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].fs_type = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount_flags\n");
|
||||
goto err;
|
||||
}
|
||||
tmp_fs_options[0] = '\0';
|
||||
fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
|
||||
tmp_fs_options, FS_OPTIONS_LEN);
|
||||
|
||||
/* fs_options are optional */
|
||||
if (tmp_fs_options[0]) {
|
||||
fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
|
||||
} else {
|
||||
fstab->recs[cnt].fs_options = NULL;
|
||||
}
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_mgr_options\n");
|
||||
goto err;
|
||||
}
|
||||
fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
|
||||
&flag_vals, NULL, 0);
|
||||
fstab->recs[cnt].key_loc = flag_vals.key_loc;
|
||||
fstab->recs[cnt].length = flag_vals.part_length;
|
||||
fstab->recs[cnt].label = flag_vals.label;
|
||||
fstab->recs[cnt].partnum = flag_vals.partnum;
|
||||
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
|
||||
fstab->recs[cnt].zram_size = flag_vals.zram_size;
|
||||
cnt++;
|
||||
}
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
return fstab;
|
||||
|
||||
err:
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
if (fstab)
|
||||
fs_mgr_free_fstab(fstab);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fs_mgr_free_fstab(struct fstab *fstab)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fstab) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Free the pointers return by strdup(3) */
|
||||
free(fstab->recs[i].blk_device);
|
||||
free(fstab->recs[i].mount_point);
|
||||
free(fstab->recs[i].fs_type);
|
||||
free(fstab->recs[i].fs_options);
|
||||
free(fstab->recs[i].key_loc);
|
||||
free(fstab->recs[i].label);
|
||||
}
|
||||
|
||||
/* Free the fstab_recs array created by calloc(3) */
|
||||
free(fstab->recs);
|
||||
|
||||
/* Free the fstab filename */
|
||||
free(fstab->fstab_filename);
|
||||
|
||||
/* Free fstab */
|
||||
free(fstab);
|
||||
}
|
||||
|
||||
/* Add an entry to the fstab, and return 0 on success or -1 on error */
|
||||
int fs_mgr_add_entry(struct fstab *fstab,
|
||||
const char *mount_point, const char *fs_type,
|
||||
const char *blk_device, long long length)
|
||||
{
|
||||
struct fstab_rec *new_fstab_recs;
|
||||
int n = fstab->num_entries;
|
||||
|
||||
new_fstab_recs = (struct fstab_rec *)
|
||||
realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
|
||||
|
||||
if (!new_fstab_recs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A new entry was added, so initialize it */
|
||||
memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
|
||||
new_fstab_recs[n].mount_point = strdup(mount_point);
|
||||
new_fstab_recs[n].fs_type = strdup(fs_type);
|
||||
new_fstab_recs[n].blk_device = strdup(blk_device);
|
||||
new_fstab_recs[n].length = 0;
|
||||
|
||||
/* Update the fstab struct */
|
||||
fstab->recs = new_fstab_recs;
|
||||
fstab->num_entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fstab) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
int len = strlen(fstab->recs[i].mount_point);
|
||||
if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
|
||||
(path[len] == '\0' || path[len] == '/')) {
|
||||
return &fstab->recs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_VOLDMANAGED;
|
||||
}
|
||||
|
||||
int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NONREMOVABLE;
|
||||
}
|
||||
|
||||
int fs_mgr_is_encryptable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_CRYPT;
|
||||
}
|
||||
|
||||
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
|
||||
}
|
|
@ -36,8 +36,7 @@
|
|||
#include "mincrypt/sha.h"
|
||||
#include "mincrypt/sha256.h"
|
||||
|
||||
#include "ext4_utils.h"
|
||||
#include "ext4.h"
|
||||
#include "ext4_sb.h"
|
||||
|
||||
#include "fs_mgr_priv.h"
|
||||
#include "fs_mgr_priv_verity.h"
|
||||
|
@ -122,6 +121,7 @@ static int get_target_device_size(char *blk_device, uint64_t *device_size)
|
|||
{
|
||||
int data_device;
|
||||
struct ext4_super_block sb;
|
||||
struct fs_info info = {0};
|
||||
|
||||
data_device = open(blk_device, O_RDONLY);
|
||||
if (data_device < 0) {
|
||||
|
@ -141,7 +141,7 @@ static int get_target_device_size(char *blk_device, uint64_t *device_size)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ext4_parse_sb(&sb);
|
||||
ext4_parse_sb(&sb, &info);
|
||||
*device_size = info.len;
|
||||
|
||||
close(data_device);
|
||||
|
|
Loading…
Reference in New Issue