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