block: add remount paramter
[project/fstools.git] / jffs2reset.c
1 /*
2  * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 2.1
6  * as published by the Free Software Foundation
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <sys/mount.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/reboot.h>
18 #include <libubox/ulog.h>
19
20 #include <fcntl.h>
21 #include <dirent.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <getopt.h>
27
28
29 #include "libfstools/libfstools.h"
30 #include "libfstools/volume.h"
31
32 static int jffs2_mark(struct volume *v);
33
34 static int
35 ask_user(void)
36 {
37         ULOG_WARN("This will erase all settings and remove any installed packages. Are you sure? [N/y]\n");
38         if (getchar() != 'y')
39                 return -1;
40         return 0;
41 }
42
43 static int jffs2_reset(struct volume *v, int reset)
44 {
45         char *mp;
46
47         mp = find_mount_point(v->blk, 1);
48         if (mp) {
49                 ULOG_INFO("%s is mounted as %s, only erasing files\n", v->blk, mp);
50                 fs_state_set("/overlay", FS_STATE_PENDING);
51                 overlay_delete(mp, false);
52                 mount(mp, "/", NULL, MS_REMOUNT, 0);
53         } else {
54                 ULOG_INFO("%s is not mounted\n", v->blk);
55                 return jffs2_mark(v);
56         }
57
58         if (reset) {
59                 sync();
60                 sleep(2);
61                 reboot(RB_AUTOBOOT);
62                 while (1)
63                         ;
64         }
65
66         return 0;
67 }
68
69 static int jffs2_mark(struct volume *v)
70 {
71         __u32 deadc0de = __cpu_to_be32(0xdeadc0de);
72         size_t sz;
73         int fd;
74
75         fd = open(v->blk, O_WRONLY);
76         ULOG_INFO("%s will be erased on next mount\n", v->blk);
77         if (!fd) {
78                 ULOG_ERR("opening %s failed\n", v->blk);
79                 return -1;
80         }
81
82         sz = write(fd, &deadc0de, sizeof(deadc0de));
83         close(fd);
84
85         if (sz != 4) {
86                 ULOG_ERR("writing %s failed: %s\n", v->blk, strerror(errno));
87                 return -1;
88         }
89
90         return 0;
91 }
92
93 int main(int argc, char **argv)
94 {
95         struct volume *v;
96         int ch, yes = 0, reset = 0;
97         while ((ch = getopt(argc, argv, "yr")) != -1) {
98                 switch(ch) {
99                 case 'y':
100                         yes = 1;
101                         break;
102                 case 'r':
103                         reset = 1;
104                         break;
105                 }
106
107         }
108
109         if (!yes && ask_user())
110                 return -1;
111
112         /*
113          * TODO: Currently this only checks if kernel supports OverlayFS. We
114          * should check if there is a mount point using it with rootfs_data
115          * as upperdir.
116          */
117         if (find_filesystem("overlay")) {
118                 ULOG_ERR("overlayfs not supported by kernel\n");
119                 return -1;
120         }
121
122         v = volume_find("rootfs_data");
123         if (!v) {
124                 ULOG_ERR("MTD partition 'rootfs_data' not found\n");
125                 return -1;
126         }
127
128         if (!strcmp(*argv, "jffs2mark"))
129                 return jffs2_mark(v);
130         return jffs2_reset(v, reset);
131 }