X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubox.git;a=blobdiff_plain;f=mount_root.c;h=8868e40c68203612f18e0a8e4da27f41d3ff8713;hp=ad1de363544afa813d95b1a1fb87321e75003566;hb=2b32e9059166a23204fcf01e65a9184b3c39166b;hpb=3eddeb76f22273f540504de78cb147fe6d60c9f2 diff --git a/mount_root.c b/mount_root.c index ad1de36..8868e40 100644 --- a/mount_root.c +++ b/mount_root.c @@ -109,12 +109,16 @@ static char* find_mount(char *mp) while (fgets(line, sizeof(line), fp)) { char *s, *t = strstr(line, " "); - if (!t) + if (!t) { + fclose(fp); return NULL; + } t++; s = strstr(t, " "); - if (!s) + if (!s) { + fclose(fp); return NULL; + } *s = '\0'; if (!strcmp(t, mp)) { @@ -143,13 +147,16 @@ static char* find_mount_point(char *block, char *fs) char *p = &line[len + 1]; char *t = strstr(p, " "); - if (!t) + if (!t) { + fclose(fp); return NULL; + } *t = '\0'; t++; if (fs && strncmp(t, fs, strlen(fs))) { + fclose(fp); ERROR("block is mounted with wrong fs\n"); return NULL; } @@ -423,6 +430,9 @@ static int switch2jffs(void) { char mtd[32]; + if (!find_mtd_block("rootfs_patches", mtd, sizeof(mtd))) + return 0; + if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) { ERROR("no rootfs_data was found\n"); return -1; @@ -490,6 +500,139 @@ static int handle_whiteout(const char *dir) return 0; } +static int mtd_erase(const char *mtd) +{ + int fd = open(mtd, O_RDWR | O_SYNC); + struct mtd_info_user i; + struct erase_info_user e; + int ret; + + if (!fd) { + ERROR("failed to open %s: %s\n", mtd, strerror(errno)); + return -1; + } + + ret = ioctl(fd, MEMGETINFO, &i); + if (ret) { + ERROR("ioctl(%s, MEMGETINFO) failed: %s\n", mtd, strerror(errno)); + return -1; + } + + e.length = i.erasesize; + for (e.start = 0; e.start < i.size; e.start += i.erasesize) { + ioctl(fd, MEMUNLOCK, &e); + if(ioctl(fd, MEMERASE, &e)) + ERROR("Failed to erase block on %s at 0x%x\n", mtd, e.start); + } + + close(fd); + return 0; +} + +static int ask_user(int argc, char **argv) +{ + if ((argc < 2) || strcmp(argv[1], "-y")) { + LOG("This will erase all settings and remove any installed packages. Are you sure? [N/y]\n"); + if (getchar() != 'y') + return -1; + } + return 0; + +} + +static int handle_rmdir(const char *dir) +{ + struct stat s; + struct dirent **namelist; + int n; + + n = scandir(dir, &namelist, NULL, NULL); + + if (n < 1) + return -1; + + while (n--) { + char file[256]; + + snprintf(file, sizeof(file), "%s%s", dir, namelist[n]->d_name); + if (!lstat(file, &s) && !S_ISDIR(s.st_mode)) { + DEBUG(1, "unlinking %s\n", file); + unlink(file); + } + free(namelist[n]); + } + free(namelist); + + DEBUG(1, "rmdir %s\n", dir); + rmdir(dir); + + return 0; +} + +static int main_jffs2reset(int argc, char **argv) +{ + char mtd[32]; + char *mp; + + if (ask_user(argc, argv)) + return -1; + + if (check_fs_exists("overlay")) { + ERROR("overlayfs not found\n"); + return -1; + } + + if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) { + ERROR("no rootfs_data was found\n"); + return -1; + } + + mp = find_mount_point(mtd, "jffs2"); + if (mp) { + LOG("%s is mounted as %s, only erasing files\n", mtd, mp); + foreachdir(mp, handle_rmdir); + mount(mp, "/", NULL, MS_REMOUNT, 0); + } else { + LOG("%s is not mounted, erasing it\n", mtd); + find_mtd_char("rootfs_data", mtd, sizeof(mtd)); + mtd_erase(mtd); + } + + return 0; +} + +static int main_jffs2mark(int argc, char **argv) +{ + FILE *fp; + __u32 deadc0de = __cpu_to_be32(0xdeadc0de); + char mtd[32]; + size_t sz; + + if (ask_user(argc, argv)) + return -1; + + if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) { + ERROR("no rootfs_data was found\n"); + return -1; + } + + fp = fopen(mtd, "w"); + LOG("%s - marking with deadc0de\n", mtd); + if (!fp) { + ERROR("opening %s failed\n", mtd); + return -1; + } + + sz = fwrite(&deadc0de, sizeof(deadc0de), 1, fp); + fclose(fp); + + if (sz != 1) { + ERROR("writing %s failed: %s\n", mtd, strerror(errno)); + return -1; + } + + return 0; + } static int main_switch2jffs(int argc, char **argv) { char mtd[32]; @@ -544,50 +687,65 @@ static int main_switch2jffs(int argc, char **argv) return ret; } -static int extroot(void) +static int extroot(const char *prefix) { + char block_path[32]; + char kmod_loader[64]; struct stat s; pid_t pid; - if (stat("/sbin/block", &s)) + sprintf(block_path, "%s/sbin/block", prefix); + + if (stat(block_path, &s)) return -1; + sprintf(kmod_loader, "/sbin/kmodloader %s/etc/modules-boot.d/ %s", prefix, prefix); + system(kmod_loader); + pid = fork(); if (!pid) { mkdir("/tmp/extroot", 0755); - execl("/sbin/block", "/sbin/block", "extroot", NULL); + execl(block_path, block_path, "extroot", NULL); exit(-1); } else if (pid > 0) { int status; waitpid(pid, &status, 0); if (!WEXITSTATUS(status)) { - if (find_mount("/tmp/mnt")) { + if (find_mount("/tmp/extroot/mnt")) { mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT | MS_RDONLY, 0); - mkdir("/tmp/mnt/proc", 0755); - mkdir("/tmp/mnt/dev", 0755); - mkdir("/tmp/mnt/sys", 0755); - mkdir("/tmp/mnt/tmp", 0755); - mkdir("/tmp/mnt/rom", 0755); + mkdir("/tmp/extroot/mnt/proc", 0755); + mkdir("/tmp/extroot/mnt/dev", 0755); + mkdir("/tmp/extroot/mnt/sys", 0755); + mkdir("/tmp/extroot/mnt/tmp", 0755); + mkdir("/tmp/extroot/mnt/rom", 0755); - if (mount_move("/tmp", "", "/mnt")) { + if (mount_move("/tmp/extroot", "", "/mnt")) { ERROR("moving pivotroot failed - continue normal boot\n"); - umount("/tmp/mnt"); + umount("/tmp/extroot/mnt"); } else if (pivot("/mnt", "/rom")) { ERROR("switching to pivotroot failed - continue normal boot\n"); umount("/mnt"); } else { + umount("/tmp/overlay"); + rmdir("/tmp/overlay"); + rmdir("/tmp/extroot/mnt"); + rmdir("/tmp/extroot"); return 0; } - } else if (find_mount("/tmp/overlay")) { - if (mount_move("/tmp", "", "/overlay")) { + } else if (find_mount("/tmp/extroot/overlay")) { + if (mount_move("/tmp/extroot", "", "/overlay")) { ERROR("moving extroot failed - continue normal boot\n"); - umount("/tmp/overlay"); + umount("/tmp/extroot/overlay"); } else if (fopivot("/overlay", "/rom")) { ERROR("switching to extroot failed - continue normal boot\n"); umount("/overlay"); } else { + umount("/tmp/overlay"); + rmdir("/tmp/overlay"); + rmdir("/tmp/extroot/overlay"); + rmdir("/tmp/extroot"); return 0; } } @@ -603,19 +761,27 @@ int main(int argc, char **argv) argv0 = basename(*argv); + if (!strcmp(basename(*argv), "jffs2mark")) + return main_jffs2mark(argc, argv); + + if (!strcmp(basename(*argv), "jffs2reset")) + return main_jffs2reset(argc, argv); + if (!strcmp(basename(*argv), "switch2jffs")) return main_switch2jffs(argc, argv); if (!getenv("PREINIT")) return -1; - if (find_mtd_char("rootfs_data", mtd, sizeof(mtd))) { + if (!find_mtd_block("rootfs_patches", mtd, sizeof(mtd))) { + ramoverlay(); + } else if (find_mtd_char("rootfs_data", mtd, sizeof(mtd))) { if (!find_mtd_char("rootfs", mtd, sizeof(mtd))) mtd_unlock(mtd); LOG("mounting /dev/root\n"); mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT, 0); } else { - if (!extroot()) { + if (!extroot("")) { fprintf(stderr, "mount_root: switched to extroot\n"); return 0; } @@ -634,6 +800,12 @@ int main(int argc, char **argv) } mtd_mount_jffs2(); + + if (!extroot("/tmp/overlay")) { + fprintf(stderr, "mount_root: switched to extroot\n"); + return 0; + } + DEBUG(1, "switching to jffs2\n"); if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) { ERROR("switching to jffs2 failed - fallback to ramoverlay\n");