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