xref: /aosp_15_r20/external/toybox/toys/pending/fsck.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* fsck.c -  check and repair a Linux filesystem
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Sandeep Sharma <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker 
6*cf5a6c84SAndroid Build Coastguard Worker USE_FSCK(NEWTOY(fsck, "?t:ANPRTVsC#", TOYFLAG_USR|TOYFLAG_BIN))
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker config FSCK
9*cf5a6c84SAndroid Build Coastguard Worker   bool "fsck"
10*cf5a6c84SAndroid Build Coastguard Worker   default n
11*cf5a6c84SAndroid Build Coastguard Worker   help
12*cf5a6c84SAndroid Build Coastguard Worker     usage: fsck [-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]...
13*cf5a6c84SAndroid Build Coastguard Worker 
14*cf5a6c84SAndroid Build Coastguard Worker     Check and repair filesystems
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     -A      Walk /etc/fstab and check all filesystems
17*cf5a6c84SAndroid Build Coastguard Worker     -N      Don't execute, just show what would be done
18*cf5a6c84SAndroid Build Coastguard Worker     -P      With -A, check filesystems in parallel
19*cf5a6c84SAndroid Build Coastguard Worker     -R      With -A, skip the root filesystem
20*cf5a6c84SAndroid Build Coastguard Worker     -T      Don't show title on startup
21*cf5a6c84SAndroid Build Coastguard Worker     -V      Verbose
22*cf5a6c84SAndroid Build Coastguard Worker     -C n    Write status information to specified file descriptor
23*cf5a6c84SAndroid Build Coastguard Worker     -t TYPE List of filesystem types to check
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker */
26*cf5a6c84SAndroid Build Coastguard Worker 
27*cf5a6c84SAndroid Build Coastguard Worker #define FOR_fsck
28*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
29*cf5a6c84SAndroid Build Coastguard Worker #include <mntent.h>
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker #define FLAG_WITHOUT_NO_PRFX 1
32*cf5a6c84SAndroid Build Coastguard Worker #define FLAG_WITH_NO_PRFX 2
33*cf5a6c84SAndroid Build Coastguard Worker #define FLAG_DONE 1
34*cf5a6c84SAndroid Build Coastguard Worker 
35*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
36*cf5a6c84SAndroid Build Coastguard Worker   int fd_num;
37*cf5a6c84SAndroid Build Coastguard Worker   char *t_list;
38*cf5a6c84SAndroid Build Coastguard Worker 
39*cf5a6c84SAndroid Build Coastguard Worker   struct double_list *devices;
40*cf5a6c84SAndroid Build Coastguard Worker   char *arr_flag;
41*cf5a6c84SAndroid Build Coastguard Worker   char **arr_type;
42*cf5a6c84SAndroid Build Coastguard Worker   int negate;
43*cf5a6c84SAndroid Build Coastguard Worker   int sum_status;
44*cf5a6c84SAndroid Build Coastguard Worker   int nr_run;
45*cf5a6c84SAndroid Build Coastguard Worker   int sig_num;
46*cf5a6c84SAndroid Build Coastguard Worker   long max_nr_run;
47*cf5a6c84SAndroid Build Coastguard Worker )
48*cf5a6c84SAndroid Build Coastguard Worker 
49*cf5a6c84SAndroid Build Coastguard Worker struct f_sys_info {
50*cf5a6c84SAndroid Build Coastguard Worker   char *device, *mountpt, *type, *opts;
51*cf5a6c84SAndroid Build Coastguard Worker   int passno, flag;
52*cf5a6c84SAndroid Build Coastguard Worker   struct f_sys_info *next;
53*cf5a6c84SAndroid Build Coastguard Worker };
54*cf5a6c84SAndroid Build Coastguard Worker 
55*cf5a6c84SAndroid Build Coastguard Worker struct child_list {
56*cf5a6c84SAndroid Build Coastguard Worker   struct child_list *next;
57*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
58*cf5a6c84SAndroid Build Coastguard Worker   char *prog_name, *dev_name;
59*cf5a6c84SAndroid Build Coastguard Worker };
60*cf5a6c84SAndroid Build Coastguard Worker 
61*cf5a6c84SAndroid Build Coastguard Worker static struct f_sys_info *filesys_info = NULL; //fstab entry list
62*cf5a6c84SAndroid Build Coastguard Worker static struct child_list *c_list = NULL; //fsck.type child list.
63*cf5a6c84SAndroid Build Coastguard Worker 
kill_all(void)64*cf5a6c84SAndroid Build Coastguard Worker static void kill_all(void)
65*cf5a6c84SAndroid Build Coastguard Worker {
66*cf5a6c84SAndroid Build Coastguard Worker   struct child_list *child;
67*cf5a6c84SAndroid Build Coastguard Worker 
68*cf5a6c84SAndroid Build Coastguard Worker   for (child = c_list; child; child = child->next)
69*cf5a6c84SAndroid Build Coastguard Worker     kill(child->pid, SIGTERM);
70*cf5a6c84SAndroid Build Coastguard Worker   _exit(0);
71*cf5a6c84SAndroid Build Coastguard Worker }
72*cf5a6c84SAndroid Build Coastguard Worker 
strtol_range(char * str,int min,int max)73*cf5a6c84SAndroid Build Coastguard Worker static long strtol_range(char *str, int min, int max)
74*cf5a6c84SAndroid Build Coastguard Worker {
75*cf5a6c84SAndroid Build Coastguard Worker   char *endptr = NULL;
76*cf5a6c84SAndroid Build Coastguard Worker   errno = 0;
77*cf5a6c84SAndroid Build Coastguard Worker   long ret_value = strtol(str, &endptr, 10);
78*cf5a6c84SAndroid Build Coastguard Worker 
79*cf5a6c84SAndroid Build Coastguard Worker   if(errno) perror_exit("Invalid num %s", str);
80*cf5a6c84SAndroid Build Coastguard Worker   else if(endptr && (*endptr != '\0' || endptr == str))
81*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("Not a valid num %s", str);
82*cf5a6c84SAndroid Build Coastguard Worker   if(ret_value >= min && ret_value <= max) return ret_value;
83*cf5a6c84SAndroid Build Coastguard Worker   else perror_exit("Number %s is not in valid [%d-%d] Range", str, min, max);
84*cf5a6c84SAndroid Build Coastguard Worker }
85*cf5a6c84SAndroid Build Coastguard Worker 
86*cf5a6c84SAndroid Build Coastguard Worker //create fstab entries list.
create_db(struct mntent * f_info)87*cf5a6c84SAndroid Build Coastguard Worker static struct f_sys_info* create_db(struct mntent *f_info)
88*cf5a6c84SAndroid Build Coastguard Worker {
89*cf5a6c84SAndroid Build Coastguard Worker   struct f_sys_info *temp = filesys_info;
90*cf5a6c84SAndroid Build Coastguard Worker   if (temp) {
91*cf5a6c84SAndroid Build Coastguard Worker     while (temp->next) temp = temp->next;
92*cf5a6c84SAndroid Build Coastguard Worker     temp->next = xzalloc(sizeof(struct f_sys_info));
93*cf5a6c84SAndroid Build Coastguard Worker     temp = temp->next;
94*cf5a6c84SAndroid Build Coastguard Worker   } else filesys_info = temp = xzalloc(sizeof(struct f_sys_info));
95*cf5a6c84SAndroid Build Coastguard Worker 
96*cf5a6c84SAndroid Build Coastguard Worker   temp->device = xstrdup(f_info->mnt_fsname);
97*cf5a6c84SAndroid Build Coastguard Worker   temp->mountpt = xstrdup(f_info->mnt_dir);
98*cf5a6c84SAndroid Build Coastguard Worker   if (strchr(f_info->mnt_type, ',')) temp->type = xstrdup("auto");
99*cf5a6c84SAndroid Build Coastguard Worker   else  temp->type = xstrdup(f_info->mnt_type);
100*cf5a6c84SAndroid Build Coastguard Worker   temp->opts = xstrdup(f_info->mnt_opts);
101*cf5a6c84SAndroid Build Coastguard Worker   temp->passno = f_info->mnt_passno;
102*cf5a6c84SAndroid Build Coastguard Worker   return temp;
103*cf5a6c84SAndroid Build Coastguard Worker }
104*cf5a6c84SAndroid Build Coastguard Worker 
105*cf5a6c84SAndroid Build Coastguard Worker //is we have 'no' or ! before type.
is_no_prefix(char ** p)106*cf5a6c84SAndroid Build Coastguard Worker static int is_no_prefix(char **p)
107*cf5a6c84SAndroid Build Coastguard Worker {
108*cf5a6c84SAndroid Build Coastguard Worker   int no = 0;
109*cf5a6c84SAndroid Build Coastguard Worker 
110*cf5a6c84SAndroid Build Coastguard Worker   if ((*p[0] == 'n' && *(*p + 1) == 'o')) no = 2;
111*cf5a6c84SAndroid Build Coastguard Worker   else if (*p[0] == '!') no = 1;
112*cf5a6c84SAndroid Build Coastguard Worker   *p += no;
113*cf5a6c84SAndroid Build Coastguard Worker   return ((no) ? 1 :0);
114*cf5a6c84SAndroid Build Coastguard Worker }
115*cf5a6c84SAndroid Build Coastguard Worker 
fix_tlist(void)116*cf5a6c84SAndroid Build Coastguard Worker static void fix_tlist(void)
117*cf5a6c84SAndroid Build Coastguard Worker {
118*cf5a6c84SAndroid Build Coastguard Worker   char *p, *s = TT.t_list;
119*cf5a6c84SAndroid Build Coastguard Worker   int n = 1, no;
120*cf5a6c84SAndroid Build Coastguard Worker 
121*cf5a6c84SAndroid Build Coastguard Worker   while ((s = strchr(s, ','))) {
122*cf5a6c84SAndroid Build Coastguard Worker     s++;
123*cf5a6c84SAndroid Build Coastguard Worker     n++;
124*cf5a6c84SAndroid Build Coastguard Worker   }
125*cf5a6c84SAndroid Build Coastguard Worker 
126*cf5a6c84SAndroid Build Coastguard Worker   TT.arr_flag = xzalloc(n + 1);
127*cf5a6c84SAndroid Build Coastguard Worker   TT.arr_type = xzalloc((n + 1) * sizeof(char *));
128*cf5a6c84SAndroid Build Coastguard Worker   s = TT.t_list;
129*cf5a6c84SAndroid Build Coastguard Worker   n = 0;
130*cf5a6c84SAndroid Build Coastguard Worker   while ((p = strsep(&s, ","))) {
131*cf5a6c84SAndroid Build Coastguard Worker     no = is_no_prefix(&p);
132*cf5a6c84SAndroid Build Coastguard Worker     if (!strcmp(p, "loop")) {
133*cf5a6c84SAndroid Build Coastguard Worker       TT.arr_flag[n] = no ? FLAG_WITH_NO_PRFX :FLAG_WITHOUT_NO_PRFX;
134*cf5a6c84SAndroid Build Coastguard Worker       TT.negate = no;
135*cf5a6c84SAndroid Build Coastguard Worker     } else if (!strncmp(p, "opts=", 5)) {
136*cf5a6c84SAndroid Build Coastguard Worker       p+=5;
137*cf5a6c84SAndroid Build Coastguard Worker       TT.arr_flag[n] = is_no_prefix(&p) ?FLAG_WITH_NO_PRFX :FLAG_WITHOUT_NO_PRFX;
138*cf5a6c84SAndroid Build Coastguard Worker       TT.negate = no;
139*cf5a6c84SAndroid Build Coastguard Worker     } else {
140*cf5a6c84SAndroid Build Coastguard Worker       if (!n) TT.negate = no;
141*cf5a6c84SAndroid Build Coastguard Worker       if (n && TT.negate != no) error_exit("either all or none of the filesystem"
142*cf5a6c84SAndroid Build Coastguard Worker           " types passed to -t must be prefixed with 'no' or '!'");
143*cf5a6c84SAndroid Build Coastguard Worker     }
144*cf5a6c84SAndroid Build Coastguard Worker     TT.arr_type[n++] = p;
145*cf5a6c84SAndroid Build Coastguard Worker   }
146*cf5a6c84SAndroid Build Coastguard Worker }
147*cf5a6c84SAndroid Build Coastguard Worker 
148*cf5a6c84SAndroid Build Coastguard Worker //ignore these types...
ignore_type(char * type)149*cf5a6c84SAndroid Build Coastguard Worker static int ignore_type(char *type)
150*cf5a6c84SAndroid Build Coastguard Worker {
151*cf5a6c84SAndroid Build Coastguard Worker   int i = 0;
152*cf5a6c84SAndroid Build Coastguard Worker   char *str;
153*cf5a6c84SAndroid Build Coastguard Worker   char *ignored_types[] = {
154*cf5a6c84SAndroid Build Coastguard Worker     "ignore","iso9660", "nfs","proc",
155*cf5a6c84SAndroid Build Coastguard Worker     "sw","swap", "tmpfs","devpts",NULL
156*cf5a6c84SAndroid Build Coastguard Worker   };
157*cf5a6c84SAndroid Build Coastguard Worker   while ((str = ignored_types[i++])) {
158*cf5a6c84SAndroid Build Coastguard Worker     if (!strcmp(str, type)) return 1;
159*cf5a6c84SAndroid Build Coastguard Worker   }
160*cf5a6c84SAndroid Build Coastguard Worker   return 0;
161*cf5a6c84SAndroid Build Coastguard Worker }
162*cf5a6c84SAndroid Build Coastguard Worker 
163*cf5a6c84SAndroid Build Coastguard Worker // return true if has to ignore the filesystem.
to_be_ignored(struct f_sys_info * finfo)164*cf5a6c84SAndroid Build Coastguard Worker static int to_be_ignored(struct f_sys_info *finfo)
165*cf5a6c84SAndroid Build Coastguard Worker {
166*cf5a6c84SAndroid Build Coastguard Worker   int i, ret = 0, type_present = 0;
167*cf5a6c84SAndroid Build Coastguard Worker 
168*cf5a6c84SAndroid Build Coastguard Worker   if (!finfo->passno) return 1; //Ignore with pass num = 0
169*cf5a6c84SAndroid Build Coastguard Worker   if (TT.arr_type) {
170*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0; TT.arr_type[i]; i++) {
171*cf5a6c84SAndroid Build Coastguard Worker       if (!TT.arr_flag[i]) { //it is type of filesys.
172*cf5a6c84SAndroid Build Coastguard Worker         type_present = 2;
173*cf5a6c84SAndroid Build Coastguard Worker         if (!strcmp(TT.arr_type[i], finfo->type)) ret = 0;
174*cf5a6c84SAndroid Build Coastguard Worker         else ret = 1;
175*cf5a6c84SAndroid Build Coastguard Worker       } else if (TT.arr_flag[i] == FLAG_WITH_NO_PRFX) { //it is option of filesys
176*cf5a6c84SAndroid Build Coastguard Worker         if (hasmntopt((const struct mntent *)finfo, TT.arr_type[i])) return 1;
177*cf5a6c84SAndroid Build Coastguard Worker       } else { //FLAG_WITHOUT_NO_PRFX
178*cf5a6c84SAndroid Build Coastguard Worker         if (!hasmntopt((const struct mntent *)finfo, TT.arr_type[i])) return 1;
179*cf5a6c84SAndroid Build Coastguard Worker       }
180*cf5a6c84SAndroid Build Coastguard Worker     }
181*cf5a6c84SAndroid Build Coastguard Worker   }
182*cf5a6c84SAndroid Build Coastguard Worker   if (ignore_type(finfo->type)) return 1;
183*cf5a6c84SAndroid Build Coastguard Worker   if (TT.arr_type && type_present != 2) return 0;
184*cf5a6c84SAndroid Build Coastguard Worker   return ((TT.negate) ? !ret : ret);
185*cf5a6c84SAndroid Build Coastguard Worker }
186*cf5a6c84SAndroid Build Coastguard Worker 
187*cf5a6c84SAndroid Build Coastguard Worker // find type and execute corresponding fsck.type prog.
do_fsck(struct f_sys_info * finfo)188*cf5a6c84SAndroid Build Coastguard Worker static void do_fsck(struct f_sys_info *finfo)
189*cf5a6c84SAndroid Build Coastguard Worker {
190*cf5a6c84SAndroid Build Coastguard Worker   struct child_list *child;
191*cf5a6c84SAndroid Build Coastguard Worker   char **args;
192*cf5a6c84SAndroid Build Coastguard Worker   char *type;
193*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
194*cf5a6c84SAndroid Build Coastguard Worker   int i = 1, j = 0;
195*cf5a6c84SAndroid Build Coastguard Worker 
196*cf5a6c84SAndroid Build Coastguard Worker   if (strcmp(finfo->type, "auto")) type = finfo->type;
197*cf5a6c84SAndroid Build Coastguard Worker   else if (TT.t_list && (TT.t_list[0] != 'n' || TT.t_list[1] != 'o' || TT.t_list[0] != '!')
198*cf5a6c84SAndroid Build Coastguard Worker       && strncmp(TT.t_list, "opts=", 5) && strncmp(TT.t_list , "loop", 4)
199*cf5a6c84SAndroid Build Coastguard Worker       && !TT.arr_type[1]) type = TT.t_list; //one file sys at cmdline
200*cf5a6c84SAndroid Build Coastguard Worker   else type = "auto";
201*cf5a6c84SAndroid Build Coastguard Worker 
202*cf5a6c84SAndroid Build Coastguard Worker   args = xzalloc((toys.optc + 2 + 1 + 1) * sizeof(char*)); //+1, for NULL, +1 if -C
203*cf5a6c84SAndroid Build Coastguard Worker   args[0] = xmprintf("fsck.%s", type);
204*cf5a6c84SAndroid Build Coastguard Worker 
205*cf5a6c84SAndroid Build Coastguard Worker   if(toys.optflags & FLAG_C) args[i++] = xmprintf("%s %d","-C", TT.fd_num);
206*cf5a6c84SAndroid Build Coastguard Worker   while(toys.optargs[j]) {
207*cf5a6c84SAndroid Build Coastguard Worker     if(*toys.optargs[j]) args[i++] = xstrdup(toys.optargs[j]);
208*cf5a6c84SAndroid Build Coastguard Worker     j++;
209*cf5a6c84SAndroid Build Coastguard Worker   }
210*cf5a6c84SAndroid Build Coastguard Worker   args[i] = finfo->device;
211*cf5a6c84SAndroid Build Coastguard Worker 
212*cf5a6c84SAndroid Build Coastguard Worker   TT.nr_run++;
213*cf5a6c84SAndroid Build Coastguard Worker   if ((toys.optflags & FLAG_V) || (toys.optflags & FLAG_N)) {
214*cf5a6c84SAndroid Build Coastguard Worker     printf("[%s (%d) -- %s]", args[0], TT.nr_run,
215*cf5a6c84SAndroid Build Coastguard Worker         finfo->mountpt ? finfo->mountpt : finfo->device);
216*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0; args[i]; i++) xprintf(" %s", args[i]);
217*cf5a6c84SAndroid Build Coastguard Worker     xputc('\n');
218*cf5a6c84SAndroid Build Coastguard Worker   }
219*cf5a6c84SAndroid Build Coastguard Worker 
220*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_N) {
221*cf5a6c84SAndroid Build Coastguard Worker     for (j=0;j<i;j++) free(args[i]);
222*cf5a6c84SAndroid Build Coastguard Worker     free(args);
223*cf5a6c84SAndroid Build Coastguard Worker     return;
224*cf5a6c84SAndroid Build Coastguard Worker   } else {
225*cf5a6c84SAndroid Build Coastguard Worker     if ((pid = fork()) < 0) {
226*cf5a6c84SAndroid Build Coastguard Worker       perror_msg_raw(*args);
227*cf5a6c84SAndroid Build Coastguard Worker       for (j=0;j<i;j++) free(args[i]);
228*cf5a6c84SAndroid Build Coastguard Worker       free(args);
229*cf5a6c84SAndroid Build Coastguard Worker       return;
230*cf5a6c84SAndroid Build Coastguard Worker     }
231*cf5a6c84SAndroid Build Coastguard Worker     if (!pid) xexec(args); //child, executes fsck.type
232*cf5a6c84SAndroid Build Coastguard Worker   }
233*cf5a6c84SAndroid Build Coastguard Worker 
234*cf5a6c84SAndroid Build Coastguard Worker   child = xzalloc(sizeof(struct child_list)); //Parent, add to child list.
235*cf5a6c84SAndroid Build Coastguard Worker   child->dev_name = xstrdup(finfo->device);
236*cf5a6c84SAndroid Build Coastguard Worker   child->prog_name = args[0];
237*cf5a6c84SAndroid Build Coastguard Worker   child->pid = pid;
238*cf5a6c84SAndroid Build Coastguard Worker 
239*cf5a6c84SAndroid Build Coastguard Worker   if (c_list) {
240*cf5a6c84SAndroid Build Coastguard Worker     child->next = c_list;
241*cf5a6c84SAndroid Build Coastguard Worker     c_list = child;
242*cf5a6c84SAndroid Build Coastguard Worker   } else {
243*cf5a6c84SAndroid Build Coastguard Worker     c_list = child;
244*cf5a6c84SAndroid Build Coastguard Worker     child->next =NULL;
245*cf5a6c84SAndroid Build Coastguard Worker   }
246*cf5a6c84SAndroid Build Coastguard Worker }
247*cf5a6c84SAndroid Build Coastguard Worker 
248*cf5a6c84SAndroid Build Coastguard Worker // for_all = 1; wait for all child to exit
249*cf5a6c84SAndroid Build Coastguard Worker // for_all = 0; wait for any one to exit
wait_for(int for_all)250*cf5a6c84SAndroid Build Coastguard Worker static int wait_for(int for_all)
251*cf5a6c84SAndroid Build Coastguard Worker {
252*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
253*cf5a6c84SAndroid Build Coastguard Worker   int status = 0, child_exited;
254*cf5a6c84SAndroid Build Coastguard Worker   struct child_list *prev, *temp;
255*cf5a6c84SAndroid Build Coastguard Worker 
256*cf5a6c84SAndroid Build Coastguard Worker   errno = 0;
257*cf5a6c84SAndroid Build Coastguard Worker   if (!c_list) return 0;
258*cf5a6c84SAndroid Build Coastguard Worker   while ((pid = wait(&status))) {
259*cf5a6c84SAndroid Build Coastguard Worker     temp = c_list;
260*cf5a6c84SAndroid Build Coastguard Worker     prev = temp;
261*cf5a6c84SAndroid Build Coastguard Worker     if (TT.sig_num) kill_all();
262*cf5a6c84SAndroid Build Coastguard Worker     child_exited = 0;
263*cf5a6c84SAndroid Build Coastguard Worker     if (pid < 0) {
264*cf5a6c84SAndroid Build Coastguard Worker       if (errno == EINTR) continue;
265*cf5a6c84SAndroid Build Coastguard Worker       else if (errno == ECHILD) break; //No child to wait, break and return status.
266*cf5a6c84SAndroid Build Coastguard Worker       else perror_exit("option arg Invalid\n"); //paranoid.
267*cf5a6c84SAndroid Build Coastguard Worker     }
268*cf5a6c84SAndroid Build Coastguard Worker     while (temp) {
269*cf5a6c84SAndroid Build Coastguard Worker       if (temp->pid == pid) {
270*cf5a6c84SAndroid Build Coastguard Worker         child_exited = 1;
271*cf5a6c84SAndroid Build Coastguard Worker         break;
272*cf5a6c84SAndroid Build Coastguard Worker       }
273*cf5a6c84SAndroid Build Coastguard Worker       prev = temp;
274*cf5a6c84SAndroid Build Coastguard Worker       temp = temp->next;
275*cf5a6c84SAndroid Build Coastguard Worker     }
276*cf5a6c84SAndroid Build Coastguard Worker     if (child_exited) {
277*cf5a6c84SAndroid Build Coastguard Worker       if (WIFEXITED(status)) TT.sum_status |= WEXITSTATUS(status);
278*cf5a6c84SAndroid Build Coastguard Worker       else if (WIFSIGNALED(status)) {
279*cf5a6c84SAndroid Build Coastguard Worker         TT.sum_status |= 4; //Uncorrected.
280*cf5a6c84SAndroid Build Coastguard Worker         if (WTERMSIG(status) != SIGINT)
281*cf5a6c84SAndroid Build Coastguard Worker           perror_msg("child Term. by sig: %d\n",(WTERMSIG(status)));
282*cf5a6c84SAndroid Build Coastguard Worker         TT.sum_status |= 8; //Operatinal error
283*cf5a6c84SAndroid Build Coastguard Worker       } else {
284*cf5a6c84SAndroid Build Coastguard Worker         TT.sum_status |= 4; //Uncorrected.
285*cf5a6c84SAndroid Build Coastguard Worker         perror_msg("%s %s: status is %x, should never happen\n",
286*cf5a6c84SAndroid Build Coastguard Worker             temp->prog_name, temp->dev_name, status);
287*cf5a6c84SAndroid Build Coastguard Worker       }
288*cf5a6c84SAndroid Build Coastguard Worker       TT.nr_run--;
289*cf5a6c84SAndroid Build Coastguard Worker       if (prev == temp) c_list = c_list->next; //first node
290*cf5a6c84SAndroid Build Coastguard Worker       else prev->next = temp->next;
291*cf5a6c84SAndroid Build Coastguard Worker       free(temp->prog_name);
292*cf5a6c84SAndroid Build Coastguard Worker       free(temp->dev_name);
293*cf5a6c84SAndroid Build Coastguard Worker       free(temp);
294*cf5a6c84SAndroid Build Coastguard Worker       if (!for_all) break;
295*cf5a6c84SAndroid Build Coastguard Worker     }
296*cf5a6c84SAndroid Build Coastguard Worker   }
297*cf5a6c84SAndroid Build Coastguard Worker   return TT.sum_status;
298*cf5a6c84SAndroid Build Coastguard Worker }
299*cf5a6c84SAndroid Build Coastguard Worker 
300*cf5a6c84SAndroid Build Coastguard Worker //scan all the fstab entries or -t matches with fstab.
scan_all(void)301*cf5a6c84SAndroid Build Coastguard Worker static int scan_all(void)
302*cf5a6c84SAndroid Build Coastguard Worker {
303*cf5a6c84SAndroid Build Coastguard Worker   struct f_sys_info *finfo = filesys_info;
304*cf5a6c84SAndroid Build Coastguard Worker   int ret = 0, passno;
305*cf5a6c84SAndroid Build Coastguard Worker 
306*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_V) xprintf("Checking all filesystem\n");
307*cf5a6c84SAndroid Build Coastguard Worker   while (finfo) {
308*cf5a6c84SAndroid Build Coastguard Worker     if (to_be_ignored(finfo)) finfo->flag |= FLAG_DONE;
309*cf5a6c84SAndroid Build Coastguard Worker     finfo = finfo->next;
310*cf5a6c84SAndroid Build Coastguard Worker   }
311*cf5a6c84SAndroid Build Coastguard Worker   finfo = filesys_info;
312*cf5a6c84SAndroid Build Coastguard Worker 
313*cf5a6c84SAndroid Build Coastguard Worker   if (!(toys.optflags & FLAG_P)) {
314*cf5a6c84SAndroid Build Coastguard Worker     while (finfo) {
315*cf5a6c84SAndroid Build Coastguard Worker       if (!strcmp(finfo->mountpt, "/")) { // man says: check / in parallel with others if -P is absent.
316*cf5a6c84SAndroid Build Coastguard Worker         if ((toys.optflags & FLAG_R) || to_be_ignored(finfo)) {
317*cf5a6c84SAndroid Build Coastguard Worker           finfo->flag |= FLAG_DONE;
318*cf5a6c84SAndroid Build Coastguard Worker           break;
319*cf5a6c84SAndroid Build Coastguard Worker         } else {
320*cf5a6c84SAndroid Build Coastguard Worker           do_fsck(finfo);
321*cf5a6c84SAndroid Build Coastguard Worker           finfo->flag |= FLAG_DONE;
322*cf5a6c84SAndroid Build Coastguard Worker           if (TT.sig_num) kill_all();
323*cf5a6c84SAndroid Build Coastguard Worker           if ((ret |= wait_for(1)) > 4) return ret; //destruction in filesys.
324*cf5a6c84SAndroid Build Coastguard Worker           break;
325*cf5a6c84SAndroid Build Coastguard Worker         }
326*cf5a6c84SAndroid Build Coastguard Worker       }
327*cf5a6c84SAndroid Build Coastguard Worker       finfo = finfo->next;
328*cf5a6c84SAndroid Build Coastguard Worker     }
329*cf5a6c84SAndroid Build Coastguard Worker   }
330*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_R) { // with -PR we choose to skip root.
331*cf5a6c84SAndroid Build Coastguard Worker     for (finfo = filesys_info; finfo; finfo = finfo->next) {
332*cf5a6c84SAndroid Build Coastguard Worker       if(!strcmp(finfo->mountpt, "/")) finfo->flag |= FLAG_DONE;
333*cf5a6c84SAndroid Build Coastguard Worker     }
334*cf5a6c84SAndroid Build Coastguard Worker   }
335*cf5a6c84SAndroid Build Coastguard Worker   passno = 1;
336*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
337*cf5a6c84SAndroid Build Coastguard Worker     for (finfo = filesys_info; finfo; finfo = finfo->next)
338*cf5a6c84SAndroid Build Coastguard Worker       if (!finfo->flag) break;
339*cf5a6c84SAndroid Build Coastguard Worker     if (!finfo) break;
340*cf5a6c84SAndroid Build Coastguard Worker 
341*cf5a6c84SAndroid Build Coastguard Worker     for (finfo = filesys_info; finfo; finfo = finfo->next) {
342*cf5a6c84SAndroid Build Coastguard Worker       if (finfo->flag) continue;
343*cf5a6c84SAndroid Build Coastguard Worker       if (finfo->passno == passno) {
344*cf5a6c84SAndroid Build Coastguard Worker         do_fsck(finfo);
345*cf5a6c84SAndroid Build Coastguard Worker         finfo->flag |= FLAG_DONE;
346*cf5a6c84SAndroid Build Coastguard Worker         if ((toys.optflags & FLAG_s) || (TT.nr_run
347*cf5a6c84SAndroid Build Coastguard Worker               && (TT.nr_run >= TT.max_nr_run))) ret |= wait_for(0);
348*cf5a6c84SAndroid Build Coastguard Worker       }
349*cf5a6c84SAndroid Build Coastguard Worker     }
350*cf5a6c84SAndroid Build Coastguard Worker     if (TT.sig_num) kill_all();
351*cf5a6c84SAndroid Build Coastguard Worker     ret |= wait_for(1);
352*cf5a6c84SAndroid Build Coastguard Worker     passno++;
353*cf5a6c84SAndroid Build Coastguard Worker   }
354*cf5a6c84SAndroid Build Coastguard Worker   return ret;
355*cf5a6c84SAndroid Build Coastguard Worker }
356*cf5a6c84SAndroid Build Coastguard Worker 
record_sig_num(int sig)357*cf5a6c84SAndroid Build Coastguard Worker void record_sig_num(int sig)
358*cf5a6c84SAndroid Build Coastguard Worker {
359*cf5a6c84SAndroid Build Coastguard Worker   TT.sig_num = sig;
360*cf5a6c84SAndroid Build Coastguard Worker }
361*cf5a6c84SAndroid Build Coastguard Worker 
fsck_main(void)362*cf5a6c84SAndroid Build Coastguard Worker void fsck_main(void)
363*cf5a6c84SAndroid Build Coastguard Worker {
364*cf5a6c84SAndroid Build Coastguard Worker   struct mntent mt;
365*cf5a6c84SAndroid Build Coastguard Worker   struct double_list *dev;
366*cf5a6c84SAndroid Build Coastguard Worker   struct f_sys_info *finfo;
367*cf5a6c84SAndroid Build Coastguard Worker   FILE *fp;
368*cf5a6c84SAndroid Build Coastguard Worker   char *tmp, **arg = toys.optargs;
369*cf5a6c84SAndroid Build Coastguard Worker 
370*cf5a6c84SAndroid Build Coastguard Worker   sigatexit(record_sig_num);
371*cf5a6c84SAndroid Build Coastguard Worker   while (*arg) {
372*cf5a6c84SAndroid Build Coastguard Worker     if ((**arg == '/') || strchr(*arg, '=')) {
373*cf5a6c84SAndroid Build Coastguard Worker       dlist_add(&TT.devices, xstrdup(*arg));
374*cf5a6c84SAndroid Build Coastguard Worker       **arg = '\0';
375*cf5a6c84SAndroid Build Coastguard Worker     }
376*cf5a6c84SAndroid Build Coastguard Worker     arg++;
377*cf5a6c84SAndroid Build Coastguard Worker   }
378*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_t) fix_tlist();
379*cf5a6c84SAndroid Build Coastguard Worker   if (!(tmp = getenv("FSTAB_FILE"))) tmp = "/etc/fstab";
380*cf5a6c84SAndroid Build Coastguard Worker   if (!(fp = setmntent(tmp, "r"))) perror_exit("setmntent failed:");
381*cf5a6c84SAndroid Build Coastguard Worker   while (getmntent_r(fp, &mt, toybuf, 4096)) create_db(&mt);
382*cf5a6c84SAndroid Build Coastguard Worker   endmntent(fp);
383*cf5a6c84SAndroid Build Coastguard Worker 
384*cf5a6c84SAndroid Build Coastguard Worker   if (!(toys.optflags & FLAG_T)) xprintf("fsck ----- (Toybox)\n");
385*cf5a6c84SAndroid Build Coastguard Worker 
386*cf5a6c84SAndroid Build Coastguard Worker   if ((tmp = getenv("FSCK_MAX_INST")))
387*cf5a6c84SAndroid Build Coastguard Worker     TT.max_nr_run = strtol_range(tmp, 0, INT_MAX);
388*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.devices || (toys.optflags & FLAG_A)) {
389*cf5a6c84SAndroid Build Coastguard Worker     toys.exitval = scan_all();
390*cf5a6c84SAndroid Build Coastguard Worker     if (CFG_TOYBOX_FREE) goto free_all;
391*cf5a6c84SAndroid Build Coastguard Worker     return; //if CFG_TOYBOX_FREE is not set, exit.
392*cf5a6c84SAndroid Build Coastguard Worker   }
393*cf5a6c84SAndroid Build Coastguard Worker 
394*cf5a6c84SAndroid Build Coastguard Worker   dev = TT.devices;
395*cf5a6c84SAndroid Build Coastguard Worker   dev->prev->next = NULL; //break double list to traverse.
396*cf5a6c84SAndroid Build Coastguard Worker   for (; dev; dev = dev->next) {
397*cf5a6c84SAndroid Build Coastguard Worker     for (finfo = filesys_info; finfo; finfo = finfo->next)
398*cf5a6c84SAndroid Build Coastguard Worker       if (!strcmp(finfo->device, dev->data)
399*cf5a6c84SAndroid Build Coastguard Worker           || !strcmp(finfo->mountpt, dev->data)) break;
400*cf5a6c84SAndroid Build Coastguard Worker     if (!finfo) { //if not present, fill def values.
401*cf5a6c84SAndroid Build Coastguard Worker       mt.mnt_fsname = dev->data;
402*cf5a6c84SAndroid Build Coastguard Worker       mt.mnt_dir = "";
403*cf5a6c84SAndroid Build Coastguard Worker       mt.mnt_type = "auto";
404*cf5a6c84SAndroid Build Coastguard Worker       mt.mnt_opts = "";
405*cf5a6c84SAndroid Build Coastguard Worker       mt.mnt_passno = -1;
406*cf5a6c84SAndroid Build Coastguard Worker       finfo = create_db(&mt);
407*cf5a6c84SAndroid Build Coastguard Worker     }
408*cf5a6c84SAndroid Build Coastguard Worker     do_fsck(finfo);
409*cf5a6c84SAndroid Build Coastguard Worker     finfo->flag |= FLAG_DONE;
410*cf5a6c84SAndroid Build Coastguard Worker     if ((toys.optflags & FLAG_s) || (TT.nr_run && (TT.nr_run >= TT.max_nr_run)))
411*cf5a6c84SAndroid Build Coastguard Worker       toys.exitval |= wait_for(0);
412*cf5a6c84SAndroid Build Coastguard Worker   }
413*cf5a6c84SAndroid Build Coastguard Worker   if (TT.sig_num) kill_all();
414*cf5a6c84SAndroid Build Coastguard Worker   toys.exitval |= wait_for(1);
415*cf5a6c84SAndroid Build Coastguard Worker   finfo = filesys_info;
416*cf5a6c84SAndroid Build Coastguard Worker 
417*cf5a6c84SAndroid Build Coastguard Worker free_all:
418*cf5a6c84SAndroid Build Coastguard Worker   if (CFG_TOYBOX_FREE) {
419*cf5a6c84SAndroid Build Coastguard Worker     struct f_sys_info *finfo, *temp;
420*cf5a6c84SAndroid Build Coastguard Worker 
421*cf5a6c84SAndroid Build Coastguard Worker     llist_traverse(TT.devices, llist_free_double);
422*cf5a6c84SAndroid Build Coastguard Worker     free(TT.arr_type);
423*cf5a6c84SAndroid Build Coastguard Worker     free(TT.arr_flag);
424*cf5a6c84SAndroid Build Coastguard Worker     for (finfo = filesys_info; finfo;) {
425*cf5a6c84SAndroid Build Coastguard Worker       temp = finfo->next;
426*cf5a6c84SAndroid Build Coastguard Worker       free(finfo->device);
427*cf5a6c84SAndroid Build Coastguard Worker       free(finfo->mountpt);
428*cf5a6c84SAndroid Build Coastguard Worker       free(finfo->type);
429*cf5a6c84SAndroid Build Coastguard Worker       free(finfo->opts);
430*cf5a6c84SAndroid Build Coastguard Worker       free(finfo);
431*cf5a6c84SAndroid Build Coastguard Worker       finfo = temp;
432*cf5a6c84SAndroid Build Coastguard Worker     }
433*cf5a6c84SAndroid Build Coastguard Worker   }
434*cf5a6c84SAndroid Build Coastguard Worker }
435