fix assorted unused code and wrong format specs found by cppchekc (bug 6716)
[platform/upstream/busybox.git] / e2fsprogs / old_e2fsprogs / fsck.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * pfsck --- A generic, parallelizing front-end for the fsck program.
4  * It will automatically try to run fsck programs in parallel if the
5  * devices are on separate spindles.  It is based on the same ideas as
6  * the generic front end for fsck by David Engel and Fred van Kempen,
7  * but it has been completely rewritten from scratch to support
8  * parallel execution.
9  *
10  * Written by Theodore Ts'o, <tytso@mit.edu>
11  *
12  * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
13  *   o Changed -t fstype to behave like with mount when -A (all file
14  *     systems) or -M (like mount) is specified.
15  *   o fsck looks if it can find the fsck.type program to decide
16  *     if it should ignore the fs type. This way more fsck programs
17  *     can be added without changing this front-end.
18  *   o -R flag skip root file system.
19  *
20  * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
21  *      2001, 2002, 2003, 2004, 2005 by  Theodore Ts'o.
22  *
23  * Licensed under GPLv2, see file LICENSE in this source tree.
24  */
25
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <sys/stat.h>
29 #include <limits.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <time.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <paths.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <signal.h>
40
41 #include "fsck.h"
42 #include "blkid/blkid.h"
43
44 #include "e2fsbb.h"
45
46 #include "libbb.h"
47
48 #ifndef _PATH_MNTTAB
49 #define _PATH_MNTTAB    "/etc/fstab"
50 #endif
51
52 /*
53  * fsck.h
54  */
55
56 #ifndef DEFAULT_FSTYPE
57 #define DEFAULT_FSTYPE  "ext2"
58 #endif
59
60 #define MAX_DEVICES 32
61 #define MAX_ARGS 32
62
63 /*
64  * Internal structure for mount tabel entries.
65  */
66
67 struct fs_info {
68         char  *device;
69         char  *mountpt;
70         char  *type;
71         char  *opts;
72         int   freq;
73         int   passno;
74         int   flags;
75         struct fs_info *next;
76 };
77
78 #define FLAG_DONE 1
79 #define FLAG_PROGRESS 2
80
81 /*
82  * Structure to allow exit codes to be stored
83  */
84 struct fsck_instance {
85         int     pid;
86         int     flags;
87         int     exit_status;
88         time_t  start_time;
89         char *  prog;
90         char *  type;
91         char *  device;
92         char *  base_device;
93         struct fsck_instance *next;
94 };
95
96 /*
97  * base_device.c
98  *
99  * Return the "base device" given a particular device; this is used to
100  * assure that we only fsck one partition on a particular drive at any
101  * one time.  Otherwise, the disk heads will be seeking all over the
102  * place.  If the base device cannot be determined, return NULL.
103  *
104  * The base_device() function returns an allocated string which must
105  * be freed.
106  *
107  */
108
109
110 #ifdef CONFIG_FEATURE_DEVFS
111 /*
112  * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
113  * pathames.
114  */
115 static const char *const devfs_hier[] = {
116         "host", "bus", "target", "lun", 0
117 };
118 #endif
119
120 static char *base_device(const char *device)
121 {
122         char *str, *cp;
123 #ifdef CONFIG_FEATURE_DEVFS
124         const char *const *hier;
125         const char *disk;
126         int len;
127 #endif
128
129         cp = str = xstrdup(device);
130
131         /* Skip over /dev/; if it's not present, give up. */
132         if (strncmp(cp, "/dev/", 5) != 0)
133                 goto errout;
134         cp += 5;
135
136         /*
137          * For md devices, we treat them all as if they were all
138          * on one disk, since we don't know how to parallelize them.
139          */
140         if (cp[0] == 'm' && cp[1] == 'd') {
141                 *(cp+2) = 0;
142                 return str;
143         }
144
145         /* Handle DAC 960 devices */
146         if (strncmp(cp, "rd/", 3) == 0) {
147                 cp += 3;
148                 if (cp[0] != 'c' || cp[2] != 'd' ||
149                     !isdigit(cp[1]) || !isdigit(cp[3]))
150                         goto errout;
151                 *(cp+4) = 0;
152                 return str;
153         }
154
155         /* Now let's handle /dev/hd* and /dev/sd* devices.... */
156         if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
157                 cp += 2;
158                 /* If there's a single number after /dev/hd, skip it */
159                 if (isdigit(*cp))
160                         cp++;
161                 /* What follows must be an alpha char, or give up */
162                 if (!isalpha(*cp))
163                         goto errout;
164                 *(cp + 1) = 0;
165                 return str;
166         }
167
168 #ifdef CONFIG_FEATURE_DEVFS
169         /* Now let's handle devfs (ugh) names */
170         len = 0;
171         if (strncmp(cp, "ide/", 4) == 0)
172                 len = 4;
173         if (strncmp(cp, "scsi/", 5) == 0)
174                 len = 5;
175         if (len) {
176                 cp += len;
177                 /*
178                  * Now we proceed down the expected devfs hierarchy.
179                  * i.e., .../host1/bus2/target3/lun4/...
180                  * If we don't find the expected token, followed by
181                  * some number of digits at each level, abort.
182                  */
183                 for (hier = devfs_hier; *hier; hier++) {
184                         len = strlen(*hier);
185                         if (strncmp(cp, *hier, len) != 0)
186                                 goto errout;
187                         cp += len;
188                         while (*cp != '/' && *cp != 0) {
189                                 if (!isdigit(*cp))
190                                         goto errout;
191                                 cp++;
192                         }
193                         cp++;
194                 }
195                 *(cp - 1) = 0;
196                 return str;
197         }
198
199         /* Now handle devfs /dev/disc or /dev/disk names */
200         disk = 0;
201         if (strncmp(cp, "discs/", 6) == 0)
202                 disk = "disc";
203         else if (strncmp(cp, "disks/", 6) == 0)
204                 disk = "disk";
205         if (disk) {
206                 cp += 6;
207                 if (strncmp(cp, disk, 4) != 0)
208                         goto errout;
209                 cp += 4;
210                 while (*cp != '/' && *cp != 0) {
211                         if (!isdigit(*cp))
212                                 goto errout;
213                         cp++;
214                 }
215                 *cp = 0;
216                 return str;
217         }
218 #endif
219
220 errout:
221         free(str);
222         return NULL;
223 }
224
225
226 static const char *const ignored_types[] = {
227         "ignore",
228         "iso9660",
229         "nfs",
230         "proc",
231         "sw",
232         "swap",
233         "tmpfs",
234         "devpts",
235         NULL
236 };
237
238 static const char *const really_wanted[] = {
239         "minix",
240         "ext2",
241         "ext3",
242         "jfs",
243         "reiserfs",
244         "xiafs",
245         "xfs",
246         NULL
247 };
248
249 #define BASE_MD "/dev/md"
250
251 /*
252  * Global variables for options
253  */
254 static char *devices[MAX_DEVICES];
255 static char *args[MAX_ARGS];
256 static int num_devices, num_args;
257
258 static int verbose;
259 static int doall;
260 static int noexecute;
261 static int serialize;
262 static int skip_root;
263 static int like_mount;
264 static int notitle;
265 static int parallel_root;
266 static int progress;
267 static int progress_fd;
268 static int force_all_parallel;
269 static int num_running;
270 static int max_running;
271 static volatile int cancel_requested;
272 static int kill_sent;
273 static char *fstype;
274 static struct fs_info *filesys_info, *filesys_last;
275 static struct fsck_instance *instance_list;
276 static char *fsck_path;
277 static blkid_cache cache;
278
279 static char *string_copy(const char *s)
280 {
281         char    *ret;
282
283         if (!s)
284                 return 0;
285         ret = xstrdup(s);
286         return ret;
287 }
288
289 static int string_to_int(const char *s)
290 {
291         long l;
292         char *p;
293
294         l = strtol(s, &p, 0);
295         if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
296                 return -1;
297         else
298                 return (int) l;
299 }
300
301 static char *skip_over_blank(char *cp)
302 {
303         while (*cp && isspace(*cp))
304                 cp++;
305         return cp;
306 }
307
308 static char *skip_over_word(char *cp)
309 {
310         while (*cp && !isspace(*cp))
311                 cp++;
312         return cp;
313 }
314
315 static void strip_line(char *line)
316 {
317         char    *p;
318
319         while (*line) {
320                 p = line + strlen(line) - 1;
321                 if ((*p == '\n') || (*p == '\r'))
322                         *p = 0;
323                 else
324                         break;
325         }
326 }
327
328 static char *parse_word(char **buf)
329 {
330         char *word, *next;
331
332         word = *buf;
333         if (*word == 0)
334                 return 0;
335
336         word = skip_over_blank(word);
337         next = skip_over_word(word);
338         if (*next)
339                 *next++ = 0;
340         *buf = next;
341         return word;
342 }
343
344 static void parse_escape(char *word)
345 {
346         char    *q, c;
347         const char *p;
348
349         if (!word)
350                 return;
351
352         strcpy_and_process_escape_sequences(word, word);
353 }
354
355 static void free_instance(struct fsck_instance *i)
356 {
357         if (i->prog)
358                 free(i->prog);
359         if (i->device)
360                 free(i->device);
361         if (i->base_device)
362                 free(i->base_device);
363         free(i);
364 }
365
366 static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
367                                         const char *type, const char *opts,
368                                         int freq, int passno)
369 {
370         struct fs_info *fs;
371
372         fs = xmalloc(sizeof(struct fs_info));
373
374         fs->device = string_copy(device);
375         fs->mountpt = string_copy(mntpnt);
376         fs->type = string_copy(type);
377         fs->opts = string_copy(opts ? opts : "");
378         fs->freq = freq;
379         fs->passno = passno;
380         fs->flags = 0;
381         fs->next = NULL;
382
383         if (!filesys_info)
384                 filesys_info = fs;
385         else
386                 filesys_last->next = fs;
387         filesys_last = fs;
388
389         return fs;
390 }
391
392
393
394 static int parse_fstab_line(char *line, struct fs_info **ret_fs)
395 {
396         char    *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
397         struct fs_info *fs;
398
399         *ret_fs = 0;
400         strip_line(line);
401         if ((cp = strchr(line, '#')))
402                 *cp = 0;        /* Ignore everything after the comment char */
403         cp = line;
404
405         device = parse_word(&cp);
406         mntpnt = parse_word(&cp);
407         type = parse_word(&cp);
408         opts = parse_word(&cp);
409         freq = parse_word(&cp);
410         passno = parse_word(&cp);
411
412         if (!device)
413                 return 0;       /* Allow blank lines */
414
415         if (!mntpnt || !type)
416                 return -1;
417
418         parse_escape(device);
419         parse_escape(mntpnt);
420         parse_escape(type);
421         parse_escape(opts);
422         parse_escape(freq);
423         parse_escape(passno);
424
425         dev = blkid_get_devname(cache, device, NULL);
426         if (dev)
427                 device = dev;
428
429         if (strchr(type, ','))
430                 type = 0;
431
432         fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
433                               freq ? atoi(freq) : -1,
434                               passno ? atoi(passno) : -1);
435         if (dev)
436                 free(dev);
437
438         if (!fs)
439                 return -1;
440         *ret_fs = fs;
441         return 0;
442 }
443
444 static void interpret_type(struct fs_info *fs)
445 {
446         char    *t;
447
448         if (strcmp(fs->type, "auto") != 0)
449                 return;
450         t = blkid_get_tag_value(cache, "TYPE", fs->device);
451         if (t) {
452                 free(fs->type);
453                 fs->type = t;
454         }
455 }
456
457 /*
458  * Load the filesystem database from /etc/fstab
459  */
460 static void load_fs_info(const char *filename)
461 {
462         FILE    *f;
463         char    buf[1024];
464         int     lineno = 0;
465         int     old_fstab = 1;
466         struct fs_info *fs;
467
468         if ((f = fopen_or_warn(filename, "r")) == NULL) {
469                 return;
470         }
471         while (!feof(f)) {
472                 lineno++;
473                 if (!fgets(buf, sizeof(buf), f))
474                         break;
475                 buf[sizeof(buf)-1] = 0;
476                 if (parse_fstab_line(buf, &fs) < 0) {
477                         bb_error_msg("WARNING: bad format "
478                                 "on line %d of %s\n", lineno, filename);
479                         continue;
480                 }
481                 if (!fs)
482                         continue;
483                 if (fs->passno < 0)
484                         fs->passno = 0;
485                 else
486                         old_fstab = 0;
487         }
488
489         fclose(f);
490
491         if (old_fstab) {
492                 fputs("\007\007\007"
493                 "WARNING: Your /etc/fstab does not contain the fsck passno\n"
494                 "       field.  I will kludge around things for you, but you\n"
495                 "       should fix your /etc/fstab file as soon as you can.\n\n", stderr);
496
497                 for (fs = filesys_info; fs; fs = fs->next) {
498                         fs->passno = 1;
499                 }
500         }
501 }
502
503 /* Lookup filesys in /etc/fstab and return the corresponding entry. */
504 static struct fs_info *lookup(char *filesys)
505 {
506         struct fs_info *fs;
507
508         /* No filesys name given. */
509         if (filesys == NULL)
510                 return NULL;
511
512         for (fs = filesys_info; fs; fs = fs->next) {
513                 if (!strcmp(filesys, fs->device) ||
514                     (fs->mountpt && !strcmp(filesys, fs->mountpt)))
515                         break;
516         }
517
518         return fs;
519 }
520
521 /* Find fsck program for a given fs type. */
522 static char *find_fsck(char *type)
523 {
524         char *s;
525         const char *tpl;
526         char *p = string_copy(fsck_path);
527         struct stat st;
528
529         /* Are we looking for a program or just a type? */
530         tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
531
532         for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
533                 s = xasprintf(tpl, s, type);
534                 if (stat(s, &st) == 0) break;
535                 free(s);
536         }
537         free(p);
538         return s;
539 }
540
541 static int progress_active(void)
542 {
543         struct fsck_instance *inst;
544
545         for (inst = instance_list; inst; inst = inst->next) {
546                 if (inst->flags & FLAG_DONE)
547                         continue;
548                 if (inst->flags & FLAG_PROGRESS)
549                         return 1;
550         }
551         return 0;
552 }
553
554 /*
555  * Execute a particular fsck program, and link it into the list of
556  * child processes we are waiting for.
557  */
558 static int execute(const char *type, const char *device, const char *mntpt,
559                    int interactive)
560 {
561         char *s, *argv[80];
562         char *prog;
563         int  argc, i;
564         struct fsck_instance *inst, *p;
565         pid_t   pid;
566
567         inst = xzalloc(sizeof(struct fsck_instance));
568
569         prog = xasprintf("fsck.%s", type);
570         argv[0] = prog;
571         argc = 1;
572
573         for (i=0; i <num_args; i++)
574                 argv[argc++] = string_copy(args[i]);
575
576         if (progress && !progress_active()) {
577                 if ((strcmp(type, "ext2") == 0) ||
578                     (strcmp(type, "ext3") == 0)) {
579                         char tmp[80];
580                         snprintf(tmp, 80, "-C%d", progress_fd);
581                         argv[argc++] = string_copy(tmp);
582                         inst->flags |= FLAG_PROGRESS;
583                 }
584         }
585
586         argv[argc++] = string_copy(device);
587         argv[argc] = 0;
588
589         s = find_fsck(prog);
590         if (s == NULL) {
591                 bb_error_msg("%s: not found", prog);
592                 return ENOENT;
593         }
594
595         if (verbose || noexecute) {
596                 printf("[%s (%d) -- %s] ", s, num_running,
597                        mntpt ? mntpt : device);
598                 for (i=0; i < argc; i++)
599                         printf("%s ", argv[i]);
600                 bb_putchar('\n');
601         }
602
603         /* Fork and execute the correct program. */
604         if (noexecute)
605                 pid = -1;
606         else if ((pid = fork()) < 0) {
607                 perror("vfork"+1);
608                 return errno;
609         } else if (pid == 0) {
610                 if (!interactive)
611                         close(0);
612                 (void) execv(s, argv);
613                 bb_simple_perror_msg_and_die(argv[0]);
614         }
615
616         for (i = 1; i < argc; i++)
617                 free(argv[i]);
618
619         free(s);
620         inst->pid = pid;
621         inst->prog = prog;
622         inst->type = string_copy(type);
623         inst->device = string_copy(device);
624         inst->base_device = base_device(device);
625         inst->start_time = time(0);
626         inst->next = NULL;
627
628         /*
629          * Find the end of the list, so we add the instance on at the end.
630          */
631         for (p = instance_list; p && p->next; p = p->next);
632
633         if (p)
634                 p->next = inst;
635         else
636                 instance_list = inst;
637
638         return 0;
639 }
640
641 /*
642  * Send a signal to all outstanding fsck child processes
643  */
644 static int kill_all(int signum)
645 {
646         struct fsck_instance *inst;
647         int     n = 0;
648
649         for (inst = instance_list; inst; inst = inst->next) {
650                 if (inst->flags & FLAG_DONE)
651                         continue;
652                 kill(inst->pid, signum);
653                 n++;
654         }
655         return n;
656 }
657
658 /*
659  * Wait for one child process to exit; when it does, unlink it from
660  * the list of executing child processes, and return it.
661  */
662 static struct fsck_instance *wait_one(int flags)
663 {
664         int     status;
665         int     sig;
666         struct fsck_instance *inst, *inst2, *prev;
667         pid_t   pid;
668
669         if (!instance_list)
670                 return NULL;
671
672         if (noexecute) {
673                 inst = instance_list;
674                 prev = 0;
675 #ifdef RANDOM_DEBUG
676                 while (inst->next && (random() & 1)) {
677                         prev = inst;
678                         inst = inst->next;
679                 }
680 #endif
681                 inst->exit_status = 0;
682                 goto ret_inst;
683         }
684
685         /*
686          * gcc -Wall fails saving throw against stupidity
687          * (inst and prev are thought to be uninitialized variables)
688          */
689         inst = prev = NULL;
690
691         do {
692                 pid = waitpid(-1, &status, flags);
693                 if (cancel_requested && !kill_sent) {
694                         kill_all(SIGTERM);
695                         kill_sent++;
696                 }
697                 if ((pid == 0) && (flags & WNOHANG))
698                         return NULL;
699                 if (pid < 0) {
700                         if ((errno == EINTR) || (errno == EAGAIN))
701                                 continue;
702                         if (errno == ECHILD) {
703                                 bb_error_msg("wait: no more child process?!?");
704                                 return NULL;
705                         }
706                         perror("wait");
707                         continue;
708                 }
709                 for (prev = 0, inst = instance_list;
710                      inst;
711                      prev = inst, inst = inst->next) {
712                         if (inst->pid == pid)
713                                 break;
714                 }
715         } while (!inst);
716
717         if (WIFEXITED(status))
718                 status = WEXITSTATUS(status);
719         else if (WIFSIGNALED(status)) {
720                 sig = WTERMSIG(status);
721                 if (sig == SIGINT) {
722                         status = EXIT_UNCORRECTED;
723                 } else {
724                         printf("Warning... %s for device %s exited "
725                                "with signal %d.\n",
726                                inst->prog, inst->device, sig);
727                         status = EXIT_ERROR;
728                 }
729         } else {
730                 printf("%s %s: status is %x, should never happen.\n",
731                        inst->prog, inst->device, status);
732                 status = EXIT_ERROR;
733         }
734         inst->exit_status = status;
735         if (progress && (inst->flags & FLAG_PROGRESS) &&
736             !progress_active()) {
737                 for (inst2 = instance_list; inst2; inst2 = inst2->next) {
738                         if (inst2->flags & FLAG_DONE)
739                                 continue;
740                         if (strcmp(inst2->type, "ext2") &&
741                             strcmp(inst2->type, "ext3"))
742                                 continue;
743                         /*
744                          * If we've just started the fsck, wait a tiny
745                          * bit before sending the kill, to give it
746                          * time to set up the signal handler
747                          */
748                         if (inst2->start_time < time(0)+2) {
749                                 if (fork() == 0) {
750                                         sleep(1);
751                                         kill(inst2->pid, SIGUSR1);
752                                         exit(0);
753                                 }
754                         } else
755                                 kill(inst2->pid, SIGUSR1);
756                         inst2->flags |= FLAG_PROGRESS;
757                         break;
758                 }
759         }
760 ret_inst:
761         if (prev)
762                 prev->next = inst->next;
763         else
764                 instance_list = inst->next;
765         if (verbose > 1)
766                 printf("Finished with %s (exit status %d)\n",
767                        inst->device, inst->exit_status);
768         num_running--;
769         return inst;
770 }
771
772 #define FLAG_WAIT_ALL           0
773 #define FLAG_WAIT_ATLEAST_ONE   1
774 /*
775  * Wait until all executing child processes have exited; return the
776  * logical OR of all of their exit code values.
777  */
778 static int wait_many(int flags)
779 {
780         struct fsck_instance *inst;
781         int     global_status = 0;
782         int     wait_flags = 0;
783
784         while ((inst = wait_one(wait_flags))) {
785                 global_status |= inst->exit_status;
786                 free_instance(inst);
787 #ifdef RANDOM_DEBUG
788                 if (noexecute && (flags & WNOHANG) && !(random() % 3))
789                         break;
790 #endif
791                 if (flags & FLAG_WAIT_ATLEAST_ONE)
792                         wait_flags = WNOHANG;
793         }
794         return global_status;
795 }
796
797 /*
798  * Run the fsck program on a particular device
799  *
800  * If the type is specified using -t, and it isn't prefixed with "no"
801  * (as in "noext2") and only one filesystem type is specified, then
802  * use that type regardless of what is specified in /etc/fstab.
803  *
804  * If the type isn't specified by the user, then use either the type
805  * specified in /etc/fstab, or DEFAULT_FSTYPE.
806  */
807 static void fsck_device(struct fs_info *fs, int interactive)
808 {
809         const char *type;
810         int retval;
811
812         interpret_type(fs);
813
814         if (strcmp(fs->type, "auto") != 0)
815                 type = fs->type;
816         else if (fstype && strncmp(fstype, "no", 2) &&
817             strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
818             !strchr(fstype, ','))
819                 type = fstype;
820         else
821                 type = DEFAULT_FSTYPE;
822
823         num_running++;
824         retval = execute(type, fs->device, fs->mountpt, interactive);
825         if (retval) {
826                 bb_error_msg("error %d while executing fsck.%s for %s",
827                                                 retval, type, fs->device);
828                 num_running--;
829         }
830 }
831
832
833 /*
834  * Deal with the fsck -t argument.
835  */
836 struct fs_type_compile {
837         char **list;
838         int *type;
839         int  negate;
840 } fs_type_compiled;
841
842 #define FS_TYPE_NORMAL  0
843 #define FS_TYPE_OPT     1
844 #define FS_TYPE_NEGOPT  2
845
846 static const char fs_type_syntax_error[] =
847 "Either all or none of the filesystem types passed to -t must be prefixed\n"
848    "with 'no' or '!'.";
849
850 static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
851 {
852         char    *cp, *list, *s;
853         int     num = 2;
854         int     negate, first_negate = 1;
855
856         if (fs_type) {
857                 for (cp=fs_type; *cp; cp++) {
858                         if (*cp == ',')
859                                 num++;
860                 }
861         }
862
863         cmp->list = xzalloc(num * sizeof(char *));
864         cmp->type = xzalloc(num * sizeof(int));
865         cmp->negate = 0;
866
867         if (!fs_type)
868                 return;
869
870         list = string_copy(fs_type);
871         num = 0;
872         s = strtok(list, ",");
873         while (s) {
874                 negate = 0;
875                 if (strncmp(s, "no", 2) == 0) {
876                         s += 2;
877                         negate = 1;
878                 } else if (*s == '!') {
879                         s++;
880                         negate = 1;
881                 }
882                 if (strcmp(s, "loop") == 0)
883                         /* loop is really short-hand for opts=loop */
884                         goto loop_special_case;
885                 else if (strncmp(s, "opts=", 5) == 0) {
886                         s += 5;
887                 loop_special_case:
888                         cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
889                 } else {
890                         if (first_negate) {
891                                 cmp->negate = negate;
892                                 first_negate = 0;
893                         }
894                         if ((negate && !cmp->negate) ||
895                             (!negate && cmp->negate)) {
896                                 bb_error_msg_and_die("%s", fs_type_syntax_error);
897                         }
898                 }
899                 cmp->list[num++] = string_copy(s);
900                 s = strtok(NULL, ",");
901         }
902         free(list);
903 }
904
905 /*
906  * This function returns true if a particular option appears in a
907  * comma-delimited options list
908  */
909 static int opt_in_list(char *opt, char *optlist)
910 {
911         char    *list, *s;
912
913         if (!optlist)
914                 return 0;
915         list = string_copy(optlist);
916
917         s = strtok(list, ",");
918         while (s) {
919                 if (strcmp(s, opt) == 0) {
920                         free(list);
921                         return 1;
922                 }
923                 s = strtok(NULL, ",");
924         }
925         free(list);
926         return 0;
927 }
928
929 /* See if the filesystem matches the criteria given by the -t option */
930 static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
931 {
932         int n, ret = 0, checked_type = 0;
933         char *cp;
934
935         if (cmp->list == 0 || cmp->list[0] == 0)
936                 return 1;
937
938         for (n=0; (cp = cmp->list[n]); n++) {
939                 switch (cmp->type[n]) {
940                 case FS_TYPE_NORMAL:
941                         checked_type++;
942                         if (strcmp(cp, fs->type) == 0) {
943                                 ret = 1;
944                         }
945                         break;
946                 case FS_TYPE_NEGOPT:
947                         if (opt_in_list(cp, fs->opts))
948                                 return 0;
949                         break;
950                 case FS_TYPE_OPT:
951                         if (!opt_in_list(cp, fs->opts))
952                                 return 0;
953                         break;
954                 }
955         }
956         if (checked_type == 0)
957                 return 1;
958         return (cmp->negate ? !ret : ret);
959 }
960
961 /* Check if we should ignore this filesystem. */
962 static int ignore(struct fs_info *fs)
963 {
964         int wanted;
965         char *s;
966
967         /*
968          * If the pass number is 0, ignore it.
969          */
970         if (fs->passno == 0)
971                 return 1;
972
973         interpret_type(fs);
974
975         /*
976          * If a specific fstype is specified, and it doesn't match,
977          * ignore it.
978          */
979         if (!fs_match(fs, &fs_type_compiled)) return 1;
980
981         /* Are we ignoring this type? */
982         if (index_in_str_array(ignored_types, fs->type) >= 0)
983                 return 1;
984
985         /* Do we really really want to check this fs? */
986         wanted = index_in_str_array(really_wanted, fs->type) >= 0;
987
988         /* See if the <fsck.fs> program is available. */
989         s = find_fsck(fs->type);
990         if (s == NULL) {
991                 if (wanted)
992                         bb_error_msg("can't check %s: fsck.%s not found",
993                                 fs->device, fs->type);
994                 return 1;
995         }
996         free(s);
997
998         /* We can and want to check this file system type. */
999         return 0;
1000 }
1001
1002 /*
1003  * Returns TRUE if a partition on the same disk is already being
1004  * checked.
1005  */
1006 static int device_already_active(char *device)
1007 {
1008         struct fsck_instance *inst;
1009         char *base;
1010
1011         if (force_all_parallel)
1012                 return 0;
1013
1014 #ifdef BASE_MD
1015         /* Don't check a soft raid disk with any other disk */
1016         if (instance_list &&
1017             (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
1018              !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
1019                 return 1;
1020 #endif
1021
1022         base = base_device(device);
1023         /*
1024          * If we don't know the base device, assume that the device is
1025          * already active if there are any fsck instances running.
1026          */
1027         if (!base)
1028                 return (instance_list != 0);
1029         for (inst = instance_list; inst; inst = inst->next) {
1030                 if (!inst->base_device || !strcmp(base, inst->base_device)) {
1031                         free(base);
1032                         return 1;
1033                 }
1034         }
1035         free(base);
1036         return 0;
1037 }
1038
1039 /* Check all file systems, using the /etc/fstab table. */
1040 static int check_all(void)
1041 {
1042         struct fs_info *fs = NULL;
1043         int status = EXIT_OK;
1044         int not_done_yet = 1;
1045         int passno = 1;
1046         int pass_done;
1047
1048         if (verbose)
1049                 fputs("Checking all file systems.\n", stdout);
1050
1051         /*
1052          * Do an initial scan over the filesystem; mark filesystems
1053          * which should be ignored as done, and resolve any "auto"
1054          * filesystem types (done as a side-effect of calling ignore()).
1055          */
1056         for (fs = filesys_info; fs; fs = fs->next) {
1057                 if (ignore(fs))
1058                         fs->flags |= FLAG_DONE;
1059         }
1060
1061         /*
1062          * Find and check the root filesystem.
1063          */
1064         if (!parallel_root) {
1065                 for (fs = filesys_info; fs; fs = fs->next) {
1066                         if (LONE_CHAR(fs->mountpt, '/'))
1067                                 break;
1068                 }
1069                 if (fs) {
1070                         if (!skip_root && !ignore(fs)) {
1071                                 fsck_device(fs, 1);
1072                                 status |= wait_many(FLAG_WAIT_ALL);
1073                                 if (status > EXIT_NONDESTRUCT)
1074                                         return status;
1075                         }
1076                         fs->flags |= FLAG_DONE;
1077                 }
1078         }
1079         /*
1080          * This is for the bone-headed user who enters the root
1081          * filesystem twice.  Skip root will skep all root entries.
1082          */
1083         if (skip_root)
1084                 for (fs = filesys_info; fs; fs = fs->next)
1085                         if (LONE_CHAR(fs->mountpt, '/'))
1086                                 fs->flags |= FLAG_DONE;
1087
1088         while (not_done_yet) {
1089                 not_done_yet = 0;
1090                 pass_done = 1;
1091
1092                 for (fs = filesys_info; fs; fs = fs->next) {
1093                         if (cancel_requested)
1094                                 break;
1095                         if (fs->flags & FLAG_DONE)
1096                                 continue;
1097                         /*
1098                          * If the filesystem's pass number is higher
1099                          * than the current pass number, then we don't
1100                          * do it yet.
1101                          */
1102                         if (fs->passno > passno) {
1103                                 not_done_yet++;
1104                                 continue;
1105                         }
1106                         /*
1107                          * If a filesystem on a particular device has
1108                          * already been spawned, then we need to defer
1109                          * this to another pass.
1110                          */
1111                         if (device_already_active(fs->device)) {
1112                                 pass_done = 0;
1113                                 continue;
1114                         }
1115                         /*
1116                          * Spawn off the fsck process
1117                          */
1118                         fsck_device(fs, serialize);
1119                         fs->flags |= FLAG_DONE;
1120
1121                         /*
1122                          * Only do one filesystem at a time, or if we
1123                          * have a limit on the number of fsck's extant
1124                          * at one time, apply that limit.
1125                          */
1126                         if (serialize ||
1127                             (max_running && (num_running >= max_running))) {
1128                                 pass_done = 0;
1129                                 break;
1130                         }
1131                 }
1132                 if (cancel_requested)
1133                         break;
1134                 if (verbose > 1)
1135                         printf("--waiting-- (pass %d)\n", passno);
1136                 status |= wait_many(pass_done ? FLAG_WAIT_ALL :
1137                                     FLAG_WAIT_ATLEAST_ONE);
1138                 if (pass_done) {
1139                         if (verbose > 1)
1140                                 printf("----------------------------------\n");
1141                         passno++;
1142                 } else
1143                         not_done_yet++;
1144         }
1145         if (cancel_requested && !kill_sent) {
1146                 kill_all(SIGTERM);
1147                 kill_sent++;
1148         }
1149         status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
1150         return status;
1151 }
1152
1153 static void signal_cancel(int sig FSCK_ATTR((unused)))
1154 {
1155         cancel_requested++;
1156 }
1157
1158 static void PRS(int argc, char **argv)
1159 {
1160         int     i, j;
1161         char    *arg, *dev, *tmp = NULL;
1162         char    options[128];
1163         int     opt = 0;
1164         int     opts_for_fsck = 0;
1165         struct sigaction        sa;
1166
1167         /*
1168          * Set up signal action
1169          */
1170         memset(&sa, 0, sizeof(struct sigaction));
1171         sa.sa_handler = signal_cancel;
1172         sigaction(SIGINT, &sa, 0);
1173         sigaction(SIGTERM, &sa, 0);
1174
1175         num_devices = 0;
1176         num_args = 0;
1177         instance_list = 0;
1178
1179         for (i=1; i < argc; i++) {
1180                 arg = argv[i];
1181                 if (!arg)
1182                         continue;
1183                 if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
1184                         if (num_devices >= MAX_DEVICES) {
1185                                 bb_error_msg_and_die("too many devices");
1186                         }
1187                         dev = blkid_get_devname(cache, arg, NULL);
1188                         if (!dev && strchr(arg, '=')) {
1189                                 /*
1190                                  * Check to see if we failed because
1191                                  * /proc/partitions isn't found.
1192                                  */
1193                                 if (access("/proc/partitions", R_OK) < 0) {
1194                                         bb_perror_msg_and_die("can't open /proc/partitions "
1195                                                         "(is /proc mounted?)");
1196                                 }
1197                                 /*
1198                                  * Check to see if this is because
1199                                  * we're not running as root
1200                                  */
1201                                 if (geteuid())
1202                                         bb_error_msg_and_die(
1203                 "must be root to scan for matching filesystems: %s\n", arg);
1204                                 else
1205                                         bb_error_msg_and_die(
1206                 "can't find matching filesystem: %s", arg);
1207                         }
1208                         devices[num_devices++] = dev ? dev : string_copy(arg);
1209                         continue;
1210                 }
1211                 if (arg[0] != '-' || opts_for_fsck) {
1212                         if (num_args >= MAX_ARGS) {
1213                                 bb_error_msg_and_die("too many arguments");
1214                         }
1215                         args[num_args++] = string_copy(arg);
1216                         continue;
1217                 }
1218                 for (j=1; arg[j]; j++) {
1219                         if (opts_for_fsck) {
1220                                 options[++opt] = arg[j];
1221                                 continue;
1222                         }
1223                         switch (arg[j]) {
1224                         case 'A':
1225                                 doall++;
1226                                 break;
1227                         case 'C':
1228                                 progress++;
1229                                 if (arg[j+1]) {
1230                                         progress_fd = string_to_int(arg+j+1);
1231                                         if (progress_fd < 0)
1232                                                 progress_fd = 0;
1233                                         else
1234                                                 goto next_arg;
1235                                 } else if ((i+1) < argc
1236                                  && argv[i+1][0] != '-') {
1237                                         progress_fd = string_to_int(argv[i]);
1238                                         if (progress_fd < 0)
1239                                                 progress_fd = 0;
1240                                         else {
1241                                                 goto next_arg;
1242                                         }
1243                                 }
1244                                 break;
1245                         case 'V':
1246                                 verbose++;
1247                                 break;
1248                         case 'N':
1249                                 noexecute++;
1250                                 break;
1251                         case 'R':
1252                                 skip_root++;
1253                                 break;
1254                         case 'T':
1255                                 notitle++;
1256                                 break;
1257                         case 'M':
1258                                 like_mount++;
1259                                 break;
1260                         case 'P':
1261                                 parallel_root++;
1262                                 break;
1263                         case 's':
1264                                 serialize++;
1265                                 break;
1266                         case 't':
1267                                 tmp = 0;
1268                                 if (fstype)
1269                                         bb_show_usage();
1270                                 if (arg[j+1])
1271                                         tmp = arg+j+1;
1272                                 else if ((i+1) < argc)
1273                                         tmp = argv[++i];
1274                                 else
1275                                         bb_show_usage();
1276                                 fstype = string_copy(tmp);
1277                                 compile_fs_type(fstype, &fs_type_compiled);
1278                                 goto next_arg;
1279                         case '-':
1280                                 opts_for_fsck++;
1281                                 break;
1282                         case '?':
1283                                 bb_show_usage();
1284                                 break;
1285                         default:
1286                                 options[++opt] = arg[j];
1287                                 break;
1288                         }
1289                 }
1290         next_arg:
1291                 if (opt) {
1292                         options[0] = '-';
1293                         options[++opt] = '\0';
1294                         if (num_args >= MAX_ARGS) {
1295                                 bb_error_msg("too many arguments");
1296                         }
1297                         args[num_args++] = string_copy(options);
1298                         opt = 0;
1299                 }
1300         }
1301         if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1302                 force_all_parallel++;
1303         if ((tmp = getenv("FSCK_MAX_INST")))
1304             max_running = atoi(tmp);
1305 }
1306
1307 int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1308 int fsck_main(int argc, char **argv)
1309 {
1310         int i, status = 0;
1311         int interactive = 0;
1312         const char *fstab;
1313         struct fs_info *fs;
1314
1315         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
1316         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
1317
1318         blkid_get_cache(&cache, NULL);
1319         PRS(argc, argv);
1320
1321         if (!notitle)
1322                 printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
1323
1324         fstab = getenv("FSTAB_FILE");
1325         if (!fstab)
1326                 fstab = _PATH_MNTTAB;
1327         load_fs_info(fstab);
1328
1329         fsck_path = e2fs_set_sbin_path();
1330
1331         if ((num_devices == 1) || (serialize))
1332                 interactive = 1;
1333
1334         /* If -A was specified ("check all"), do that! */
1335         if (doall)
1336                 return check_all();
1337
1338         if (num_devices == 0) {
1339                 serialize++;
1340                 interactive++;
1341                 return check_all();
1342         }
1343         for (i = 0; i < num_devices; i++) {
1344                 if (cancel_requested) {
1345                         if (!kill_sent) {
1346                                 kill_all(SIGTERM);
1347                                 kill_sent++;
1348                         }
1349                         break;
1350                 }
1351                 fs = lookup(devices[i]);
1352                 if (!fs) {
1353                         fs = create_fs_device(devices[i], 0, "auto",
1354                                               0, -1, -1);
1355                         if (!fs)
1356                                 continue;
1357                 }
1358                 fsck_device(fs, interactive);
1359                 if (serialize ||
1360                     (max_running && (num_running >= max_running))) {
1361                         struct fsck_instance *inst;
1362
1363                         inst = wait_one(0);
1364                         if (inst) {
1365                                 status |= inst->exit_status;
1366                                 free_instance(inst);
1367                         }
1368                         if (verbose > 1)
1369                                 printf("----------------------------------\n");
1370                 }
1371         }
1372         status |= wait_many(FLAG_WAIT_ALL);
1373         blkid_put_cache(cache);
1374         return status;
1375 }