block: get mountpoints from /proc/self/mountinfo
[project/fstools.git] / jffs2reset.c
index 122e03b..97fd0ab 100644 (file)
@@ -14,6 +14,8 @@
 #include <sys/mount.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/reboot.h>
+#include <libubox/ulog.h>
 
 #include <fcntl.h>
 #include <dirent.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <getopt.h>
+
 
 #include "libfstools/libfstools.h"
 #include "libfstools/volume.h"
 
-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))
-                       unlink(file);
-               free(namelist[n]);
-       }
-       free(namelist);
-
-       rmdir(dir);
-
-       return 0;
-}
+static int jffs2_mark(struct volume *v);
 
 static int
-ask_user(int argc, char **argv)
+ask_user(void)
 {
-       if ((argc < 2) || strcmp(argv[1], "-y")) {
-               fprintf(stderr, "This will erase all settings and remove any installed packages. Are you sure? [N/y]\n");
-               if (getchar() != 'y')
-                       return -1;
-       }
+       ULOG_WARN("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
-jffs2_reset(int argc, char **argv)
+static int jffs2_reset(struct volume *v, int reset)
 {
-       struct volume *v;
        char *mp;
 
-       if (ask_user(argc, argv))
-               return -1;
-
-       if (find_filesystem("overlay")) {
-               fprintf(stderr, "overlayfs not found\n");
-               return -1;
-       }
-
-       v = volume_find("rootfs_data");
-       if (!v) {
-               fprintf(stderr, "no rootfs_data was found\n");
-               return -1;
-       }
-
-       mp = find_mount_point(v->blk, "jffs2");
+       mp = find_mount_point(v->blk, 1);
        if (mp) {
-               fprintf(stderr, "%s is mounted as %s, only erasing files\n", v->blk, mp);
-               foreachdir(mp, handle_rmdir);
+               ULOG_INFO("%s is mounted as %s, only erasing files\n", v->blk, mp);
+               fs_state_set("/overlay", FS_STATE_PENDING);
+               overlay_delete(mp, false);
                mount(mp, "/", NULL, MS_REMOUNT, 0);
        } else {
-               fprintf(stderr, "%s is not mounted, erasing it\n", v->blk);
-               volume_erase_all(v);
+               ULOG_INFO("%s is not mounted\n", v->blk);
+               return jffs2_mark(v);
+       }
+
+       if (reset) {
+               sync();
+               sleep(2);
+               reboot(RB_AUTOBOOT);
+               while (1)
+                       ;
        }
 
        return 0;
 }
 
-static int
-jffs2_mark(int argc, char **argv)
+static int jffs2_mark(struct volume *v)
 {
        __u32 deadc0de = __cpu_to_be32(0xdeadc0de);
-       struct volume *v;
        size_t sz;
        int fd;
 
-       if (ask_user(argc, argv))
-               return -1;
-
-       v = volume_find("rootfs_data");
-       if (!v) {
-               fprintf(stderr, "no rootfs_data was found\n");
-               return -1;
-       }
-
        fd = open(v->blk, O_WRONLY);
-       fprintf(stderr, "%s - marking with deadc0de\n", v->blk);
+       ULOG_INFO("%s will be erased on next mount\n", v->blk);
        if (!fd) {
-               fprintf(stderr, "opening %s failed\n", v->blk);
+               ULOG_ERR("opening %s failed\n", v->blk);
                return -1;
        }
 
@@ -125,7 +83,7 @@ jffs2_mark(int argc, char **argv)
        close(fd);
 
        if (sz != 4) {
-               fprintf(stderr, "writing %s failed: %s\n", v->blk, strerror(errno));
+               ULOG_ERR("writing %s failed: %s\n", v->blk, strerror(errno));
                return -1;
        }
 
@@ -134,7 +92,40 @@ jffs2_mark(int argc, char **argv)
 
 int main(int argc, char **argv)
 {
+       struct volume *v;
+       int ch, yes = 0, reset = 0;
+       while ((ch = getopt(argc, argv, "yr")) != -1) {
+               switch(ch) {
+               case 'y':
+                       yes = 1;
+                       break;
+               case 'r':
+                       reset = 1;
+                       break;
+               }
+
+       }
+
+       if (!yes && ask_user())
+               return -1;
+
+       /*
+        * TODO: Currently this only checks if kernel supports OverlayFS. We
+        * should check if there is a mount point using it with rootfs_data
+        * as upperdir.
+        */
+       if (find_filesystem("overlay")) {
+               ULOG_ERR("overlayfs not supported by kernel\n");
+               return -1;
+       }
+
+       v = volume_find("rootfs_data");
+       if (!v) {
+               ULOG_ERR("MTD partition 'rootfs_data' not found\n");
+               return -1;
+       }
+
        if (!strcmp(*argv, "jffs2mark"))
-               return jffs2_mark(argc, argv);
-       return jffs2_reset(argc, argv);
+               return jffs2_mark(v);
+       return jffs2_reset(v, reset);
 }