diff --git a/Android.mk b/Android.mk index f4ecdb5d..35151ee7 100644 --- a/Android.mk +++ b/Android.mk @@ -32,6 +32,7 @@ LOCAL_MODULE := recovery LOCAL_FORCE_STATIC_EXECUTABLE := true RECOVERY_API_VERSION := 3 +RECOVERY_FSTAB_VERSION := 2 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) LOCAL_STATIC_LIBRARIES := \ @@ -45,6 +46,7 @@ LOCAL_STATIC_LIBRARIES := \ libminui \ libpixelflinger_static \ libpng \ + libfs_mgr \ libcutils \ libselinux \ libstdc++ \ diff --git a/bootloader.cpp b/bootloader.cpp index baaddc55..600d238f 100644 --- a/bootloader.cpp +++ b/bootloader.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "bootloader.h" #include "common.h" #include "mtdutils/mtdutils.h" @@ -71,22 +72,22 @@ static int get_bootloader_message_mtd(struct bootloader_message *out, const Volume* v) { size_t write_size; mtd_scan_partitions(); - const MtdPartition *part = mtd_find_partition_by_name(v->device); + const MtdPartition *part = mtd_find_partition_by_name(v->blk_device); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { - LOGE("Can't find %s\n", v->device); + LOGE("Can't find %s\n", v->blk_device); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { - LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } const ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); - if (r != size) LOGE("Can't read %s\n(%s)\n", v->device, strerror(errno)); + if (r != size) LOGE("Can't read %s\n(%s)\n", v->blk_device, strerror(errno)); mtd_read_close(read); if (r != size) return -1; @@ -97,22 +98,22 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in, const Volume* v) { size_t write_size; mtd_scan_partitions(); - const MtdPartition *part = mtd_find_partition_by_name(v->device); + const MtdPartition *part = mtd_find_partition_by_name(v->blk_device); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { - LOGE("Can't find %s\n", v->device); + LOGE("Can't find %s\n", v->blk_device); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { - LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); - if (r != size) LOGE("Can't read %s\n(%s)\n", v->device, strerror(errno)); + if (r != size) LOGE("Can't read %s\n(%s)\n", v->blk_device, strerror(errno)); mtd_read_close(read); if (r != size) return -1; @@ -120,16 +121,16 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in, MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { - LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } if (mtd_write_data(write, data, size) != size) { - LOGE("Can't write %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't write %s\n(%s)\n", v->blk_device, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { - LOGE("Can't finish %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't finish %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } @@ -161,20 +162,20 @@ static void wait_for_device(const char* fn) { static int get_bootloader_message_block(struct bootloader_message *out, const Volume* v) { - wait_for_device(v->device); - FILE* f = fopen(v->device, "rb"); + wait_for_device(v->blk_device); + FILE* f = fopen(v->blk_device, "rb"); if (f == NULL) { - LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } struct bootloader_message temp; int count = fread(&temp, sizeof(temp), 1, f); if (count != 1) { - LOGE("Failed reading %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Failed reading %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } if (fclose(f) != 0) { - LOGE("Failed closing %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Failed closing %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } memcpy(out, &temp, sizeof(temp)); @@ -183,19 +184,19 @@ static int get_bootloader_message_block(struct bootloader_message *out, static int set_bootloader_message_block(const struct bootloader_message *in, const Volume* v) { - wait_for_device(v->device); - FILE* f = fopen(v->device, "wb"); + wait_for_device(v->blk_device); + FILE* f = fopen(v->blk_device, "wb"); if (f == NULL) { - LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } int count = fwrite(in, sizeof(*in), 1, f); if (count != 1) { - LOGE("Failed writing %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Failed writing %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } if (fclose(f) != 0) { - LOGE("Failed closing %s\n(%s)\n", v->device, strerror(errno)); + LOGE("Failed closing %s\n(%s)\n", v->blk_device, strerror(errno)); return -1; } return 0; diff --git a/common.h b/common.h index a1168cdb..3587a31f 100644 --- a/common.h +++ b/common.h @@ -39,24 +39,7 @@ extern "C" { #define STRINGIFY(x) #x #define EXPAND(x) STRINGIFY(x) -typedef struct { - const char* mount_point; // eg. "/cache". must live in the root directory. - - const char* fs_type; // "yaffs2" or "ext4" or "vfat" - - const char* device; // MTD partition name if fs_type == "yaffs" - // block device if fs_type == "ext4" or "vfat" - - const char* device2; // alternative device to try if fs_type - // == "ext4" or "vfat" and mounting - // 'device' fails - - long long length; // (ext4 partition only) when - // formatting, size to use for the - // partition. 0 or negative number - // means to format all but the last - // (that much). -} Volume; +typedef struct fstab_rec Volume; // fopen a file, mounting volumes and making parent dirs as necessary. FILE* fopen_path(const char *path, const char *mode); diff --git a/roots.cpp b/roots.cpp index ca37cf14..09471225 100644 --- a/roots.cpp +++ b/roots.cpp @@ -22,120 +22,48 @@ #include #include +#include #include "mtdutils/mtdutils.h" #include "mtdutils/mounts.h" #include "roots.h" #include "common.h" #include "make_ext4fs.h" -static int num_volumes = 0; -static Volume* device_volumes = NULL; +static struct fstab *fstab = NULL; extern struct selabel_handle *sehandle; -static int parse_options(char* options, Volume* volume) { - char* option; - while ((option = strtok(options, ","))) { - options = NULL; +void load_volume_table() +{ + int i; + int ret; - if (strncmp(option, "length=", 7) == 0) { - volume->length = strtoll(option+7, NULL, 10); - } else { - LOGE("bad option \"%s\"\n", option); - return -1; - } - } - return 0; -} - -void load_volume_table() { - int alloc = 2; - device_volumes = (Volume*)malloc(alloc * sizeof(Volume)); - - // Insert an entry for /tmp, which is the ramdisk and is always mounted. - device_volumes[0].mount_point = "/tmp"; - device_volumes[0].fs_type = "ramdisk"; - device_volumes[0].device = NULL; - device_volumes[0].device2 = NULL; - device_volumes[0].length = 0; - num_volumes = 1; - - FILE* fstab = fopen("/etc/recovery.fstab", "r"); - if (fstab == NULL) { - LOGE("failed to open /etc/recovery.fstab (%s)\n", strerror(errno)); + fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); + if (!fstab) { + LOGE("failed to read /etc/recovery.fstab\n"); return; } - char buffer[1024]; - int i; - while (fgets(buffer, sizeof(buffer)-1, fstab)) { - for (i = 0; buffer[i] && isspace(buffer[i]); ++i); - if (buffer[i] == '\0' || buffer[i] == '#') continue; - - char* original = strdup(buffer); - - char* mount_point = strtok(buffer+i, " \t\n"); - char* fs_type = strtok(NULL, " \t\n"); - char* device = strtok(NULL, " \t\n"); - // lines may optionally have a second device, to use if - // mounting the first one fails. - char* options = NULL; - char* device2 = strtok(NULL, " \t\n"); - if (device2) { - if (device2[0] == '/') { - options = strtok(NULL, " \t\n"); - } else { - options = device2; - device2 = NULL; - } - } - - if (mount_point && fs_type && device) { - while (num_volumes >= alloc) { - alloc *= 2; - device_volumes = (Volume*)realloc(device_volumes, alloc*sizeof(Volume)); - } - device_volumes[num_volumes].mount_point = strdup(mount_point); - device_volumes[num_volumes].fs_type = strdup(fs_type); - device_volumes[num_volumes].device = strdup(device); - device_volumes[num_volumes].device2 = - device2 ? strdup(device2) : NULL; - - device_volumes[num_volumes].length = 0; - if (parse_options(options, device_volumes + num_volumes) != 0) { - LOGE("skipping malformed recovery.fstab line: %s\n", original); - } else { - ++num_volumes; - } - } else { - LOGE("skipping malformed recovery.fstab line: %s\n", original); - } - free(original); + ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk", 0); + if (ret < 0 ) { + LOGE("failed to add /tmp entry to fstab\n"); + fs_mgr_free_fstab(fstab); + fstab = NULL; + return; } - fclose(fstab); - printf("recovery filesystem table\n"); printf("=========================\n"); - for (i = 0; i < num_volumes; ++i) { - Volume* v = &device_volumes[i]; - printf(" %d %s %s %s %s %lld\n", i, v->mount_point, v->fs_type, - v->device, v->device2, v->length); + for (i = 0; i < fstab->num_entries; ++i) { + Volume* v = &fstab->recs[i]; + printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, + v->blk_device, v->length); } printf("\n"); } Volume* volume_for_path(const char* path) { - int i; - for (i = 0; i < num_volumes; ++i) { - Volume* v = device_volumes+i; - int len = strlen(v->mount_point); - if (strncmp(path, v->mount_point, len) == 0 && - (path[len] == '\0' || path[len] == '/')) { - return v; - } - } - return NULL; + return fs_mgr_get_entry_for_mount_point(fstab, path); } int ensure_path_mounted(const char* path) { @@ -169,27 +97,19 @@ int ensure_path_mounted(const char* path) { // mount an MTD partition as a YAFFS2 filesystem. mtd_scan_partitions(); const MtdPartition* partition; - partition = mtd_find_partition_by_name(v->device); + partition = mtd_find_partition_by_name(v->blk_device); if (partition == NULL) { LOGE("failed to find \"%s\" partition to mount at \"%s\"\n", - v->device, v->mount_point); + v->blk_device, v->mount_point); return -1; } return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0); } else if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "vfat") == 0) { - result = mount(v->device, v->mount_point, v->fs_type, + result = mount(v->blk_device, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); if (result == 0) return 0; - if (v->device2) { - LOGW("failed to mount %s (%s); trying %s\n", - v->device, strerror(errno), v->device2); - result = mount(v->device2, v->mount_point, v->fs_type, - MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); - if (result == 0) return 0; - } - LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno)); return -1; } @@ -249,31 +169,31 @@ int format_volume(const char* volume) { if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) { mtd_scan_partitions(); - const MtdPartition* partition = mtd_find_partition_by_name(v->device); + const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device); if (partition == NULL) { - LOGE("format_volume: no MTD partition \"%s\"\n", v->device); + LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device); return -1; } MtdWriteContext *write = mtd_write_partition(partition); if (write == NULL) { - LOGW("format_volume: can't open MTD \"%s\"\n", v->device); + LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device); return -1; } else if (mtd_erase_blocks(write, -1) == (off_t) -1) { - LOGW("format_volume: can't erase MTD \"%s\"\n", v->device); + LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device); mtd_write_close(write); return -1; } else if (mtd_write_close(write)) { - LOGW("format_volume: can't close MTD \"%s\"\n", v->device); + LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device); return -1; } return 0; } if (strcmp(v->fs_type, "ext4") == 0) { - int result = make_ext4fs(v->device, v->length, volume, sehandle); + int result = make_ext4fs(v->blk_device, v->length, volume, sehandle); if (result != 0) { - LOGE("format_volume: make_extf4fs failed on %s\n", v->device); + LOGE("format_volume: make_extf4fs failed on %s\n", v->blk_device); return -1; } return 0;