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