]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fsck/fsck.c
include/exitcodes: clean up names, add _EX_ suffix
[thirdparty/util-linux.git] / fsck / fsck.c
CommitLineData
607c2a72 1/*
41e32d9f 2 * fsck --- A generic, parallelizing front-end for the fsck program.
607c2a72
KZ
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 *
41e32d9f 22 * Copyright (C) 2009, 2012 Karel Zak <kzak@redhat.com>
607c2a72
KZ
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>
607c2a72 32#include <sys/stat.h>
dd0bd943
KZ
33#include <sys/file.h>
34#include <fcntl.h>
607c2a72
KZ
35#include <limits.h>
36#include <stdio.h>
37#include <ctype.h>
38#include <string.h>
39#include <time.h>
40#include <stdlib.h>
607c2a72
KZ
41#include <paths.h>
42#include <unistd.h>
43#include <errno.h>
607c2a72 44#include <signal.h>
0c0f93fc
KZ
45#include <dirent.h>
46#include <blkid.h>
607c2a72 47
06cb26d9 48#include "fsprobe.h"
607c2a72
KZ
49
50#include "nls.h"
51#include "pathnames.h"
52#include "ismounted.h"
93bd18bc 53#include "c.h"
0a09eb4e
SK
54#include "fsck.h"
55
56#define XALLOC_EXIT_CODE EXIT_ERROR
57#include "xalloc.h"
607c2a72
KZ
58
59static const char *ignored_types[] = {
e3174198
KZ
60 "9p",
61 "afs",
62 "autofs",
63 "binfmt_misc",
64 "cgroup",
65 "cifs",
66 "cpuset",
67 "debugfs",
68 "devfs",
69 "devpts",
70 "devtmpfs",
71 "dlmfs",
72 "fusectl",
73 "fuse.gvfs-fuse-daemon",
74 "hugetlbfs",
607c2a72
KZ
75 "ignore",
76 "iso9660",
e3174198
KZ
77 "mqueue"
78 "ncpfs",
607c2a72
KZ
79 "nfs",
80 "proc",
e3174198
KZ
81 "rpc_pipefs",
82 "securityfs",
83 "smbfs",
84 "spufs",
607c2a72
KZ
85 "sw",
86 "swap",
e3174198 87 "sysfs",
607c2a72 88 "tmpfs",
607c2a72
KZ
89 NULL
90};
91
92static const char *really_wanted[] = {
93 "minix",
94 "ext2",
95 "ext3",
96 "ext4",
97 "ext4dev",
98 "jfs",
99 "reiserfs",
100 "xiafs",
101 "xfs",
102 NULL
103};
104
105#define BASE_MD "/dev/md"
106
107/*
108 * Global variables for options
109 */
110char *devices[MAX_DEVICES];
111char *args[MAX_ARGS];
112int num_devices, num_args;
113
dd0bd943 114int lockdisk = 0;
607c2a72
KZ
115int verbose = 0;
116int doall = 0;
117int noexecute = 0;
118int serialize = 0;
119int skip_root = 0;
120int ignore_mounted = 0;
121int notitle = 0;
122int parallel_root = 0;
123int progress = 0;
124int progress_fd = 0;
125int force_all_parallel = 0;
126int num_running = 0;
127int max_running = 0;
128volatile int cancel_requested = 0;
129int kill_sent = 0;
607c2a72
KZ
130char *fstype = NULL;
131struct fs_info *filesys_info = NULL, *filesys_last = NULL;
132struct fsck_instance *instance_list;
bb4cb69d 133const char fsck_prefix_path[] = FS_SEARCH_PATH;
607c2a72 134char *fsck_path = 0;
607c2a72
KZ
135
136static char *string_copy(const char *s)
137{
138 char *ret;
139
140 if (!s)
141 return 0;
0a09eb4e
SK
142 ret = xmalloc(strlen(s)+1);
143 strcpy(ret, s);
607c2a72
KZ
144 return ret;
145}
146
147static int string_to_int(const char *s)
148{
149 long l;
150 char *p;
151
152 l = strtol(s, &p, 0);
153 if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
154 return -1;
155 else
156 return (int) l;
157}
158
159static int ignore(struct fs_info *);
160
161static char *skip_over_blank(char *cp)
162{
163 while (*cp && isspace(*cp))
164 cp++;
165 return cp;
166}
167
168static char *skip_over_word(char *cp)
169{
170 while (*cp && !isspace(*cp))
171 cp++;
172 return cp;
173}
174
175static void strip_line(char *line)
176{
177 char *p;
178
179 while (*line) {
180 p = line + strlen(line) - 1;
181 if ((*p == '\n') || (*p == '\r'))
182 *p = 0;
183 else
184 break;
185 }
186}
187
188static char *parse_word(char **buf)
189{
190 char *word, *next;
191
192 word = *buf;
193 if (*word == 0)
194 return 0;
195
196 word = skip_over_blank(word);
197 next = skip_over_word(word);
198 if (*next)
199 *next++ = 0;
200 *buf = next;
201 return word;
202}
203
204static void parse_escape(char *word)
205{
206 char *p, *q;
207 int ac, i;
208
209 if (!word)
210 return;
211
212 for (p = word, q = word; *p; p++, q++) {
213 *q = *p;
214 if (*p != '\\')
215 continue;
216 if (*++p == 0)
217 break;
218 if (*p == 't') {
219 *q = '\t';
220 continue;
221 }
222 if (*p == 'n') {
223 *q = '\n';
224 continue;
225 }
226 if (!isdigit(*p)) {
227 *q = *p;
228 continue;
229 }
230 ac = 0;
231 for (i = 0; i < 3; i++, p++) {
232 if (!isdigit(*p))
233 break;
234 ac = (ac * 8) + (*p - '0');
235 }
236 *q = ac;
237 p--;
238 }
239 *q = 0;
240}
241
dd0bd943
KZ
242static dev_t get_disk(const char *device)
243{
244 struct stat st;
245 dev_t disk;
246
247 if (!stat(device, &st) &&
248 !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk))
249 return disk;
250
251 return 0;
252}
253
254static int is_irrotational_disk(dev_t disk)
255{
256 char path[PATH_MAX];
257 FILE *f;
258 int rc, x;
259
260 rc = snprintf(path, sizeof(path),
261 "/sys/dev/block/%d:%d/queue/rotational",
262 major(disk), minor(disk));
263
0a09eb4e 264 if (rc < 0 || (unsigned int) (rc + 1) > sizeof(path))
dd0bd943
KZ
265 return 0;
266
267 f = fopen(path, "r");
268 if (!f)
269 return 0;
270
0a09eb4e
SK
271 rc = fscanf(f, "%d", &x);
272 if (rc != 1) {
273 if (ferror(f))
274 warn(_("failed to read: %s"), path);
275 else
276 warnx(_("parse error: %s"), path);
277 }
dd0bd943
KZ
278 fclose(f);
279
280 return rc == 1 ? !x : 0;
281}
282
283static void lock_disk(struct fsck_instance *inst)
284{
0a09eb4e 285 dev_t disk = inst->fs->disk ? inst->fs->disk : get_disk(inst->fs->device);
dd0bd943
KZ
286 char *diskname;
287
288 if (!disk || is_irrotational_disk(disk))
289 return;
290
291 diskname = blkid_devno_to_devname(disk);
292 if (!diskname)
293 return;
294
295 if (verbose)
296 printf(_("Locking disk %s ... "), diskname);
297
298 inst->lock = open(diskname, O_CLOEXEC | O_RDONLY);
299 if (inst->lock >= 0) {
300 int rc = -1;
301
302 /* inform users that we're waiting on the lock */
303 if (verbose &&
304 (rc = flock(inst->lock, LOCK_EX | LOCK_NB)) != 0 &&
305 errno == EWOULDBLOCK)
306 printf(_("(waiting) "));
307
308 if (rc != 0 && flock(inst->lock, LOCK_EX) != 0) {
309 close(inst->lock); /* failed */
310 inst->lock = -1;
311 }
312 }
313
314 if (verbose)
fcc058f4
BS
315 /* TRANSLATORS: These are followups to "Locking disk...". */
316 printf("%s.\n", inst->lock >= 0 ? _("succeeded") : _("failed"));
dd0bd943
KZ
317
318 free(diskname);
319 return;
320}
321
322static void unlock_disk(struct fsck_instance *inst)
323{
324 if (inst->lock >= 0) {
325 /* explicitly unlock, don't rely on close(), maybe some library
326 * (e.g. liblkid) has still open the device.
327 */
328 flock(inst->lock, LOCK_UN);
329 close(inst->lock);
330 }
331}
332
607c2a72
KZ
333static void free_instance(struct fsck_instance *i)
334{
dd0bd943
KZ
335 if (lockdisk)
336 unlock_disk(i);
7009077b 337 free(i->prog);
607c2a72
KZ
338 free(i);
339 return;
340}
341
342static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
343 const char *type, const char *opts,
344 int freq, int passno)
345{
346 struct fs_info *fs;
347
0a09eb4e 348 fs = xmalloc(sizeof(struct fs_info));
607c2a72
KZ
349
350 fs->device = string_copy(device);
351 fs->mountpt = string_copy(mntpnt);
352 fs->type = string_copy(type);
353 fs->opts = string_copy(opts ? opts : "");
354 fs->freq = freq;
355 fs->passno = passno;
356 fs->flags = 0;
357 fs->next = NULL;
0c0f93fc
KZ
358 fs->disk = 0;
359 fs->stacked = 0;
607c2a72
KZ
360
361 if (!filesys_info)
362 filesys_info = fs;
363 else
364 filesys_last->next = fs;
365 filesys_last = fs;
366
367 return fs;
368}
369
370
371
372static int parse_fstab_line(char *line, struct fs_info **ret_fs)
373{
374 char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
375 struct fs_info *fs;
376
377 *ret_fs = 0;
378 strip_line(line);
379 cp = line;
380
381 device = parse_word(&cp);
382 if (!device || *device == '#')
383 return 0; /* Ignore blank lines and comments */
384 mntpnt = parse_word(&cp);
385 type = parse_word(&cp);
386 opts = parse_word(&cp);
387 freq = parse_word(&cp);
388 passno = parse_word(&cp);
389
390 if (!mntpnt || !type)
391 return -1;
392
393 parse_escape(device);
394 parse_escape(mntpnt);
395 parse_escape(type);
396 parse_escape(opts);
397 parse_escape(freq);
398 parse_escape(passno);
399
06cb26d9 400 dev = fsprobe_get_devname_by_spec(device);
607c2a72
KZ
401 if (dev)
402 device = dev;
403
404 if (strchr(type, ','))
405 type = 0;
406
407 fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
408 freq ? atoi(freq) : -1,
409 passno ? atoi(passno) : -1);
7009077b 410 free(dev);
607c2a72
KZ
411
412 if (!fs)
413 return -1;
414 *ret_fs = fs;
415 return 0;
416}
417
418static void interpret_type(struct fs_info *fs)
419{
420 char *t;
421
3d4820f4 422 if (fs->type && strcmp(fs->type, "auto") != 0)
607c2a72 423 return;
06cb26d9 424 t = fsprobe_get_fstype_by_devname(fs->device);
607c2a72
KZ
425 if (t) {
426 free(fs->type);
427 fs->type = t;
428 }
429}
430
431/*
432 * Load the filesystem database from /etc/fstab
433 */
434static void load_fs_info(const char *filename)
435{
436 FILE *f;
437 char buf[1024];
438 int lineno = 0;
439 int old_fstab = 1;
440 struct fs_info *fs;
441
442 if ((f = fopen(filename, "r")) == NULL) {
0a09eb4e 443 warn(_("WARNING: couldn't open %s"), filename);
607c2a72
KZ
444 return;
445 }
446 while (!feof(f)) {
447 lineno++;
448 if (!fgets(buf, sizeof(buf), f))
449 break;
450 buf[sizeof(buf)-1] = 0;
451 if (parse_fstab_line(buf, &fs) < 0) {
0a09eb4e
SK
452 warnx(_("WARNING: bad format "
453 "on line %d of %s"), lineno, filename);
607c2a72
KZ
454 continue;
455 }
456 if (!fs)
457 continue;
458 if (fs->passno < 0)
459 fs->passno = 0;
460 else
461 old_fstab = 0;
462 }
463
464 fclose(f);
465
466 if (old_fstab && filesys_info) {
0a09eb4e 467 warnx(_(
607c2a72
KZ
468 "WARNING: Your /etc/fstab does not contain the fsck passno\n"
469 " field. I will kludge around things for you, but you\n"
0a09eb4e 470 " should fix your /etc/fstab file as soon as you can.\n"));
607c2a72
KZ
471
472 for (fs = filesys_info; fs; fs = fs->next) {
473 fs->passno = 1;
474 }
475 }
476}
477
478/* Lookup filesys in /etc/fstab and return the corresponding entry. */
479static struct fs_info *lookup(char *filesys)
480{
481 struct fs_info *fs;
482
483 /* No filesys name given. */
484 if (filesys == NULL)
485 return NULL;
486
487 for (fs = filesys_info; fs; fs = fs->next) {
488 if (!strcmp(filesys, fs->device) ||
489 (fs->mountpt && !strcmp(filesys, fs->mountpt)))
490 break;
491 }
492
493 return fs;
494}
495
496/* Find fsck program for a given fs type. */
497static char *find_fsck(char *type)
498{
41e32d9f
KZ
499 char *s;
500 const char *tpl;
501 static char prog[256];
502 char *p = string_copy(fsck_path);
503 struct stat st;
504
505 /* Are we looking for a program or just a type? */
506 tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
507
508 for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
509 sprintf(prog, tpl, s, type);
510 if (stat(prog, &st) == 0) break;
511 }
512 free(p);
513
514 return(s ? prog : NULL);
607c2a72
KZ
515}
516
517static int progress_active(NOARGS)
518{
519 struct fsck_instance *inst;
520
521 for (inst = instance_list; inst; inst = inst->next) {
522 if (inst->flags & FLAG_DONE)
523 continue;
524 if (inst->flags & FLAG_PROGRESS)
525 return 1;
526 }
527 return 0;
528}
529
530/*
531 * Execute a particular fsck program, and link it into the list of
532 * child processes we are waiting for.
533 */
0c0f93fc 534static int execute(const char *type, struct fs_info *fs, int interactive)
607c2a72
KZ
535{
536 char *s, *argv[80], prog[80];
537 int argc, i;
538 struct fsck_instance *inst, *p;
539 pid_t pid;
540
0a09eb4e 541 inst = xmalloc(sizeof(struct fsck_instance));
607c2a72
KZ
542 memset(inst, 0, sizeof(struct fsck_instance));
543
544 sprintf(prog, "fsck.%s", type);
545 argv[0] = string_copy(prog);
546 argc = 1;
547
548 for (i=0; i <num_args; i++)
549 argv[argc++] = string_copy(args[i]);
550
551 if (progress) {
552 if ((strcmp(type, "ext2") == 0) ||
553 (strcmp(type, "ext3") == 0) ||
554 (strcmp(type, "ext4") == 0) ||
555 (strcmp(type, "ext4dev") == 0)) {
556 char tmp[80];
557
558 tmp[0] = 0;
559 if (!progress_active()) {
560 snprintf(tmp, 80, "-C%d", progress_fd);
561 inst->flags |= FLAG_PROGRESS;
562 } else if (progress_fd)
563 snprintf(tmp, 80, "-C%d", progress_fd * -1);
564 if (tmp[0])
565 argv[argc++] = string_copy(tmp);
566 }
567 }
568
0c0f93fc 569 argv[argc++] = string_copy(fs->device);
607c2a72
KZ
570 argv[argc] = 0;
571
572 s = find_fsck(prog);
573 if (s == NULL) {
0a09eb4e 574 warnx(_("%s: not found"), prog);
607c2a72
KZ
575 free(inst);
576 return ENOENT;
577 }
578
579 if (verbose || noexecute) {
580 printf("[%s (%d) -- %s] ", s, num_running,
0c0f93fc 581 fs->mountpt ? fs->mountpt : fs->device);
607c2a72
KZ
582 for (i=0; i < argc; i++)
583 printf("%s ", argv[i]);
584 printf("\n");
585 }
586
dd0bd943
KZ
587
588 inst->fs = fs;
589 inst->lock = -1;
590
591 if (lockdisk)
592 lock_disk(inst);
593
607c2a72
KZ
594 /* Fork and execute the correct program. */
595 if (noexecute)
596 pid = -1;
597 else if ((pid = fork()) < 0) {
598 perror("fork");
599 free(inst);
600 return errno;
601 } else if (pid == 0) {
602 if (!interactive)
603 close(0);
604 (void) execv(s, argv);
605 perror(argv[0]);
606 free(inst);
607 exit(EXIT_ERROR);
608 }
609
610 for (i=0; i < argc; i++)
611 free(argv[i]);
612
613 inst->pid = pid;
614 inst->prog = string_copy(prog);
615 inst->type = string_copy(type);
607c2a72
KZ
616 inst->start_time = time(0);
617 inst->next = NULL;
618
619 /*
620 * Find the end of the list, so we add the instance on at the end.
621 */
622 for (p = instance_list; p && p->next; p = p->next);
623
624 if (p)
625 p->next = inst;
626 else
627 instance_list = inst;
628
629 return 0;
630}
631
632/*
633 * Send a signal to all outstanding fsck child processes
634 */
635static int kill_all(int signum)
636{
637 struct fsck_instance *inst;
638 int n = 0;
639
640 for (inst = instance_list; inst; inst = inst->next) {
641 if (inst->flags & FLAG_DONE)
642 continue;
643 kill(inst->pid, signum);
644 n++;
645 }
646 return n;
647}
648
649/*
650 * Wait for one child process to exit; when it does, unlink it from
651 * the list of executing child processes, and return it.
652 */
653static struct fsck_instance *wait_one(int flags)
654{
655 int status;
656 int sig;
657 struct fsck_instance *inst, *inst2, *prev;
658 pid_t pid;
659
660 if (!instance_list)
661 return NULL;
662
663 if (noexecute) {
664 inst = instance_list;
665 prev = 0;
666#ifdef RANDOM_DEBUG
667 while (inst->next && (random() & 1)) {
668 prev = inst;
669 inst = inst->next;
670 }
671#endif
672 inst->exit_status = 0;
673 goto ret_inst;
674 }
675
676 /*
677 * gcc -Wall fails saving throw against stupidity
678 * (inst and prev are thought to be uninitialized variables)
679 */
680 inst = prev = NULL;
681
682 do {
683 pid = waitpid(-1, &status, flags);
684 if (cancel_requested && !kill_sent) {
685 kill_all(SIGTERM);
686 kill_sent++;
687 }
688 if ((pid == 0) && (flags & WNOHANG))
689 return NULL;
690 if (pid < 0) {
691 if ((errno == EINTR) || (errno == EAGAIN))
692 continue;
693 if (errno == ECHILD) {
0a09eb4e 694 warnx(_("wait: no more child process?!?"));
607c2a72
KZ
695 return NULL;
696 }
697 perror("wait");
698 continue;
699 }
700 for (prev = 0, inst = instance_list;
701 inst;
702 prev = inst, inst = inst->next) {
703 if (inst->pid == pid)
704 break;
705 }
706 } while (!inst);
707
708 if (WIFEXITED(status))
709 status = WEXITSTATUS(status);
710 else if (WIFSIGNALED(status)) {
711 sig = WTERMSIG(status);
712 if (sig == SIGINT) {
713 status = EXIT_UNCORRECTED;
714 } else {
0a09eb4e
SK
715 warnx(_("Warning... %s for device %s exited "
716 "with signal %d."),
0c0f93fc 717 inst->prog, inst->fs->device, sig);
607c2a72
KZ
718 status = EXIT_ERROR;
719 }
720 } else {
0a09eb4e 721 warnx(_("%s %s: status is %x, should never happen."),
0c0f93fc 722 inst->prog, inst->fs->device, status);
607c2a72
KZ
723 status = EXIT_ERROR;
724 }
725 inst->exit_status = status;
726 inst->flags |= FLAG_DONE;
727 if (progress && (inst->flags & FLAG_PROGRESS) &&
728 !progress_active()) {
729 for (inst2 = instance_list; inst2; inst2 = inst2->next) {
730 if (inst2->flags & FLAG_DONE)
731 continue;
732 if (strcmp(inst2->type, "ext2") &&
733 strcmp(inst2->type, "ext3") &&
734 strcmp(inst2->type, "ext4") &&
735 strcmp(inst2->type, "ext4dev"))
736 continue;
737 /*
738 * If we've just started the fsck, wait a tiny
739 * bit before sending the kill, to give it
740 * time to set up the signal handler
741 */
742 if (inst2->start_time < time(0)+2) {
743 if (fork() == 0) {
744 sleep(1);
745 kill(inst2->pid, SIGUSR1);
0a09eb4e 746 exit(EXIT_OK);
607c2a72
KZ
747 }
748 } else
749 kill(inst2->pid, SIGUSR1);
750 inst2->flags |= FLAG_PROGRESS;
751 break;
752 }
753 }
754ret_inst:
755 if (prev)
756 prev->next = inst->next;
757 else
758 instance_list = inst->next;
759 if (verbose > 1)
760 printf(_("Finished with %s (exit status %d)\n"),
0c0f93fc 761 inst->fs->device, inst->exit_status);
607c2a72
KZ
762 num_running--;
763 return inst;
764}
765
766#define FLAG_WAIT_ALL 0
767#define FLAG_WAIT_ATLEAST_ONE 1
768/*
769 * Wait until all executing child processes have exited; return the
770 * logical OR of all of their exit code values.
771 */
772static int wait_many(int flags)
773{
774 struct fsck_instance *inst;
775 int global_status = 0;
776 int wait_flags = 0;
777
778 while ((inst = wait_one(wait_flags))) {
779 global_status |= inst->exit_status;
780 free_instance(inst);
781#ifdef RANDOM_DEBUG
782 if (noexecute && (flags & WNOHANG) && !(random() % 3))
783 break;
784#endif
785 if (flags & FLAG_WAIT_ATLEAST_ONE)
786 wait_flags = WNOHANG;
787 }
788 return global_status;
789}
790
791/*
792 * Run the fsck program on a particular device
793 *
794 * If the type is specified using -t, and it isn't prefixed with "no"
795 * (as in "noext2") and only one filesystem type is specified, then
796 * use that type regardless of what is specified in /etc/fstab.
797 *
798 * If the type isn't specified by the user, then use either the type
799 * specified in /etc/fstab, or DEFAULT_FSTYPE.
800 */
6c6f2af9 801static int fsck_device(struct fs_info *fs, int interactive)
607c2a72
KZ
802{
803 const char *type;
804 int retval;
805
806 interpret_type(fs);
807
808 if (strcmp(fs->type, "auto") != 0)
809 type = fs->type;
810 else if (fstype && strncmp(fstype, "no", 2) &&
811 strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
812 !strchr(fstype, ','))
813 type = fstype;
814 else
815 type = DEFAULT_FSTYPE;
816
817 num_running++;
0c0f93fc 818 retval = execute(type, fs, interactive);
607c2a72 819 if (retval) {
0a09eb4e
SK
820 warnx(_("error %d while executing fsck.%s for %s"),
821 retval, type, fs->device);
607c2a72 822 num_running--;
6c6f2af9 823 return EXIT_ERROR;
607c2a72 824 }
6c6f2af9 825 return 0;
607c2a72
KZ
826}
827
828
829/*
830 * Deal with the fsck -t argument.
831 */
832struct fs_type_compile {
833 char **list;
834 int *type;
835 int negate;
836} fs_type_compiled;
837
838#define FS_TYPE_NORMAL 0
839#define FS_TYPE_OPT 1
840#define FS_TYPE_NEGOPT 2
841
607c2a72
KZ
842static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
843{
844 char *cp, *list, *s;
845 int num = 2;
846 int negate, first_negate = 1;
847
848 if (fs_type) {
849 for (cp=fs_type; *cp; cp++) {
850 if (*cp == ',')
851 num++;
852 }
853 }
854
0a09eb4e
SK
855 cmp->list = xmalloc(num * sizeof(char *));
856 cmp->type = xmalloc(num * sizeof(int));
607c2a72
KZ
857 memset(cmp->list, 0, num * sizeof(char *));
858 memset(cmp->type, 0, num * sizeof(int));
859 cmp->negate = 0;
860
861 if (!fs_type)
862 return;
863
864 list = string_copy(fs_type);
865 num = 0;
866 s = strtok(list, ",");
867 while(s) {
868 negate = 0;
869 if (strncmp(s, "no", 2) == 0) {
870 s += 2;
871 negate = 1;
872 } else if (*s == '!') {
873 s++;
874 negate = 1;
875 }
876 if (strcmp(s, "loop") == 0)
877 /* loop is really short-hand for opts=loop */
878 goto loop_special_case;
879 else if (strncmp(s, "opts=", 5) == 0) {
880 s += 5;
881 loop_special_case:
882 cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
883 } else {
884 if (first_negate) {
885 cmp->negate = negate;
886 first_negate = 0;
887 }
888 if ((negate && !cmp->negate) ||
889 (!negate && cmp->negate)) {
e0eadc0d
SK
890 errx(EXIT_USAGE,
891 _("Either all or none of the filesystem types passed to -t must be prefixed\n"
892 "with 'no' or '!'."));
607c2a72
KZ
893 }
894 }
895#if 0
896 printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
897#endif
0a09eb4e 898 cmp->list[num++] = string_copy(s);
607c2a72
KZ
899 s = strtok(NULL, ",");
900 }
901 free(list);
902}
903
904/*
905 * This function returns true if a particular option appears in a
906 * comma-delimited options list
907 */
908static int opt_in_list(const char *opt, char *optlist)
909{
910 char *list, *s;
911
912 if (!optlist)
913 return 0;
914 list = string_copy(optlist);
915
916 s = strtok(list, ",");
917 while(s) {
918 if (strcmp(s, opt) == 0) {
919 free(list);
920 return 1;
921 }
922 s = strtok(NULL, ",");
923 }
0a09eb4e 924 free(list);
607c2a72
KZ
925 return 0;
926}
927
928/* See if the filesystem matches the criteria given by the -t option */
929static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
930{
931 int n, ret = 0, checked_type = 0;
932 char *cp;
933
934 if (cmp->list == 0 || cmp->list[0] == 0)
935 return 1;
936
937 for (n=0; (cp = cmp->list[n]); n++) {
938 switch (cmp->type[n]) {
939 case FS_TYPE_NORMAL:
940 checked_type++;
941 if (strcmp(cp, fs->type) == 0) {
942 ret = 1;
943 }
944 break;
945 case FS_TYPE_NEGOPT:
946 if (opt_in_list(cp, fs->opts))
947 return 0;
948 break;
949 case FS_TYPE_OPT:
950 if (!opt_in_list(cp, fs->opts))
951 return 0;
952 break;
953 }
954 }
955 if (checked_type == 0)
956 return 1;
957 return (cmp->negate ? !ret : ret);
958}
959
1bb516c3
LN
960/*
961 * Check if a device exists
962 */
963static int device_exists(const char *device)
964{
965 struct stat st;
966
967 if (stat(device, &st) == -1)
968 return 0;
969
970 if (!S_ISBLK(st.st_mode))
971 return 0;
972
973 return 1;
974}
975
e3174198
KZ
976static int ignored_type(const char *fstype)
977{
978 const char **ip;
979
980 for(ip = ignored_types; *ip; ip++) {
981 if (strcmp(fstype, *ip) == 0)
982 return 1;
983 }
984
985 return 0;
986}
987
607c2a72
KZ
988/* Check if we should ignore this filesystem. */
989static int ignore(struct fs_info *fs)
990{
991 const char **ip;
992 int wanted = 0;
993
994 /*
995 * If the pass number is 0, ignore it.
996 */
997 if (fs->passno == 0)
998 return 1;
999
1000 /*
1001 * If this is a bind mount, ignore it.
1002 */
1003 if (opt_in_list("bind", fs->opts)) {
0a09eb4e
SK
1004 warnx(_("%s: skipping bad line in /etc/fstab: "
1005 "bind mount with nonzero fsck pass number"),
607c2a72
KZ
1006 fs->mountpt);
1007 return 1;
1008 }
1009
1bb516c3
LN
1010 /*
1011 * ignore devices that don't exist and have the "nofail" mount option
1012 */
236acf2d
KZ
1013 if (!device_exists(fs->device)) {
1014 if (opt_in_list("nofail", fs->opts)) {
1015 if (verbose)
1016 printf(_("%s: skipping nonexistent device\n"),
1017 fs->device);
1018 return 1;
1019 }
1bb516c3 1020 if (verbose)
236acf2d
KZ
1021 printf(_("%s: nonexistent device (\"nofail\" fstab "
1022 "option may be used to skip this device)\n"),
1023 fs->device);
1bb516c3
LN
1024 }
1025
607c2a72
KZ
1026 interpret_type(fs);
1027
1028 /*
1029 * If a specific fstype is specified, and it doesn't match,
1030 * ignore it.
1031 */
3d4820f4
KZ
1032 if (!fs_match(fs, &fs_type_compiled))
1033 return 1;
607c2a72
KZ
1034
1035 /* Are we ignoring this type? */
e3174198
KZ
1036 if (fs->type && ignored_type(fs->type))
1037 return 1;
607c2a72 1038
3d4820f4
KZ
1039 if (!fs->type)
1040 return 0; /* should not happen */
1041
607c2a72
KZ
1042 /* Do we really really want to check this fs? */
1043 for(ip = really_wanted; *ip; ip++)
1044 if (strcmp(fs->type, *ip) == 0) {
1045 wanted = 1;
1046 break;
1047 }
1048
1049 /* See if the <fsck.fs> program is available. */
1050 if (find_fsck(fs->type) == NULL) {
1051 if (wanted)
0a09eb4e 1052 warnx(_("cannot check %s: fsck.%s not found"),
607c2a72
KZ
1053 fs->device, fs->type);
1054 return 1;
1055 }
1056
1057 /* We can and want to check this file system type. */
1058 return 0;
1059}
1060
0c0f93fc
KZ
1061static int count_slaves(dev_t disk)
1062{
1063 DIR *dir;
1064 struct dirent *dp;
1065 char dirname[PATH_MAX];
1066 int count = 0;
1067
1068 snprintf(dirname, sizeof(dirname),
1069 "/sys/dev/block/%u:%u/slaves/",
1070 major(disk), minor(disk));
1071
1072 if (!(dir = opendir(dirname)))
1073 return -1;
1074
1075 while ((dp = readdir(dir)) != 0) {
1076#ifdef _DIRENT_HAVE_D_TYPE
1077 if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
1078 continue;
1079#endif
1080 if (dp->d_name[0] == '.' &&
1081 ((dp->d_name[1] == 0) ||
1082 ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
1083 continue;
1084
1085 count++;
1086 }
1087 closedir(dir);
1088 return count;
1089}
1090
607c2a72
KZ
1091/*
1092 * Returns TRUE if a partition on the same disk is already being
1093 * checked.
1094 */
0c0f93fc 1095static int disk_already_active(struct fs_info *fs)
607c2a72
KZ
1096{
1097 struct fsck_instance *inst;
607c2a72
KZ
1098
1099 if (force_all_parallel)
1100 return 0;
1101
0c0f93fc
KZ
1102 if (instance_list && instance_list->fs->stacked)
1103 /* any instance for a stacked device is already running */
607c2a72 1104 return 1;
607c2a72 1105
0c0f93fc 1106 if (!fs->disk) {
dd0bd943
KZ
1107 fs->disk = get_disk(fs->device);
1108 if (fs->disk)
1109 fs->stacked = count_slaves(fs->disk);
0c0f93fc
KZ
1110 }
1111
607c2a72
KZ
1112 /*
1113 * If we don't know the base device, assume that the device is
1114 * already active if there are any fsck instances running.
0c0f93fc
KZ
1115 *
1116 * Don't check a stacked device with any other disk too.
607c2a72 1117 */
0c0f93fc 1118 if (!fs->disk || fs->stacked)
607c2a72 1119 return (instance_list != 0);
0c0f93fc 1120
607c2a72 1121 for (inst = instance_list; inst; inst = inst->next) {
0c0f93fc 1122 if (!inst->fs->disk || fs->disk == inst->fs->disk)
607c2a72 1123 return 1;
607c2a72 1124 }
607c2a72
KZ
1125 return 0;
1126}
1127
1128/* Check all file systems, using the /etc/fstab table. */
1129static int check_all(NOARGS)
1130{
1131 struct fs_info *fs = NULL;
1132 int status = EXIT_OK;
1133 int not_done_yet = 1;
1134 int passno = 1;
1135 int pass_done;
1136
1137 if (verbose)
1138 fputs(_("Checking all file systems.\n"), stdout);
1139
1140 /*
1141 * Do an initial scan over the filesystem; mark filesystems
1142 * which should be ignored as done, and resolve any "auto"
1143 * filesystem types (done as a side-effect of calling ignore()).
1144 */
1145 for (fs = filesys_info; fs; fs = fs->next) {
1146 if (ignore(fs))
1147 fs->flags |= FLAG_DONE;
1148 }
1149
1150 /*
1151 * Find and check the root filesystem.
1152 */
1153 if (!parallel_root) {
1154 for (fs = filesys_info; fs; fs = fs->next) {
1155 if (!strcmp(fs->mountpt, "/"))
1156 break;
1157 }
1158 if (fs) {
1159 if (!skip_root && !ignore(fs) &&
1160 !(ignore_mounted && is_mounted(fs->device))) {
6c6f2af9 1161 status |= fsck_device(fs, 1);
607c2a72
KZ
1162 status |= wait_many(FLAG_WAIT_ALL);
1163 if (status > EXIT_NONDESTRUCT)
1164 return status;
1165 }
1166 fs->flags |= FLAG_DONE;
1167 }
1168 }
1169 /*
1170 * This is for the bone-headed user who enters the root
1171 * filesystem twice. Skip root will skep all root entries.
1172 */
1173 if (skip_root)
1174 for (fs = filesys_info; fs; fs = fs->next)
1175 if (!strcmp(fs->mountpt, "/"))
1176 fs->flags |= FLAG_DONE;
1177
1178 while (not_done_yet) {
1179 not_done_yet = 0;
1180 pass_done = 1;
1181
1182 for (fs = filesys_info; fs; fs = fs->next) {
1183 if (cancel_requested)
1184 break;
1185 if (fs->flags & FLAG_DONE)
1186 continue;
1187 /*
1188 * If the filesystem's pass number is higher
1189 * than the current pass number, then we don't
1190 * do it yet.
1191 */
1192 if (fs->passno > passno) {
1193 not_done_yet++;
1194 continue;
1195 }
1196 if (ignore_mounted && is_mounted(fs->device)) {
1197 fs->flags |= FLAG_DONE;
1198 continue;
1199 }
1200 /*
1201 * If a filesystem on a particular device has
1202 * already been spawned, then we need to defer
1203 * this to another pass.
1204 */
0c0f93fc 1205 if (disk_already_active(fs)) {
607c2a72
KZ
1206 pass_done = 0;
1207 continue;
1208 }
1209 /*
1210 * Spawn off the fsck process
1211 */
6c6f2af9 1212 status |= fsck_device(fs, serialize);
607c2a72
KZ
1213 fs->flags |= FLAG_DONE;
1214
1215 /*
1216 * Only do one filesystem at a time, or if we
1217 * have a limit on the number of fsck's extant
1218 * at one time, apply that limit.
1219 */
1220 if (serialize ||
1221 (max_running && (num_running >= max_running))) {
1222 pass_done = 0;
1223 break;
1224 }
1225 }
1226 if (cancel_requested)
1227 break;
1228 if (verbose > 1)
1229 printf(_("--waiting-- (pass %d)\n"), passno);
1230 status |= wait_many(pass_done ? FLAG_WAIT_ALL :
1231 FLAG_WAIT_ATLEAST_ONE);
1232 if (pass_done) {
1233 if (verbose > 1)
1234 printf("----------------------------------\n");
1235 passno++;
1236 } else
1237 not_done_yet++;
1238 }
1239 if (cancel_requested && !kill_sent) {
1240 kill_all(SIGTERM);
1241 kill_sent++;
1242 }
1243 status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
1244 return status;
1245}
1246
0a09eb4e 1247static void __attribute__((__noreturn__)) usage(void)
607c2a72 1248{
0a09eb4e
SK
1249 printf(_("\nUsage:\n"
1250 " %s [fsck-options] [fs-options] [filesys ...]\n"),
1251 program_invocation_short_name);
1252
1253 puts(_( "\nOptions:\n"
e6e060ec
KZ
1254 " -A check all filesystems\n"
1255 " -R skip root filesystem; useful only with `-A'\n"
1256 " -M do not check mounted filesystems\n"
be060aa1
KZ
1257 " -t <type> specify filesystem types to be checked;\n"
1258 " type is allowed to be comma-separated list\n"
e6e060ec
KZ
1259 " -P check filesystems in parallel, including root\n"
1260 " -s serialize fsck operations\n"
1261 " -l lock the device using flock()\n"
1262 " -N do not execute, just show what would be done\n"
1263 " -T do not show the title on startup\n"
be060aa1 1264 " -C <fd> display progress bar; file descriptor is for GUIs\n"
e6e060ec
KZ
1265 " -V explain what is being done\n"
1266 " -? display this help and exit\n\n"
0a09eb4e
SK
1267 "See fsck.* commands for fs-options."));
1268
607c2a72
KZ
1269 exit(EXIT_USAGE);
1270}
1271
1272static void signal_cancel(int sig FSCK_ATTR((unused)))
1273{
1274 cancel_requested++;
1275}
1276
1277static void PRS(int argc, char *argv[])
1278{
1279 int i, j;
1280 char *arg, *dev, *tmp = 0;
1281 char options[128];
1282 int opt = 0;
1283 int opts_for_fsck = 0;
1284 struct sigaction sa;
1285
1286 /*
1287 * Set up signal action
1288 */
1289 memset(&sa, 0, sizeof(struct sigaction));
1290 sa.sa_handler = signal_cancel;
1291 sigaction(SIGINT, &sa, 0);
1292 sigaction(SIGTERM, &sa, 0);
1293
1294 num_devices = 0;
1295 num_args = 0;
1296 instance_list = 0;
1297
607c2a72
KZ
1298 for (i=1; i < argc; i++) {
1299 arg = argv[i];
1300 if (!arg)
1301 continue;
1302 if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
0a09eb4e
SK
1303 if (num_devices >= MAX_DEVICES)
1304 errx(EXIT_ERROR, _("too many devices"));
06cb26d9 1305 dev = fsprobe_get_devname_by_spec(arg);
607c2a72
KZ
1306 if (!dev && strchr(arg, '=')) {
1307 /*
1308 * Check to see if we failed because
1309 * /proc/partitions isn't found.
1310 */
fb429f22 1311 if (access(_PATH_PROC_PARTITIONS, R_OK) < 0) {
0a09eb4e
SK
1312 warn(_("couldn't open %s"),
1313 _PATH_PROC_PARTITIONS);
1314 errx(EXIT_ERROR, _("Is /proc mounted?"));
607c2a72
KZ
1315 }
1316 /*
1317 * Check to see if this is because
1318 * we're not running as root
1319 */
1320 if (geteuid())
0a09eb4e
SK
1321 errx(EXIT_ERROR,
1322 _("must be root to scan for matching filesystems: %s"),
1323 arg);
607c2a72 1324 else
0a09eb4e
SK
1325 errx(EXIT_ERROR,
1326 _("couldn't find matching filesystem: %s"),
1327 arg);
607c2a72
KZ
1328 }
1329 devices[num_devices++] = dev ? dev : string_copy(arg);
1330 continue;
1331 }
1332 if (arg[0] != '-' || opts_for_fsck) {
0a09eb4e
SK
1333 if (num_args >= MAX_ARGS)
1334 errx(EXIT_ERROR, _("too many arguments"));
607c2a72
KZ
1335 args[num_args++] = string_copy(arg);
1336 continue;
1337 }
1338 for (j=1; arg[j]; j++) {
1339 if (opts_for_fsck) {
1340 options[++opt] = arg[j];
1341 continue;
1342 }
1343 switch (arg[j]) {
1344 case 'A':
0a09eb4e 1345 doall = 1;
607c2a72
KZ
1346 break;
1347 case 'C':
0a09eb4e 1348 progress = 1;
607c2a72
KZ
1349 if (arg[j+1]) {
1350 progress_fd = string_to_int(arg+j+1);
1351 if (progress_fd < 0)
1352 progress_fd = 0;
1353 else
1354 goto next_arg;
1355 } else if ((i+1) < argc &&
1356 !strncmp(argv[i+1], "-", 1) == 0) {
1357 progress_fd = string_to_int(argv[i]);
1358 if (progress_fd < 0)
1359 progress_fd = 0;
1360 else {
f1c2eaac 1361 ++i;
607c2a72 1362 goto next_arg;
607c2a72
KZ
1363 }
1364 }
1365 break;
dd0bd943 1366 case 'l':
0a09eb4e 1367 lockdisk = 1;
dd0bd943 1368 break;
607c2a72
KZ
1369 case 'V':
1370 verbose++;
1371 break;
1372 case 'N':
0a09eb4e 1373 noexecute = 1;
607c2a72
KZ
1374 break;
1375 case 'R':
0a09eb4e 1376 skip_root = 1;
607c2a72
KZ
1377 break;
1378 case 'T':
0a09eb4e 1379 notitle = 1;
607c2a72
KZ
1380 break;
1381 case 'M':
0a09eb4e 1382 ignore_mounted = 1;
607c2a72
KZ
1383 break;
1384 case 'P':
0a09eb4e 1385 parallel_root = 1;
607c2a72
KZ
1386 break;
1387 case 's':
0a09eb4e 1388 serialize = 1;
607c2a72
KZ
1389 break;
1390 case 't':
1391 tmp = 0;
1392 if (fstype)
1393 usage();
1394 if (arg[j+1])
1395 tmp = arg+j+1;
1396 else if ((i+1) < argc)
1397 tmp = argv[++i];
1398 else
1399 usage();
1400 fstype = string_copy(tmp);
1401 compile_fs_type(fstype, &fs_type_compiled);
1402 goto next_arg;
1403 case '-':
1404 opts_for_fsck++;
1405 break;
1406 case '?':
1407 usage();
1408 break;
1409 default:
1410 options[++opt] = arg[j];
1411 break;
1412 }
1413 }
1414 next_arg:
1415 if (opt) {
1416 options[0] = '-';
1417 options[++opt] = '\0';
0a09eb4e
SK
1418 if (num_args >= MAX_ARGS)
1419 errx(EXIT_ERROR, _("too many arguments"));
607c2a72
KZ
1420 args[num_args++] = string_copy(options);
1421 opt = 0;
1422 }
1423 }
1424 if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1425 force_all_parallel++;
1426 if ((tmp = getenv("FSCK_MAX_INST")))
1427 max_running = atoi(tmp);
1428}
1429
1430int main(int argc, char *argv[])
1431{
1432 int i, status = 0;
1433 int interactive = 0;
1434 char *oldpath = getenv("PATH");
1435 const char *fstab;
1436 struct fs_info *fs;
1437
1438 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
1439 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
1440
1441 setlocale(LC_MESSAGES, "");
1442 setlocale(LC_CTYPE, "");
1443 bindtextdomain(PACKAGE, LOCALEDIR);
1444 textdomain(PACKAGE);
1445
06cb26d9 1446 fsprobe_init();
607c2a72
KZ
1447 PRS(argc, argv);
1448
1449 if (!notitle)
0a09eb4e 1450 printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING);
607c2a72
KZ
1451
1452 fstab = getenv("FSTAB_FILE");
1453 if (!fstab)
1454 fstab = _PATH_MNTTAB;
1455 load_fs_info(fstab);
1456
1457 /* Update our search path to include uncommon directories. */
1458 if (oldpath) {
0a09eb4e 1459 fsck_path = xmalloc (strlen (fsck_prefix_path) + 1 +
607c2a72 1460 strlen (oldpath) + 1);
607c2a72
KZ
1461 strcpy (fsck_path, fsck_prefix_path);
1462 strcat (fsck_path, ":");
1463 strcat (fsck_path, oldpath);
1464 } else {
1465 fsck_path = string_copy(fsck_prefix_path);
1466 }
1467
1468 if ((num_devices == 1) || (serialize))
1469 interactive = 1;
1470
dd0bd943 1471 if (lockdisk && (doall || num_devices > 1)) {
0a09eb4e
SK
1472 warnx(_("the -l option can be used with one "
1473 "device only -- ignore"));
dd0bd943
KZ
1474 lockdisk = 0;
1475 }
1476
607c2a72
KZ
1477 /* If -A was specified ("check all"), do that! */
1478 if (doall)
1479 return check_all();
1480
1481 if (num_devices == 0) {
1482 serialize++;
1483 interactive++;
1484 return check_all();
1485 }
1486 for (i = 0 ; i < num_devices; i++) {
1487 if (cancel_requested) {
1488 if (!kill_sent) {
1489 kill_all(SIGTERM);
1490 kill_sent++;
1491 }
1492 break;
1493 }
1494 fs = lookup(devices[i]);
1495 if (!fs) {
1496 fs = create_fs_device(devices[i], 0, "auto",
1497 0, -1, -1);
1498 if (!fs)
1499 continue;
e3174198
KZ
1500 } else if (fs->type && ignored_type(fs->type))
1501 continue;
1502
607c2a72
KZ
1503 if (ignore_mounted && is_mounted(fs->device))
1504 continue;
6c6f2af9 1505 status |= fsck_device(fs, interactive);
607c2a72
KZ
1506 if (serialize ||
1507 (max_running && (num_running >= max_running))) {
1508 struct fsck_instance *inst;
1509
1510 inst = wait_one(0);
1511 if (inst) {
1512 status |= inst->exit_status;
1513 free_instance(inst);
1514 }
1515 if (verbose > 1)
1516 printf("----------------------------------\n");
1517 }
1518 }
1519 status |= wait_many(FLAG_WAIT_ALL);
1520 free(fsck_path);
06cb26d9 1521 fsprobe_exit();
607c2a72
KZ
1522 return status;
1523}
fb429f22 1524