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