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