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