X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubox.git;a=blobdiff_plain;f=block.c;h=194eb4a17c7ac85353b9e8a19d2ddc2f9fb6b0c1;hp=4bbfeb0f98257bbab1e4896309dfdfc00b5861e9;hb=75b17dab43c511d1cecc70c370e9f8283dfbf547;hpb=0a4e3d257da46a7c0232362ac82a01a8c15ae6d5 diff --git a/block.c b/block.c index 4bbfeb0..194eb4a 100644 --- a/block.c +++ b/block.c @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#define _GNU_SOURCE #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -57,7 +59,7 @@ struct mount { static struct vlist_tree mounts; static struct blob_buf b; static LIST_HEAD(devices); -static int anon_mount, anon_swap, auto_mount, auto_swap; +static int anon_mount, anon_swap, auto_mount, auto_swap, check_fs; static unsigned int delay_root; enum { @@ -66,6 +68,7 @@ enum { CFG_AUTO_MOUNT, CFG_AUTO_SWAP, CFG_DELAY_ROOT, + CFG_CHECK_FS, __CFG_MAX }; @@ -75,6 +78,7 @@ static const struct blobmsg_policy config_policy[__CFG_MAX] = { [CFG_AUTO_SWAP] = { .name = "auto_swap", .type = BLOBMSG_TYPE_INT32 }, [CFG_AUTO_MOUNT] = { .name = "auto_mount", .type = BLOBMSG_TYPE_INT32 }, [CFG_DELAY_ROOT] = { .name = "delay_root", .type = BLOBMSG_TYPE_INT32 }, + [CFG_CHECK_FS] = { .name = "check_fs", .type = BLOBMSG_TYPE_INT32 }, }; enum { @@ -134,6 +138,14 @@ static char *blobmsg_get_strdup(struct blob_attr *attr) return strdup(blobmsg_get_string(attr)); } +static char *blobmsg_get_basename(struct blob_attr *attr) +{ + if (!attr) + return NULL; + + return strdup(basename(blobmsg_get_string(attr))); +} + static int mount_add(struct uci_section *s) { struct blob_attr *tb[__MOUNT_MAX] = { 0 }; @@ -155,7 +167,7 @@ static int mount_add(struct uci_section *s) m->label = blobmsg_get_strdup(tb[MOUNT_LABEL]); m->target = blobmsg_get_strdup(tb[MOUNT_TARGET]); m->options = blobmsg_get_strdup(tb[MOUNT_OPTIONS]); - m->device = blobmsg_get_strdup(tb[MOUNT_DEVICE]); + m->device = blobmsg_get_basename(tb[MOUNT_DEVICE]); m->overlay = m->extroot = 0; if (m->target && !strcmp(m->target, "/")) m->extroot = 1; @@ -188,7 +200,7 @@ static int swap_add(struct uci_section *s) memset(m, 0, sizeof(struct mount)); m->type = TYPE_SWAP; m->uuid = blobmsg_get_strdup(tb[SWAP_UUID]); - m->device = blobmsg_get_strdup(tb[SWAP_DEVICE]); + m->device = blobmsg_get_basename(tb[SWAP_DEVICE]); if (tb[SWAP_PRIO]) m->prio = blobmsg_get_u32(tb[SWAP_PRIO]); if (m->prio) @@ -221,6 +233,9 @@ static int global_add(struct uci_section *s) if (tb[CFG_DELAY_ROOT]) delay_root = blobmsg_get_u32(tb[CFG_DELAY_ROOT]); + if ((tb[CFG_CHECK_FS]) && blobmsg_get_u32(tb[CFG_CHECK_FS])) + check_fs = 1; + return 0; } @@ -313,7 +328,7 @@ static int _cache_load(const char *path) struct blkid_struct_probe *pr = malloc(sizeof(struct blkid_struct_probe)); memset(pr, 0, sizeof(struct blkid_struct_probe)); probe_block(gl.gl_pathv[j], pr); - if (pr->err) + if (pr->err || !pr->id) free(pr); else list_add_tail(&pr->list, &devices); @@ -330,6 +345,10 @@ static void cache_load(int mtd) _cache_load("/dev/mtdblock*"); _cache_load("/dev/mmcblk*"); _cache_load("/dev/sd*"); + _cache_load("/dev/sdc*"); + _cache_load("/dev/hd*"); + _cache_load("/dev/md*"); + _cache_load("/dev/mapper/*"); } static int print_block_info(struct blkid_struct_probe *pr) @@ -363,7 +382,7 @@ static int print_block_uci(struct blkid_struct_probe *pr) if (pr->uuid[0]) printf("\toption\tuuid\t'%s'\n", pr->uuid); else - printf("\toption\tdevice\t'%s'\n", basename(pr->dev)); + printf("\toption\tdevice\t'%s'\n", pr->dev); printf("\toption\tenabled\t'0'\n\n"); return 0; @@ -431,14 +450,45 @@ static void mkdir_p(char *dir) } } +static void check_filesystem(struct blkid_struct_probe *pr) +{ + pid_t pid; + struct stat statbuf; + char *e2fsck = "/usr/sbin/e2fsck"; + + if (strncmp(pr->id->name, "ext", 3)) { + fprintf(stderr, "check_filesystem: %s is not supported\n", pr->id->name); + return; + } + + if (stat(e2fsck, &statbuf) < 0) { + fprintf(stderr, "check_filesystem: %s not found\n", e2fsck); + return; + } + + pid = fork(); + if (!pid) { + execl(e2fsck, e2fsck, "-p", pr->dev, NULL); + exit(-1); + } else if (pid > 0) { + int status; + + waitpid(pid, &status, 0); + if (WEXITSTATUS(status)) + fprintf(stderr, "check_filesystem: %s returned %d\n", e2fsck, WEXITSTATUS(status)); + } +} + static int mount_device(struct blkid_struct_probe *pr, int hotplug) { struct mount *m; - char *device = basename(pr->dev); + char *device; if (!pr) return -1; + device = basename(pr->dev); + if (!strcmp(pr->id->name, "swap")) { if (hotplug && !auto_swap) return -1; @@ -463,7 +513,7 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) if (m) { char *target = m->target; - char _target[] = "/mnt/mmcblk123"; + char _target[32]; int err = 0; if (!target) { @@ -471,6 +521,10 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) target = _target; } mkdir_p(target); + + if (check_fs) + check_filesystem(pr); + err = mount(pr->dev, target, pr->id->name, 0, (m->options) ? (m->options) : ("")); if (err) fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", @@ -484,6 +538,10 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) snprintf(target, sizeof(target), "/mnt/%s", device); mkdir_p(target); + + if (check_fs) + check_filesystem(pr); + err = mount(pr->dev, target, pr->id->name, 0, ""); if (err) fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", @@ -605,7 +663,7 @@ static int check_extroot(char *path) if (!strcmp(pr->dev, fs)) { struct stat s; FILE *fp = NULL; - char tag[32]; + char tag[64]; char uuid[32] = { 0 }; snprintf(tag, sizeof(tag), "%s/etc/.extroot-uuid", path); @@ -639,8 +697,8 @@ static int check_extroot(char *path) static int mount_extroot(char *cfg) { - char overlay[] = "/tmp/overlay"; - char mnt[] = "/tmp/mnt"; + char overlay[] = "/tmp/extroot/overlay"; + char mnt[] = "/tmp/extroot/mnt"; char *path = mnt; struct blkid_struct_probe *pr; struct mount *m; @@ -659,8 +717,10 @@ static int mount_extroot(char *cfg) pr = find_block_info(m->uuid, m->label, NULL); if (!pr && delay_root){ - fprintf(stderr, "extroot: is not ready yet, retrying in %ui seconds\n", delay_root); + fprintf(stderr, "extroot: is not ready yet, retrying in %u seconds\n", delay_root); sleep(delay_root); + mkblkdev(); + cache_load(0); pr = find_block_info(m->uuid, m->label, NULL); } if (pr) { @@ -672,6 +732,9 @@ static int mount_extroot(char *cfg) path = overlay; mkdir_p(path); + if (check_fs) + check_filesystem(pr); + err = mount(pr->dev, path, pr->id->name, 0, (m->options) ? (m->options) : ("")); if (err) { @@ -741,7 +804,7 @@ static int main_mount(int argc, char **argv) if (config_load(NULL)) return -1; - cache_load(0); + cache_load(1); list_for_each_entry(pr, &devices, list) mount_device(pr, 0); @@ -771,8 +834,9 @@ static int main_detect(int argc, char **argv) printf("\toption\tanon_swap\t'0'\n"); printf("\toption\tanon_mount\t'0'\n"); printf("\toption\tauto_swap\t'1'\n"); - printf("\toption\tauto_mount\t'1'\n\n"); - printf("\toption\tdelay_root\t'0'\n\n"); + printf("\toption\tauto_mount\t'1'\n"); + printf("\toption\tdelay_root\t'5'\n"); + printf("\toption\tcheck_fs\t'0'\n\n"); list_for_each_entry(pr, &devices, list) print_block_uci(pr); @@ -814,11 +878,25 @@ static int main_info(int argc, char **argv) static int main_swapon(int argc, char **argv) { if (argc != 2) { - fprintf(stderr, "Usage: swapoff [-a] [DEVICE]\n\nStop swapping on DEVICE\n\n\t-a Stop swapping on all swap devices\n"); + fprintf(stderr, "Usage: swapon <-s> <-a> [DEVICE]\n\n\tStart swapping on [DEVICE]\n -a\tStart swapping on all swap devices\n -s\tShow summary\n"); return -1; } - if (!strcmp(argv[1], "-a")) { + if (!strcmp(argv[1], "-s")) { + FILE *fp = fopen("/proc/swaps", "r"); + char *lineptr = NULL; + size_t s; + + if (!fp) { + fprintf(stderr, "failed to open /proc/swaps\n"); + return -1; + } + while (getline(&lineptr, &s, fp) > 0) + printf(lineptr); + if (lineptr) + free(lineptr); + fclose(fp); + } else if (!strcmp(argv[1], "-a")) { struct blkid_struct_probe *pr; cache_load(0); @@ -832,8 +910,8 @@ static int main_swapon(int argc, char **argv) struct stat s; int err; - if (stat(argv[1], &s) || !S_ISBLK(s.st_mode)) { - fprintf(stderr, "%s is not a block device\n", argv[1]); + if (stat(argv[1], &s) || (!S_ISBLK(s.st_mode) && !S_ISREG(s.st_mode))) { + fprintf(stderr, "%s is not a block device or file\n", argv[1]); return -1; } err = swapon(argv[1], 0); @@ -849,7 +927,7 @@ static int main_swapon(int argc, char **argv) static int main_swapoff(int argc, char **argv) { if (argc != 2) { - fprintf(stderr, "Usage: swapoff [-a] [DEVICE]\n\nStop swapping on DEVICE\n\n\t-a Stop swapping on all swap devices\n"); + fprintf(stderr, "Usage: swapoff [-a] [DEVICE]\n\n\tStop swapping on DEVICE\n -a\tStop swapping on all swap devices\n"); return -1; } @@ -878,8 +956,8 @@ static int main_swapoff(int argc, char **argv) struct stat s; int err; - if (stat(argv[1], &s) || !S_ISBLK(s.st_mode)) { - fprintf(stderr, "%s is not a block device\n", argv[1]); + if (stat(argv[1], &s) || (!S_ISBLK(s.st_mode) && !S_ISREG(s.st_mode))) { + fprintf(stderr, "%s is not a block device or file\n", argv[1]); return -1; } err = swapoff(argv[1]);