fsck.c revision 5e38fed9c5e5c0741ff00fc7001b44a075bfb64c
1ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj/*
2ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj * pfsck --- A generic, parallelizing front-end for the fsck program.
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj * It will automatically try to run fsck programs in parallel if the
4ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj * devices are on separate spindles.  It is based on the same ideas as
5ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj * the generic front end for fsck by David Engel and Fred van Kempen,
6f8ed9d874a7b8651654591c68c6d431c758d787csewardj * but it has been completely rewritten from scratch to support
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj * parallel execution.
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj *
9f8ed9d874a7b8651654591c68c6d431c758d787csewardj * Written by Theodore Ts'o, <tytso@mit.edu>
1089ae8477745fd2a15453557d729a50e627325ee2sewardj *
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj * Usage:	fsck [-ACVRNTM] [-s] [-t fstype] [fs-options] device
127bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj *
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj *   o Changed -t fstype to behave like with mount when -A (all file
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj *     systems) or -M (like mount) is specified.
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj *   o fsck looks if it can find the fsck.type program to decide
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj *     if it should ignore the fs type. This way more fsck programs
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj *     can be added without changing this front-end.
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj *   o -R flag skip root file system.
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj *
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj *
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj * %Begin-Header%
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj * This file may be redistributed under the terms of the GNU Public
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj * License.
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj * %End-Header%
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj */
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj
29f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <sys/types.h>
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <sys/wait.h>
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <sys/signal.h>
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <sys/stat.h>
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <limits.h>
34f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <stdio.h>
35f8ed9d874a7b8651654591c68c6d431c758d787csewardj#include <ctype.h>
36887a11a609f3e61d2ae8fe4e67f176207715da7esewardj#include <string.h>
37887a11a609f3e61d2ae8fe4e67f176207715da7esewardj#include <time.h>
38ac9af021b93dfe6f35c01d9c6fd15a3d67685843sewardj#if HAVE_STDLIB_H
39887a11a609f3e61d2ae8fe4e67f176207715da7esewardj#include <stdlib.h>
40ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj#endif
4157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#if HAVE_ERRNO_H
42ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj#include <errno.h>
4357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#endif
4457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#if HAVE_PATHS_H
4557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#include <paths.h>
4657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#endif
4757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#if HAVE_UNISTD_H
4857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#include <unistd.h>
4957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#endif
5057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#if HAVE_ERRNO_H
5157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#include <errno.h>
5257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#endif
53dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#if HAVE_MALLOC_H
54dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#include <malloc.h>
55dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#endif
56dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj
5757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#include "../version.h"
58dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#include "nls-enable.h"
5957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#include "fsck.h"
60dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#include "blkid/blkid.h"
6157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
62dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#ifndef _PATH_MNTTAB
63dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#define	_PATH_MNTTAB	"/etc/fstab"
64dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj#endif
65dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj
6657c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic const char *ignored_types[] = {
6757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"ignore",
6857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"iso9660",
6957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"nfs",
7057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"proc",
7157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"sw",
7257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"swap",
7357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"tmpfs",
7457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"devpts",
7557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	NULL
7657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj};
7757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
7857c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic const char *really_wanted[] = {
7957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"minix",
8057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"ext2",
8157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"ext3",
8257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"jfs",
8357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"reiserfs",
8457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"xiafs",
8557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	"xfs",
8657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	NULL
8757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj};
8857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
8957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj#define BASE_MD "/dev/md"
9057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
9157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj/*
9257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj * Global variables for options
93dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj */
94dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjchar *devices[MAX_DEVICES];
95dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjchar *args[MAX_ARGS];
96dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjint num_devices, num_args;
97dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj
9857c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint verbose = 0;
9957c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint doall = 0;
10057c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint noexecute = 0;
10157c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint serialize = 0;
10257c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint skip_root = 0;
10357c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint like_mount = 0;
10457c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint notitle = 0;
10557c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint parallel_root = 0;
10657c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint progress = 0;
1072f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardjint force_all_parallel = 0;
10857c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint num_running = 0;
10957c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint max_running = 0;
11057c10c89904f7fdc4244fcbf704625e7169aafe6sewardjvolatile int cancel_requested = 0;
11157c10c89904f7fdc4244fcbf704625e7169aafe6sewardjint kill_sent = 0;
11257c10c89904f7fdc4244fcbf704625e7169aafe6sewardjchar *progname;
11357c10c89904f7fdc4244fcbf704625e7169aafe6sewardjchar *fstype = NULL;
11457c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstruct fs_info *filesys_info = NULL, *filesys_last = NULL;
11557c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstruct fsck_instance *instance_list;
11657c10c89904f7fdc4244fcbf704625e7169aafe6sewardjconst char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc";
11757c10c89904f7fdc4244fcbf704625e7169aafe6sewardjchar *fsck_path = 0;
11857c10c89904f7fdc4244fcbf704625e7169aafe6sewardjblkid_cache cache = NULL;
11957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
12057c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic char *string_copy(const char *s)
12157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
12257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	char	*ret;
12357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
12457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (!s)
12557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		return 0;
12657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	ret = malloc(strlen(s)+1);
12757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (ret)
12857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		strcpy(ret, s);
12957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	return ret;
13057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
13157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
13257c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic int ignore(struct fs_info *);
13357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
13457c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic char *skip_over_blank(char *cp)
13557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
13657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	while (*cp && isspace(*cp))
13757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		cp++;
13857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	return cp;
13957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
14057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
14157c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic char *skip_over_word(char *cp)
14257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
14357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	while (*cp && !isspace(*cp))
14457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		cp++;
14557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	return cp;
14657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
14757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
14857c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic void strip_line(char *line)
14957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
1502f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj	char	*p;
15157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
15257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	while (*line) {
15357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		p = line + strlen(line) - 1;
15457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if ((*p == '\n') || (*p == '\r'))
15557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj			*p = 0;
15657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		else
15757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj			break;
15857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	}
15957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
16057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
16157c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic char *parse_word(char **buf)
16257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
16357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	char *word, *next;
16457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
16557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	word = *buf;
16657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (*word == 0)
16757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		return 0;
16857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
16957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	word = skip_over_blank(word);
170dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj	next = skip_over_word(word);
17157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (*next)
17257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		*next++ = 0;
17357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	*buf = next;
17457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	return word;
17557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
17657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
17757c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic void parse_escape(char *word)
17857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
17957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	char	*p, *q;
18057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	int	ac, i;
18157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
18257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (!word)
18357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		return;
18457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
18557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	for (p = word, q = word; *p; p++, q++) {
18657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		*q = *p;
18757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if (*p != '\\')
188ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj			continue;
189ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj		if (*++p == 0)
190ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj			break;
191496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		if (*p == 't') {
192496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			*q = '\t';
193496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			continue;
194496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		}
195496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		if (*p == 'n') {
196496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			*q = '\n';
197496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			continue;
198496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		}
199496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		if (!isdigit(*p)) {
200496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			*q = *p;
201496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			continue;
202496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		}
203496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		ac = 0;
204dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj		for (i = 0; i < 3; i++, p++) {
205496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj			if (!isdigit(*p))
206f6c8ebf1294fea43756683ba7089b746168abb8esewardj				break;
207f6c8ebf1294fea43756683ba7089b746168abb8esewardj			ac = (ac * 8) + (*p - '0');
208496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		}
209dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj		*q = ac;
210496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		p--;
211f6c8ebf1294fea43756683ba7089b746168abb8esewardj	}
212f6c8ebf1294fea43756683ba7089b746168abb8esewardj	*q = 0;
213496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
214496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
215c97096c44637ae5775ed305b19f16f0b505f17d8sewardjstatic void free_instance(struct fsck_instance *i)
216e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj{
21757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (i->prog)
21857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		free(i->prog);
219e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	if (i->device)
220c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		free(i->device);
221cfe046e178666280b87da998b1b52ecda03ecd89sewardj	if (i->base_device)
222c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj		free(i->base_device);
223c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	free(i);
224c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	return;
225c9a43665879a03886b27a65b68af2a2c11b04f59sewardj}
226c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
2279b96767debeeb1f78378f0e7e295fe6762c64002sewardjstatic struct fs_info *create_fs_device(const char *device, const char *mntpnt,
228c9a43665879a03886b27a65b68af2a2c11b04f59sewardj					const char *type, const char *opts,
229c9a43665879a03886b27a65b68af2a2c11b04f59sewardj					int freq, int passno)
230c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
231c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	struct fs_info *fs;
232c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (!(fs = malloc(sizeof(struct fs_info))))
234c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj		return NULL;
235c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj
236d1725d18b61bf7912a9099686179faef5815dba1sewardj	fs->device = string_copy(device);
237e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	fs->mountpt = string_copy(mntpnt);
238e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	fs->type = string_copy(type);
23957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	fs->opts = string_copy(opts ? opts : "");
24035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj	fs->freq = freq;
24157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	fs->passno = passno;
24257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	fs->flags = 0;
24357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	fs->next = NULL;
244c97096c44637ae5775ed305b19f16f0b505f17d8sewardj
2457d00913f2ac5014a145a899b6ee4b8511539221fsewardj	if (!filesys_info)
2467d00913f2ac5014a145a899b6ee4b8511539221fsewardj		filesys_info = fs;
2477d00913f2ac5014a145a899b6ee4b8511539221fsewardj	else
2487d00913f2ac5014a145a899b6ee4b8511539221fsewardj		filesys_last->next = fs;
249e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	filesys_last = fs;
250af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
251af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	return fs;
25257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj}
253af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
254af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
255cfe046e178666280b87da998b1b52ecda03ecd89sewardj
256c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardjstatic int parse_fstab_line(char *line, struct fs_info **ret_fs)
257af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj{
258af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	char	*dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
259af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	struct fs_info *fs;
260af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
261c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	*ret_fs = 0;
262ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	strip_line(line);
26357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if ((cp = strchr(line, '#')))
26457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		*cp = 0;	/* Ignore everything after the comment char */
26557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	cp = line;
266ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj
267c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	device = parse_word(&cp);
268cfe046e178666280b87da998b1b52ecda03ecd89sewardj	mntpnt = parse_word(&cp);
269c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	type = parse_word(&cp);
270c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	opts = parse_word(&cp);
271c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	freq = parse_word(&cp);
272c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	passno = parse_word(&cp);
2732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (!device)
2752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		return 0;	/* Allow blank lines */
2761e6ad745ebafd0524da1da27a4b85524fa84f777sewardj
2771e6ad745ebafd0524da1da27a4b85524fa84f777sewardj	if (!mntpnt || !type)
2781e6ad745ebafd0524da1da27a4b85524fa84f777sewardj		return -1;
27937a505b5a6814921fcfff1eac950a9ef7651e42bsewardj
28057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	parse_escape(device);
28137a505b5a6814921fcfff1eac950a9ef7651e42bsewardj	parse_escape(mntpnt);
28237a505b5a6814921fcfff1eac950a9ef7651e42bsewardj	parse_escape(type);
283207557ab2ea38239b670785c976b89d50bbb0eccsewardj	parse_escape(opts);
284ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	parse_escape(freq);
285ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	parse_escape(passno);
28657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
28757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	dev = blkid_get_devname(cache, device, NULL);
28857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	if (dev)
28957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		device = dev;
290ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj
291e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	if (strchr(type, ','))
292ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj		type = 0;
293ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj
294ba99931f6dfa264d7bc7c3845a46fc955ab56d93sewardj	fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
295c97096c44637ae5775ed305b19f16f0b505f17d8sewardj			      freq ? atoi(freq) : -1,
296c97096c44637ae5775ed305b19f16f0b505f17d8sewardj			      passno ? atoi(passno) : -1);
297c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	if (dev)
298c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		free(dev);
2992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
3002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (!fs)
301a58ea668d4725b87a146cf43cc48b8ea6ead84casewardj		return -1;
30217442fe8094d0f82266e5a05509f62cac8f7539esewardj	*ret_fs = fs;
30357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	return 0;
30437a505b5a6814921fcfff1eac950a9ef7651e42bsewardj}
305ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj
306ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardjstatic void interpret_type(struct fs_info *fs)
307ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj{
308ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	char	*t;
30957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
310ba99931f6dfa264d7bc7c3845a46fc955ab56d93sewardj	if (strcmp(fs->type, "auto") != 0)
31117442fe8094d0f82266e5a05509f62cac8f7539esewardj		return;
31217442fe8094d0f82266e5a05509f62cac8f7539esewardj	t = blkid_get_tag_value(cache, "TYPE", fs->device);
31317442fe8094d0f82266e5a05509f62cac8f7539esewardj	if (t) {
31417442fe8094d0f82266e5a05509f62cac8f7539esewardj		free(fs->type);
3152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		fs->type = t;
3162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	}
31717442fe8094d0f82266e5a05509f62cac8f7539esewardj}
31817442fe8094d0f82266e5a05509f62cac8f7539esewardj
3191e6ad745ebafd0524da1da27a4b85524fa84f777sewardj/*
32037a505b5a6814921fcfff1eac950a9ef7651e42bsewardj * Load the filesystem database from /etc/fstab
321c97096c44637ae5775ed305b19f16f0b505f17d8sewardj */
32257c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic void load_fs_info(const char *filename)
323dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj{
324695cff9303ef5dc8079117acfd632b44edb1f010sewardj	FILE	*f;
32557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	char	buf[1024];
32635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj	int	lineno = 0;
32757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	int	old_fstab = 1;
32857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	struct fs_info *fs;
3294345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
330ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	if ((f = fopen(filename, "r")) == NULL) {
331c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		fprintf(stderr, _("WARNING: couldn't open %s: %s\n"),
3328ea867b06de73d909c29e243407713c291c8414esewardj			filename, strerror(errno));
3338ea867b06de73d909c29e243407713c291c8414esewardj		return;
3348ea867b06de73d909c29e243407713c291c8414esewardj	}
33577352545d8416a36a4e6310aaea6b0205508aea2sewardj	while (!feof(f)) {
3368ea867b06de73d909c29e243407713c291c8414esewardj		lineno++;
33703d91140809def2f5afc04b0cc9beb0f4f0a1b13sewardj		if (!fgets(buf, sizeof(buf), f))
33803d91140809def2f5afc04b0cc9beb0f4f0a1b13sewardj			break;
33903d91140809def2f5afc04b0cc9beb0f4f0a1b13sewardj		buf[sizeof(buf)-1] = 0;
34003d91140809def2f5afc04b0cc9beb0f4f0a1b13sewardj		if (parse_fstab_line(buf, &fs) < 0) {
34143c56461a667ca81fe29f1db01450d6ff1d62949sewardj			fprintf(stderr, _("WARNING: bad format "
34243c56461a667ca81fe29f1db01450d6ff1d62949sewardj				"on line %d of %s\n"), lineno, filename);
34343c56461a667ca81fe29f1db01450d6ff1d62949sewardj			continue;
34443c56461a667ca81fe29f1db01450d6ff1d62949sewardj		}
34543c56461a667ca81fe29f1db01450d6ff1d62949sewardj		if (!fs)
34643c56461a667ca81fe29f1db01450d6ff1d62949sewardj			continue;
34743c56461a667ca81fe29f1db01450d6ff1d62949sewardj		if (fs->passno < 0)
3488ea867b06de73d909c29e243407713c291c8414esewardj			fs->passno = 0;
3498ea867b06de73d909c29e243407713c291c8414esewardj		else
3508ea867b06de73d909c29e243407713c291c8414esewardj			old_fstab = 0;
3511ff4756e1731485e6bf3cd96717cd8398daec1f2florian	}
3521ff4756e1731485e6bf3cd96717cd8398daec1f2florian
3531ff4756e1731485e6bf3cd96717cd8398daec1f2florian	fclose(f);
3541ff4756e1731485e6bf3cd96717cd8398daec1f2florian
3558ea867b06de73d909c29e243407713c291c8414esewardj	if (old_fstab) {
3568ea867b06de73d909c29e243407713c291c8414esewardj		fprintf(stderr, _("\007\007\007"
3578ea867b06de73d909c29e243407713c291c8414esewardj		"WARNING: Your /etc/fstab does not contain the fsck passno\n"
35857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		"	field.  I will kludge around things for you, but you\n"
3591ff4756e1731485e6bf3cd96717cd8398daec1f2florian		"	should fix your /etc/fstab file as soon as you can.\n\n"));
3608ea867b06de73d909c29e243407713c291c8414esewardj
36157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		for (fs = filesys_info; fs; fs = fs->next) {
362dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj			fs->passno = 1;
3638ea867b06de73d909c29e243407713c291c8414esewardj		}
36457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	}
3658ea867b06de73d909c29e243407713c291c8414esewardj}
3668ea867b06de73d909c29e243407713c291c8414esewardj
3678ea867b06de73d909c29e243407713c291c8414esewardj/* Lookup filesys in /etc/fstab and return the corresponding entry. */
3682d3f77c12d2911173fd182d0b6e954196dee9135sewardjstatic struct fs_info *lookup(char *filesys)
3692d3f77c12d2911173fd182d0b6e954196dee9135sewardj{
37057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	struct fs_info *fs;
37157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
37257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	/* No filesys name given. */
3732d3f77c12d2911173fd182d0b6e954196dee9135sewardj	if (filesys == NULL)
3742d3f77c12d2911173fd182d0b6e954196dee9135sewardj		return NULL;
37557c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
37657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	for (fs = filesys_info; fs; fs = fs->next) {
37757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if (!strcmp(filesys, fs->device) ||
3782d3f77c12d2911173fd182d0b6e954196dee9135sewardj		    (fs->mountpt && !strcmp(filesys, fs->mountpt)))
379dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj			break;
3802d3f77c12d2911173fd182d0b6e954196dee9135sewardj	}
381dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj
3822d3f77c12d2911173fd182d0b6e954196dee9135sewardj	return fs;
383dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj}
384695cff9303ef5dc8079117acfd632b44edb1f010sewardj
385dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* Find fsck program for a given fs type. */
386dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic char *find_fsck(char *type)
3872d3f77c12d2911173fd182d0b6e954196dee9135sewardj{
3882d3f77c12d2911173fd182d0b6e954196dee9135sewardj  char *s;
389c97096c44637ae5775ed305b19f16f0b505f17d8sewardj  const char *tpl;
390ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj  static char prog[256];
39157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj  char *p = string_copy(fsck_path);
39257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj  struct stat st;
39357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
394fbcaf3312f39fb73d54821636c6168db76245f61sewardj  /* Are we looking for a program or just a type? */
395ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj  tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
39657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
39735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj  for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
398c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	sprintf(prog, tpl, s, type);
39992d168d0f2a985ed9f7ae4e6bba9565a13921b31sewardj	if (stat(prog, &st) == 0) break;
400fbcaf3312f39fb73d54821636c6168db76245f61sewardj  }
401ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj  free(p);
40240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj  return(s ? prog : NULL);
403ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj}
40457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
40557c10c89904f7fdc4244fcbf704625e7169aafe6sewardjstatic int progress_active(NOARGS)
40657c10c89904f7fdc4244fcbf704625e7169aafe6sewardj{
40757c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	struct fsck_instance *inst;
40857c10c89904f7fdc4244fcbf704625e7169aafe6sewardj
40957c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	for (inst = instance_list; inst; inst = inst->next) {
41057c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if (inst->flags & FLAG_DONE)
41157c10c89904f7fdc4244fcbf704625e7169aafe6sewardj			continue;
41257c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if (inst->flags & FLAG_PROGRESS)
41357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj			return 1;
414ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	}
41541f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	return 0;
41671a35e7351fc1202ef2960d3f0315d9181624fe2sewardj}
41771a35e7351fc1202ef2960d3f0315d9181624fe2sewardj
41871a35e7351fc1202ef2960d3f0315d9181624fe2sewardj/*
419cfe046e178666280b87da998b1b52ecda03ecd89sewardj * Execute a particular fsck program, and link it into the list of
42066de22767fc526eff52133c18d4a42a9b25d5f18sewardj * child processes we are waiting for.
42141f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj */
42241f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardjstatic int execute(const char *type, const char *device, const char *mntpt,
42341f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj		   int interactive)
42441f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj{
42541f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	char *s, *argv[80], prog[80];
42641f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	int  argc, i;
42741f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	struct fsck_instance *inst, *p;
42841f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	pid_t	pid;
42941f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
430e90ad6abbe540a5b3ffa68ba0c641ced77c20211sewardj	inst = malloc(sizeof(struct fsck_instance));
431e90ad6abbe540a5b3ffa68ba0c641ced77c20211sewardj	if (!inst)
432e90ad6abbe540a5b3ffa68ba0c641ced77c20211sewardj		return ENOMEM;
43341f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj	memset(inst, 0, sizeof(struct fsck_instance));
43441f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
43571a35e7351fc1202ef2960d3f0315d9181624fe2sewardj	sprintf(prog, "fsck.%s", type);
4361fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj	argv[0] = string_copy(prog);
4371fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj	argc = 1;
4381fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj
4391fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj	for (i=0; i <num_args; i++)
4401fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj		argv[argc++] = string_copy(args[i]);
4411fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj
4421fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj	if (progress & !progress_active()) {
4431fb8c92e9b0882ebbd53c04c69ebad7efb1cd3d8sewardj		if ((strcmp(type, "ext2") == 0) ||
444e13074c2c1321d069fb95806bdce64f9a3512341sewardj		    (strcmp(type, "ext3") == 0)) {
445e13074c2c1321d069fb95806bdce64f9a3512341sewardj			argv[argc++] = string_copy("-C0");
446e13074c2c1321d069fb95806bdce64f9a3512341sewardj			inst->flags |= FLAG_PROGRESS;
447e13074c2c1321d069fb95806bdce64f9a3512341sewardj		}
44871a35e7351fc1202ef2960d3f0315d9181624fe2sewardj	}
44971a35e7351fc1202ef2960d3f0315d9181624fe2sewardj
4509690d927540d730525a5f7f14663f3ceaa7818dasewardj	argv[argc++] = string_copy(device);
4519b96767debeeb1f78378f0e7e295fe6762c64002sewardj	argv[argc] = 0;
4529b96767debeeb1f78378f0e7e295fe6762c64002sewardj
4538f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	s = find_fsck(prog);
454ce646f23d71ac432c340667387aa4a5ce7d18099sewardj	if (s == NULL) {
455f53b7359a342e7d79090615169c6583a1a75fbcesewardj		fprintf(stderr, _("fsck: %s: not found\n"), prog);
456f53b7359a342e7d79090615169c6583a1a75fbcesewardj		return ENOENT;
457f53b7359a342e7d79090615169c6583a1a75fbcesewardj	}
458f53b7359a342e7d79090615169c6583a1a75fbcesewardj
4598f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	if (verbose || noexecute) {
4608f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		printf("[%s (%d) -- %s] ", s, num_running,
461b51f0f4f33256638ed953156a2635aa739b232f1sewardj		       mntpt ? mntpt : device);
4629854007808ab24cad3f971eab63face1cb1e6089sewardj		for (i=0; i < argc; i++)
4639854007808ab24cad3f971eab63face1cb1e6089sewardj			printf("%s ", argv[i]);
4649854007808ab24cad3f971eab63face1cb1e6089sewardj		printf("\n");
4659854007808ab24cad3f971eab63face1cb1e6089sewardj	}
466343b9d0f6be20948ab2f4fe87de55835f96fe30asewardj
4670033ddccac6f90789fe2e78e86b8a649931d77b4sewardj	/* Fork and execute the correct program. */
4680033ddccac6f90789fe2e78e86b8a649931d77b4sewardj	if (noexecute)
469eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj		pid = -1;
470eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj	else if ((pid = fork()) < 0) {
471478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj		perror("fork");
4720033ddccac6f90789fe2e78e86b8a649931d77b4sewardj		return errno;
47357c10c89904f7fdc4244fcbf704625e7169aafe6sewardj	} else if (pid == 0) {
47457c10c89904f7fdc4244fcbf704625e7169aafe6sewardj		if (!interactive)
475b51f0f4f33256638ed953156a2635aa739b232f1sewardj			close(0);
476b51f0f4f33256638ed953156a2635aa739b232f1sewardj		(void) execv(s, argv);
477b51f0f4f33256638ed953156a2635aa739b232f1sewardj		perror(argv[0]);
478b51f0f4f33256638ed953156a2635aa739b232f1sewardj		exit(EXIT_ERROR);
4792831b00c4950d6c2b061def05fd67528fe132ececerion	}
4802831b00c4950d6c2b061def05fd67528fe132ececerion
481b51f0f4f33256638ed953156a2635aa739b232f1sewardj	for (i=0; i < argc; i++)
4829690d927540d730525a5f7f14663f3ceaa7818dasewardj		free(argv[i]);
4838f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj
4845c8a0cbfd7fd3b506f6ba1cb25a6aa20efb59dcbcerion	inst->pid = pid;
4855c8a0cbfd7fd3b506f6ba1cb25a6aa20efb59dcbcerion	inst->prog = string_copy(prog);
486f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion	inst->type = string_copy(type);
487f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion	inst->device = string_copy(device);
4888b1715b543b95a21be7f7aa27149cb3e4570cb61sewardj	inst->base_device = base_device(device);
4898b1715b543b95a21be7f7aa27149cb3e4570cb61sewardj	inst->start_time = time(0);
490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj	inst->next = NULL;
4918b1715b543b95a21be7f7aa27149cb3e4570cb61sewardj
4928b1715b543b95a21be7f7aa27149cb3e4570cb61sewardj	/*
493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj	 * Find the end of the list, so we add the instance on at the end.
4945c8a0cbfd7fd3b506f6ba1cb25a6aa20efb59dcbcerion	 */
4959690d927540d730525a5f7f14663f3ceaa7818dasewardj	for (p = instance_list; p && p->next; p = p->next);
4969690d927540d730525a5f7f14663f3ceaa7818dasewardj
4979690d927540d730525a5f7f14663f3ceaa7818dasewardj	if (p)
49889d4e9828ce36532c957566ebb46947109a7b53dsewardj		p->next = inst;
499343b9d0f6be20948ab2f4fe87de55835f96fe30asewardj	else
500343b9d0f6be20948ab2f4fe87de55835f96fe30asewardj		instance_list = inst;
501343b9d0f6be20948ab2f4fe87de55835f96fe30asewardj
502343b9d0f6be20948ab2f4fe87de55835f96fe30asewardj	return 0;
5032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
5042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
5052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*
5060033ddccac6f90789fe2e78e86b8a649931d77b4sewardj * Send a signal to all outstanding fsck child processes
5070033ddccac6f90789fe2e78e86b8a649931d77b4sewardj */
5080033ddccac6f90789fe2e78e86b8a649931d77b4sewardjstatic int kill_all(int signum)
5090033ddccac6f90789fe2e78e86b8a649931d77b4sewardj{
5100033ddccac6f90789fe2e78e86b8a649931d77b4sewardj	struct fsck_instance *inst;
5119690d927540d730525a5f7f14663f3ceaa7818dasewardj	int	n = 0;
5120033ddccac6f90789fe2e78e86b8a649931d77b4sewardj
5130033ddccac6f90789fe2e78e86b8a649931d77b4sewardj	for (inst = instance_list; inst; inst = inst->next) {
5140033ddccac6f90789fe2e78e86b8a649931d77b4sewardj		if (inst->flags & FLAG_DONE)
5150033ddccac6f90789fe2e78e86b8a649931d77b4sewardj			continue;
5160033ddccac6f90789fe2e78e86b8a649931d77b4sewardj		kill(inst->pid, signum);
5170033ddccac6f90789fe2e78e86b8a649931d77b4sewardj		n++;
5180033ddccac6f90789fe2e78e86b8a649931d77b4sewardj	}
519a238471814bd386aeb58a76718b41e68b1a794b2sewardj	return n;
5200033ddccac6f90789fe2e78e86b8a649931d77b4sewardj}
521b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj
522b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj/*
523b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj * Wait for one child process to exit; when it does, unlink it from
524b81f8b3e9110a5608094b8ec1a5c6d3c30a8e5aesewardj * the list of executing child processes, and return it.
5258c7f1abe9e022f6382634efea09c9cac89ec6336sewardj */
5268c7f1abe9e022f6382634efea09c9cac89ec6336sewardjstatic struct fsck_instance *wait_one(int flags)
5278c7f1abe9e022f6382634efea09c9cac89ec6336sewardj{
5288c7f1abe9e022f6382634efea09c9cac89ec6336sewardj	int	status;
5299690d927540d730525a5f7f14663f3ceaa7818dasewardj	int	sig;
5308c7f1abe9e022f6382634efea09c9cac89ec6336sewardj	struct fsck_instance *inst, *inst2, *prev;
5319690d927540d730525a5f7f14663f3ceaa7818dasewardj	pid_t	pid;
5329690d927540d730525a5f7f14663f3ceaa7818dasewardj
5339b96767debeeb1f78378f0e7e295fe6762c64002sewardj	if (!instance_list)
5349b96767debeeb1f78378f0e7e295fe6762c64002sewardj		return NULL;
5359b96767debeeb1f78378f0e7e295fe6762c64002sewardj
5369b96767debeeb1f78378f0e7e295fe6762c64002sewardj	if (noexecute) {
537cf780b4c356a274cc48a6829963f8bc79a1b34e8sewardj		inst = instance_list;
5386e797c5fbd90ecc6531f9d8c4929848664a13714sewardj		prev = 0;
53984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj#ifdef RANDOM_DEBUG
540291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj		while (inst->next && (random() & 1)) {
541291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj			prev = inst;
54284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj			inst = inst->next;
543291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj		}
544fd33277c458b31596eb4fb15959467ac047c75dasewardj#endif
5458eda6304ecfaa1d0aa70773a2c07f996717f8f54sewardj		inst->exit_status = 0;
546cf7879021370aabcccb1a9347244fcc7d5680141sewardj		goto ret_inst;
547b5874aa03bb38bf754aa8c1cb1e400f3d7e86b9fsewardj	}
5488f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj
549baf971ad7f6e005109f3301ec9d19c98066b3840sewardj	/*
5508f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	 * gcc -Wall fails saving throw against stupidity
551b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	 * (inst and prev are thought to be uninitialized variables)
552cfded9ab7c059881ecdbe967ddfcc1ce207986casewardj	 */
553b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	inst = prev = NULL;
554b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
555b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	do {
55652ace3ed99ccb7d0e4c64dc06381e407a8bfcf1dsewardj		pid = waitpid(-1, &status, flags);
5576c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		if (cancel_requested && !kill_sent) {
5586c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			kill_all(SIGTERM);
5596c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			kill_sent++;
560b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		}
561b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		if ((pid == 0) && (flags & WNOHANG))
562b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			return NULL;
563b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		if (pid < 0) {
56452ace3ed99ccb7d0e4c64dc06381e407a8bfcf1dsewardj			if ((errno == EINTR) || (errno == EAGAIN))
565b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj				continue;
566b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			if (errno == ECHILD) {
567b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj				fprintf(stderr,
5688f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj					_("%s: wait: No more child process?!?\n"),
5696c299f3acab617581ea504e45fbb6cab24c2b29fsewardj					progname);
5706c299f3acab617581ea504e45fbb6cab24c2b29fsewardj				return NULL;
5716c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			}
572b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			perror("wait");
573b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			continue;
5746d52228c83cccffb6cadf7f0cdfe34df057b6fefflorian		}
575baf971ad7f6e005109f3301ec9d19c98066b3840sewardj		for (prev = 0, inst = instance_list;
5766c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		     inst;
5776c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		     prev = inst, inst = inst->next) {
5786c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			if (inst->pid == pid)
5798f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj				break;
580883b00b3d97a9873371557d7b1f2ac5db7985e43sewardj		}
5818f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	} while (!inst);
5828f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj
583883b00b3d97a9873371557d7b1f2ac5db7985e43sewardj	if (WIFEXITED(status))
5848f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		status = WEXITSTATUS(status);
5858f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	else if (WIFSIGNALED(status)) {
5868f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		sig = WTERMSIG(status);
5876c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		if (sig == SIGINT) {
5888f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			status = EXIT_UNCORRECTED;
5892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		} else {
5902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj			printf(_("Warning... %s for device %s exited "
5918f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			       "with signal %d.\n"),
5923bca906f6e715c544eb49c278bedef093c14c0d7sewardj			       inst->prog, inst->device, sig);
593b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			status = EXIT_ERROR;
5946c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		}
5956c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	} else {
5966c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		printf(_("%s %s: status is %x, should never happen.\n"),
5976c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		       inst->prog, inst->device, status);
5988f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		status = EXIT_ERROR;
5998f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	}
6008f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	inst->exit_status = status;
6018f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	if (progress && (inst->flags & FLAG_PROGRESS) &&
6028f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj	    !progress_active()) {
6038f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		for (inst2 = instance_list; inst2; inst2 = inst2->next) {
6048f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			if (inst2->flags & FLAG_DONE)
6058f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj				continue;
6068f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			if (strcmp(inst2->type, "ext2") &&
6078f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			    strcmp(inst2->type, "ext3"))
6088f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj				continue;
6096c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			/*
6106c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			 * If we've just started the fsck, wait a tiny
6116c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			 * bit before sending the kill, to give it
6126c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			 * time to set up the signal handler
6136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			 */
6146c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			if (inst2->start_time < time(0)+2) {
6156c299f3acab617581ea504e45fbb6cab24c2b29fsewardj				if (fork() == 0) {
6166c299f3acab617581ea504e45fbb6cab24c2b29fsewardj					sleep(1);
6176c299f3acab617581ea504e45fbb6cab24c2b29fsewardj					kill(inst2->pid, SIGUSR1);
6188f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj					exit(0);
6198f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj				}
6208f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj			} else
6216c299f3acab617581ea504e45fbb6cab24c2b29fsewardj				kill(inst2->pid, SIGUSR1);
6226c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			inst2->flags |= FLAG_PROGRESS;
6236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj			break;
6246c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		}
6256c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	}
6266c299f3acab617581ea504e45fbb6cab24c2b29fsewardjret_inst:
6276c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	if (prev)
6286c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		prev->next = inst->next;
6293bca906f6e715c544eb49c278bedef093c14c0d7sewardj	else
6303bca906f6e715c544eb49c278bedef093c14c0d7sewardj		instance_list = inst->next;
6313bca906f6e715c544eb49c278bedef093c14c0d7sewardj	if (verbose > 1)
6328f3debf52b76a050bc84997a0358c4aa86dfc88dsewardj		printf(_("Finished with %s (exit status %d)\n"),
6336c299f3acab617581ea504e45fbb6cab24c2b29fsewardj		       inst->device, inst->exit_status);
6346c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	num_running--;
6356c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	return inst;
6364aa412af1d8166cc11f39a6e721df49431d23618sewardj}
6376c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
6386c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#define FLAG_WAIT_ALL		0
6396c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#define FLAG_WAIT_ATLEAST_ONE	1
6406c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*
6416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj * Wait until all executing child processes have exited; return the
64266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * logical OR of all of their exit code values.
64366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
64452ace3ed99ccb7d0e4c64dc06381e407a8bfcf1dsewardjstatic int wait_many(int flags)
6451c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian{
6466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj	struct fsck_instance *inst;
6473bca906f6e715c544eb49c278bedef093c14c0d7sewardj	int	global_status = 0;
6482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	int	wait_flags = 0;
6492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
6501c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian	while ((inst = wait_one(wait_flags))) {
6511c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian		global_status |= inst->exit_status;
6522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		free_instance(inst);
6532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#ifdef RANDOM_DEBUG
6542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		if (noexecute && (flags & WNOHANG) && !(random() % 3))
6552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj			break;
6566c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#endif
6573bca906f6e715c544eb49c278bedef093c14c0d7sewardj		if (flags & FLAG_WAIT_ATLEAST_ONE)
6583bca906f6e715c544eb49c278bedef093c14c0d7sewardj			wait_flags = WNOHANG;
6594cb918d355cef4e7640d374346852db4556f3524sewardj	}
66017442fe8094d0f82266e5a05509f62cac8f7539esewardj	return global_status;
66117442fe8094d0f82266e5a05509f62cac8f7539esewardj}
662c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
663fc1b541264539587f12721ca0b73ef04580ed2bdsewardj/*
664b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj * Run the fsck program on a particular device
6652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj *
6662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj * If the type is specified using -t, and it isn't prefixed with "no"
6672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj * (as in "noext2") and only one filesystem type is specified, then
6682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj * use that type regardless of what is specified in /etc/fstab.
6692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj *
6702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj * If the type isn't specified by the user, then use either the type
6712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj * specified in /etc/fstab, or DEFAULT_FSTYPE.
6722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj */
6732019a976f07ff418dde2dfc7cc74667ef66d7764sewardjstatic void fsck_device(struct fs_info *fs, int interactive)
6742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
6752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	const char *type;
6762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	int retval;
6772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
6782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	interpret_type(fs);
6792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
6802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (strcmp(fs->type, "auto") != 0)
6811c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian		type = fs->type;
6821c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian	else if (fstype && strncmp(fstype, "no", 2) &&
6832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	    strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
6842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	    !strchr(fstype, ','))
6852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		type = fstype;
6862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	else
6872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		type = DEFAULT_FSTYPE;
6881c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
6891c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian	num_running++;
6902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	retval = execute(type, fs->device, fs->mountpt, interactive);
6912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (retval) {
6922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		fprintf(stderr, _("%s: Error %d while executing fsck.%s "
693b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			"for %s\n"), progname, retval, type, fs->device);
694b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		num_running--;
695b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	}
696b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj}
697b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
698b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
699b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj/*
700b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj * Deal with the fsck -t argument.
701b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj */
702b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstruct fs_type_compile {
703b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	char **list;
704b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	int *type;
705b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	int  negate;
706b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj} fs_type_compiled;
707b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
708b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj#define FS_TYPE_NORMAL	0
709b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj#define FS_TYPE_OPT	1
710b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj#define FS_TYPE_NEGOPT	2
711b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
712b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic const char *fs_type_syntax_error =
713b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjN_("Either all or none of the filesystem types passed to -t must be prefixed\n"
714b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   "with 'no' or '!'.\n");
715b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
716b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
717d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj{
718d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj	char 	*cp, *list, *s;
719b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	int	num = 2;
7202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	int	negate, first_negate = 1;
7212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
7222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (fs_type) {
7232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		for (cp=fs_type; *cp; cp++) {
7245906a6b242b06c27fdc583d4547eab10b86a9800florian			if (*cp == ',')
7252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj				num++;
7262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		}
727b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	}
728b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
72940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	cmp->list = malloc(num * sizeof(char *));
73040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	cmp->type = malloc(num * sizeof(int));
7312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	if (!cmp->list || !cmp->type) {
7322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj		fprintf(stderr, _("Couldn't allocate memory for "
73340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj				  "filesystem types\n"));
73440c802659108a96bb87cbc1a30b7b77e2abd0829sewardj		exit(EXIT_ERROR);
73540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	}
73640c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	memset(cmp->list, 0, num * sizeof(char *));
73740c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	memset(cmp->type, 0, num * sizeof(int));
73840c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	cmp->negate = 0;
73940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
74040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj	if (!fs_type)
74140c802659108a96bb87cbc1a30b7b77e2abd0829sewardj		return;
742b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
7431ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj	list = string_copy(fs_type);
7440f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj	num = 0;
7450f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj	s = strtok(list, ",");
7460f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj	while(s) {
7470f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj		negate = 0;
748b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		if (strncmp(s, "no", 2) == 0) {
749b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			s += 2;
750b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			negate = 1;
751b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		} else if (*s == '!') {
752b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			s++;
753b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			negate = 1;
754b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		}
755b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj		if (strcmp(s, "loop") == 0)
756b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj			/* loop is really short-hand for opts=loop */
757e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			goto loop_special_case;
758e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj		else if (strncmp(s, "opts=", 5) == 0) {
75944ce46d5945ed83d96695d280510cc2a858894dcsewardj			s += 5;
76044ce46d5945ed83d96695d280510cc2a858894dcsewardj		loop_special_case:
76144ce46d5945ed83d96695d280510cc2a858894dcsewardj			cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
76244ce46d5945ed83d96695d280510cc2a858894dcsewardj		} else {
763e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			if (first_negate) {
764e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj				cmp->negate = negate;
765e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj				first_negate = 0;
766e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			}
767e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			if ((negate && !cmp->negate) ||
768e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			    (!negate && cmp->negate)) {
769e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj				fprintf(stderr, _(fs_type_syntax_error));
770e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj				exit(EXIT_USAGE);
771e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj			}
772e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj		}
773e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj#if 0
774e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj		printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
775e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj#endif
776e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj	        cmp->list[num++] = string_copy(s);
777e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj		s = strtok(NULL, ",");
778e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj	}
779e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj	free(list);
780e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj}
781e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj
782e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj/*
783e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj * This function returns true if a particular option appears in a
784e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj * comma-delimited options list
785310d6b2d02c3b22a8e496f3e26f3e9b3eb616ea5sewardj */
786310d6b2d02c3b22a8e496f3e26f3e9b3eb616ea5sewardjstatic int opt_in_list(char *opt, char *optlist)
787310d6b2d02c3b22a8e496f3e26f3e9b3eb616ea5sewardj{
788e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj	char	*list, *s;
789e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj
790e2ea17600e3bbdc4cc0edcd2a03f7d1142666f37sewardj	if (!optlist)
7912fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return 0;
7922fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	list = string_copy(optlist);
7932fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
7942fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	s = strtok(list, ",");
7952fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	while(s) {
7962fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		if (strcmp(s, opt) == 0) {
7972fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			free(list);
7982fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			return 1;
7992fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		}
8002fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		s = strtok(NULL, ",");
8012fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	}
8022fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj        free(list);
8032fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	return 0;
8042fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj}
8052fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8062fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj/* See if the filesystem matches the criteria given by the -t option */
8072fdd41628b79039a9586c7a601cc7ddcd376fccfsewardjstatic int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
8082fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj{
8092fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	int n, ret = 0, checked_type = 0;
8102fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	char *cp;
8112fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8122fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (cmp->list == 0 || cmp->list[0] == 0)
8132fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return 1;
8141ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj
8152fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	for (n=0; (cp = cmp->list[n]); n++) {
8162fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		switch (cmp->type[n]) {
8172fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		case FS_TYPE_NORMAL:
8182fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			checked_type++;
8191ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj			if (strcmp(cp, fs->type) == 0) {
8202fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				ret = 1;
8212fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			}
8222fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			break;
8231ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj		case FS_TYPE_NEGOPT:
8242fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			if (opt_in_list(cp, fs->opts))
8252fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				return 0;
8262fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			break;
8272fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		case FS_TYPE_OPT:
8281ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj			if (!opt_in_list(cp, fs->opts))
8292fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				return 0;
8302fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			break;
8312fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		}
8322fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	}
83338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	if (checked_type == 0)
83438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj		return 1;
83538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	return (cmp->negate ? !ret : ret);
8361806918ae2783af5808f00876581e01c7b650a0dsewardj}
83738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj
83838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj/* Check if we should ignore this filesystem. */
83938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardjstatic int ignore(struct fs_info *fs)
8402fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj{
8412fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	const char **ip;
8422fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	int wanted = 0;
8432fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8442fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/*
8452fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 * If the pass number is 0, ignore it.
8462fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 */
8472fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (fs->passno == 0)
8482fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return 1;
8492fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8502fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	interpret_type(fs);
8512fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8522fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/*
8532fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 * If a specific fstype is specified, and it doesn't match,
8542fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 * ignore it.
8552fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 */
8562fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (!fs_match(fs, &fs_type_compiled)) return 1;
8572fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
85838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	/* Are we ignoring this type? */
85938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	for(ip = ignored_types; *ip; ip++)
86038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj		if (strcmp(fs->type, *ip) == 0) return 1;
8612fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8622fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/* Do we really really want to check this fs? */
86338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	for(ip = really_wanted; *ip; ip++)
8642fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		if (strcmp(fs->type, *ip) == 0) {
8652fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			wanted = 1;
8662fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			break;
8672fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		}
8682fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8692fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/* See if the <fsck.fs> program is available. */
87038a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	if (find_fsck(fs->type) == NULL) {
87138a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj		if (wanted)
8722fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			fprintf(stderr, _("fsck: cannot check %s: fsck.%s not found\n"),
8732fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				fs->device, fs->type);
8742fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return 1;
8752fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	}
8762fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8772fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/* We can and want to check this file system type. */
8782fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	return 0;
8792fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj}
8802fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8812fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj/*
8822fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj * Returns TRUE if a partition on the same disk is already being
8832fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj * checked.
88438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj */
8855ce5fd60b7690ed8fdbaba9334d4d54929264da2sewardjstatic int device_already_active(char *device)
88638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj{
88738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	struct fsck_instance *inst;
88838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	char *base;
88938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj
8902fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (force_all_parallel)
8912fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return 0;
8922fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
8932fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj#ifdef BASE_MD
89438a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	/* Don't check a soft raid disk with any other disk */
89538a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	if (instance_list &&
89638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	    (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
8972fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
89838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj		return 1;
89938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj#endif
9002fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
9012fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	base = base_device(device);
9022fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	/*
903a8c7b0f2ac208ed08763d0873131962a65669d58sewardj	 * If we don't know the base device, assume that the device is
904a8c7b0f2ac208ed08763d0873131962a65669d58sewardj	 * already active if there are any fsck instances running.
9057deaf9552b546b847528cf39b38898fb7742b5f5carll	 */
9062fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (!base)
9072fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		return (instance_list != 0);
9082fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	for (inst = instance_list; inst; inst = inst->next) {
9092fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		if (!inst->base_device || !strcmp(base, inst->base_device)) {
9102fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			free(base);
9112fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			return 1;
9122fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		}
91338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	}
914d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj	free(base);
9152fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	return 0;
916d71ba837242cc470f622335b1c650bce8886a533sewardj}
91738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj
9182fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj/* Check all file systems, using the /etc/fstab table. */
9192fdd41628b79039a9586c7a601cc7ddcd376fccfsewardjstatic int check_all(NOARGS)
9202fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj{
9212fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	struct fs_info *fs = NULL;
9221dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj	int status = EXIT_OK;
9231dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj	int not_done_yet = 1;
9241dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj	int passno = 1;
9251dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj	int pass_done;
9261dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj
9271dd3ec1c8a8d28f1d81f42a599b390595466c805sewardj	if (verbose)
9282fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		printf(_("Checking all file systems.\n"));
9295f438dd73072211989c6d496845bdc9b777ecbecsewardj
9305f438dd73072211989c6d496845bdc9b777ecbecsewardj	/*
931c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 * Do an initial scan over the filesystem; mark filesystems
932c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 * which should be ignored as done, and resolve any "auto"
933c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 * filesystem types (done as a side-effect of calling ignore()).
934c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 */
935c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	for (fs = filesys_info; fs; fs = fs->next) {
936c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj		if (ignore(fs))
937c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj			fs->flags |= FLAG_DONE;
938c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	}
939c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj
940c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	/*
941c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 * Find and check the root filesystem.
942c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	 */
943c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj	if (!parallel_root) {
944c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj		for (fs = filesys_info; fs; fs = fs->next) {
945c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj			if (!strcmp(fs->mountpt, "/"))
946c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj				break;
947c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj		}
948c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj		if (fs) {
949c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj			if (!skip_root && !ignore(fs)) {
9505f438dd73072211989c6d496845bdc9b777ecbecsewardj				fsck_device(fs, 1);
9515f438dd73072211989c6d496845bdc9b777ecbecsewardj				status |= wait_many(FLAG_WAIT_ALL);
952ad2c9ea0c360fced134b2dd0d4b28c0be3639cfbsewardj				if (status > EXIT_NONDESTRUCT)
95338a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj					return status;
9542fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			}
9552fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			fs->flags |= FLAG_DONE;
95638a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj		}
95738a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	}
95838a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	/*
95938a3f868aebe4ade7279d7168e0efb6a98eaed5fsewardj	 * This is for the bone-headed user who enters the root
9602fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 * filesystem twice.  Skip root will skep all root entries.
9612fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	 */
9622fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	if (skip_root)
9632fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		for (fs = filesys_info; fs; fs = fs->next)
9642fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			if (!strcmp(fs->mountpt, "/"))
9652fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				fs->flags |= FLAG_DONE;
966d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj
967d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj	while (not_done_yet) {
968d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj		not_done_yet = 0;
969d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj		pass_done = 1;
9702fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj
9712fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		for (fs = filesys_info; fs; fs = fs->next) {
9722fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			if (cancel_requested)
9732fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				break;
9742fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			if (fs->flags & FLAG_DONE)
9752fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				continue;
9762fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			/*
9772fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			 * If the filesystem's pass number is higher
9782fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			 * than the current pass number, then we don't
9792fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			 * do it yet.
9802fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			 */
9812fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			if (fs->passno > passno) {
9822fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj				not_done_yet++;
983e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj				continue;
984e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj			}
985e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj			/*
986e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj			 * If a filesystem on a particular device has
987e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj			 * already been spawned, then we need to defer
988e6b9bd927408d9a7b0a95a9d930b387659f65218sewardj			 * this to another pass.
9892fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			 */
990336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			if (device_already_active(fs->device)) {
991336803528188cd4fe8b4fcfa7c48ca1056811046sewardj				pass_done = 0;
992336803528188cd4fe8b4fcfa7c48ca1056811046sewardj				continue;
9932fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			}
994336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			/*
995336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			 * Spawn off the fsck process
996336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			 */
997336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			fsck_device(fs, serialize);
998336803528188cd4fe8b4fcfa7c48ca1056811046sewardj			fs->flags |= FLAG_DONE;
999336803528188cd4fe8b4fcfa7c48ca1056811046sewardj
1000d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			/*
1001d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			 * Only do one filesystem at a time, or if we
1002d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			 * have a limit on the number of fsck's extant
1003d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			 * at one time, apply that limit.
1004d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			 */
1005d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			if (serialize ||
1006d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj			    (max_running && (num_running >= max_running))) {
1007d166e2874e0d9a9e567a281d7f1f6e8ef8127196sewardj				pass_done = 0;
1008e13074c2c1321d069fb95806bdce64f9a3512341sewardj				break;
1009e13074c2c1321d069fb95806bdce64f9a3512341sewardj			}
1010e13074c2c1321d069fb95806bdce64f9a3512341sewardj		}
1011e13074c2c1321d069fb95806bdce64f9a3512341sewardj		if (cancel_requested)
10122fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj			break;
10131ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj		if (verbose > 1)
10141ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj			printf(_("--waiting-- (pass %d)\n"), passno);
10152fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj		status |= wait_many(pass_done ? FLAG_WAIT_ALL :
1016c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj				    FLAG_WAIT_ATLEAST_ONE);
1017c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		if (pass_done) {
1018c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj			if (verbose > 1)
1019c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj				printf("----------------------------------\n");
102079e5a4845df6d09250b142c4e160a95cf7688fc8florian			passno++;
1021c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		} else
1022c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj			not_done_yet++;
1023c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	}
1024c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	if (cancel_requested && !kill_sent) {
1025c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		kill_all(SIGTERM);
102679e5a4845df6d09250b142c4e160a95cf7688fc8florian		kill_sent++;
1027c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	}
1028c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
1029c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	return status;
103026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
103126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
103226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic void usage(NOARGS)
103326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj{
103426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	fprintf(stderr,
103526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj		_("Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] [filesys ...]\n"));
1036cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	exit(EXIT_USAGE);
1037cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
103826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
103926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj#ifdef HAVE_SIGNAL_H
104026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic void signal_cancel(int sig)
104126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj{
104226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	cancel_requested++;
104326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
104426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj#endif
104526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
104626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic void PRS(int argc, char *argv[])
104726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj{
104826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	int	i, j;
104926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	char	*arg, *dev, *tmp = 0;
105026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	char	options[128];
105126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	int	opt = 0;
1052b17e16fb3709b8282646009caffa2ead7bcf363fflorian	int     opts_for_fsck = 0;
1053b17e16fb3709b8282646009caffa2ead7bcf363fflorian#ifdef HAVE_SIGNAL_H
1054b17e16fb3709b8282646009caffa2ead7bcf363fflorian	struct sigaction	sa;
1055b17e16fb3709b8282646009caffa2ead7bcf363fflorian
1056b17e16fb3709b8282646009caffa2ead7bcf363fflorian	/*
1057b17e16fb3709b8282646009caffa2ead7bcf363fflorian	 * Set up signal action
105826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	 */
105926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	memset(&sa, 0, sizeof(struct sigaction));
106026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	sa.sa_handler = signal_cancel;
1061b17e16fb3709b8282646009caffa2ead7bcf363fflorian	sigaction(SIGINT, &sa, 0);
1062b17e16fb3709b8282646009caffa2ead7bcf363fflorian	sigaction(SIGTERM, &sa, 0);
1063b17e16fb3709b8282646009caffa2ead7bcf363fflorian#endif
106479e5a4845df6d09250b142c4e160a95cf7688fc8florian
106526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	num_devices = 0;
106626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	num_args = 0;
106779e5a4845df6d09250b142c4e160a95cf7688fc8florian	instance_list = 0;
106826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
106926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj	progname = argv[0];
1070b17e16fb3709b8282646009caffa2ead7bcf363fflorian
1071b17e16fb3709b8282646009caffa2ead7bcf363fflorian	for (i=1; i < argc; i++) {
1072b17e16fb3709b8282646009caffa2ead7bcf363fflorian		arg = argv[i];
1073b17e16fb3709b8282646009caffa2ead7bcf363fflorian		if (!arg)
1074b17e16fb3709b8282646009caffa2ead7bcf363fflorian			continue;
1075b17e16fb3709b8282646009caffa2ead7bcf363fflorian		if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
107679e5a4845df6d09250b142c4e160a95cf7688fc8florian			if (num_devices >= MAX_DEVICES) {
107726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj				fprintf(stderr, _("%s: too many devices\n"),
107826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj					progname);
107979e5a4845df6d09250b142c4e160a95cf7688fc8florian				exit(EXIT_ERROR);
1080b17e16fb3709b8282646009caffa2ead7bcf363fflorian			}
1081b17e16fb3709b8282646009caffa2ead7bcf363fflorian			dev = blkid_get_devname(cache, arg, NULL);
108279e5a4845df6d09250b142c4e160a95cf7688fc8florian			if (!dev && strchr(arg, '=')) {
1083b17e16fb3709b8282646009caffa2ead7bcf363fflorian				/*
1084b17e16fb3709b8282646009caffa2ead7bcf363fflorian				 * Check to see if we failed because
108579e5a4845df6d09250b142c4e160a95cf7688fc8florian				 * /proc/partitions isn't found.
1086b17e16fb3709b8282646009caffa2ead7bcf363fflorian				 */
1087b17e16fb3709b8282646009caffa2ead7bcf363fflorian				if (access("/proc/partitions", R_OK) < 0) {
108879e5a4845df6d09250b142c4e160a95cf7688fc8florian					fprintf(stderr, "Couldn't open /proc/partitions: %s\n",
108926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj						strerror(errno));
109026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj					fprintf(stderr, "Is /proc mounted?\n");
109179e5a4845df6d09250b142c4e160a95cf7688fc8florian					exit(EXIT_ERROR);
1092b17e16fb3709b8282646009caffa2ead7bcf363fflorian				}
1093b17e16fb3709b8282646009caffa2ead7bcf363fflorian				/*
109479e5a4845df6d09250b142c4e160a95cf7688fc8florian				 * Check to see if this is because
1095b17e16fb3709b8282646009caffa2ead7bcf363fflorian				 * we're not running as root
1096b17e16fb3709b8282646009caffa2ead7bcf363fflorian				 */
109779e5a4845df6d09250b142c4e160a95cf7688fc8florian				if (geteuid())
1098b17e16fb3709b8282646009caffa2ead7bcf363fflorian					fprintf(stderr,
1099b17e16fb3709b8282646009caffa2ead7bcf363fflorian		"Must be root to scan for matching filesystems: %s\n", arg);
110079e5a4845df6d09250b142c4e160a95cf7688fc8florian				else
110126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj					fprintf(stderr,
110226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj		"Couldn't find matching filesystem: %s\n", arg);
110379e5a4845df6d09250b142c4e160a95cf7688fc8florian				exit(EXIT_ERROR);
1104b17e16fb3709b8282646009caffa2ead7bcf363fflorian			}
1105b17e16fb3709b8282646009caffa2ead7bcf363fflorian			devices[num_devices++] = dev ? dev : string_copy(arg);
1106b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			continue;
1107b22838d88488f42a46a6d01f5df441c391fb3bbaflorian		}
1108b22838d88488f42a46a6d01f5df441c391fb3bbaflorian		if (arg[0] != '-' || opts_for_fsck) {
1109b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			if (num_args >= MAX_ARGS) {
1110b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				fprintf(stderr, _("%s: too many arguments\n"),
1111b22838d88488f42a46a6d01f5df441c391fb3bbaflorian					progname);
1112b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				exit(EXIT_ERROR);
1113b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			}
1114b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			args[num_args++] = string_copy(arg);
1115b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			continue;
1116b22838d88488f42a46a6d01f5df441c391fb3bbaflorian		}
1117b22838d88488f42a46a6d01f5df441c391fb3bbaflorian		for (j=1; arg[j]; j++) {
111879e5a4845df6d09250b142c4e160a95cf7688fc8florian			if (opts_for_fsck) {
111937c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian				options[++opt] = arg[j];
112037c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian				continue;
112179e5a4845df6d09250b142c4e160a95cf7688fc8florian			}
112237c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian			switch (arg[j]) {
112337c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian			case 'A':
1124b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				doall++;
1125b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1126b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 'C':
1127b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				progress++;
1128b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
112937c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian			case 'V':
113079e5a4845df6d09250b142c4e160a95cf7688fc8florian				verbose++;
113137c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian				break;
113237c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian			case 'N':
1133b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				noexecute++;
1134b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1135b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 'R':
1136b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				skip_root++;
1137b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1138b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 'T':
1139b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				notitle++;
1140b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1141b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 'M':
1142b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				like_mount++;
1143b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1144b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 'P':
1145b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				parallel_root++;
1146b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1147b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 's':
1148b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				serialize++;
1149b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				break;
1150b22838d88488f42a46a6d01f5df441c391fb3bbaflorian			case 't':
1151b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				if (fstype)
1152b22838d88488f42a46a6d01f5df441c391fb3bbaflorian					usage();
1153b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				if (arg[j+1])
1154b22838d88488f42a46a6d01f5df441c391fb3bbaflorian					tmp = arg+j+1;
1155b22838d88488f42a46a6d01f5df441c391fb3bbaflorian				else if ((i+1) < argc)
1156b22838d88488f42a46a6d01f5df441c391fb3bbaflorian					tmp = argv[++i];
115779e5a4845df6d09250b142c4e160a95cf7688fc8florian				else
115837c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian					usage();
115937c57f396b7a6dc1fc3a7e59e85bbf7eac627a88florian				fstype = string_copy(tmp);
1160cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				compile_fs_type(fstype, &fs_type_compiled);
1161cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				goto next_arg;
1162cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll			case '-':
1163cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll				opts_for_fsck++;
1164cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				break;
1165cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			case '?':
1166cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				usage();
1167cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				break;
1168cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			default:
1169cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				options[++opt] = arg[j];
1170cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				break;
1171cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			}
1172cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		}
1173cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	next_arg:
1174daa4084cffd771efef294a484e64868f3eeeb0e4florian		if (opt) {
1175cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			options[0] = '-';
1176cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			options[++opt] = '\0';
117720c6bca02d9b3c985607b4639ffc70eb504cc237florian			if (num_args >= MAX_ARGS) {
117820c6bca02d9b3c985607b4639ffc70eb504cc237florian				fprintf(stderr,
117920c6bca02d9b3c985607b4639ffc70eb504cc237florian					_("%s: too many arguments\n"),
118020c6bca02d9b3c985607b4639ffc70eb504cc237florian					progname);
118120c6bca02d9b3c985607b4639ffc70eb504cc237florian				exit(EXIT_ERROR);
118220c6bca02d9b3c985607b4639ffc70eb504cc237florian			}
118320c6bca02d9b3c985607b4639ffc70eb504cc237florian			args[num_args++] = string_copy(options);
1184cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj			opt = 0;
1185cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		}
1186cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	}
1187cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1188cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		force_all_parallel++;
1189cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if ((tmp = getenv("FSCK_MAX_INST")))
1190cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	    max_running = atoi(tmp);
1191cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
119279e5a4845df6d09250b142c4e160a95cf7688fc8florian
1193cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjint main(int argc, char *argv[])
1194cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj{
119579e5a4845df6d09250b142c4e160a95cf7688fc8florian	int i, status = 0;
1196cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	int interactive = 0;
1197cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	char *oldpath = getenv("PATH");
119879e5a4845df6d09250b142c4e160a95cf7688fc8florian	const char *fstab;
1199cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	struct fs_info *fs;
1200cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1201cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	setvbuf(stdout, NULL, _IONBF, BUFSIZ);
1202cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	setvbuf(stderr, NULL, _IONBF, BUFSIZ);
1203cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1204cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj#ifdef ENABLE_NLS
120579e5a4845df6d09250b142c4e160a95cf7688fc8florian	setlocale(LC_MESSAGES, "");
1206cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	setlocale(LC_CTYPE, "");
1207cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
1208cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	textdomain(NLS_CAT_NAME);
1209cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj#endif
1210cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	blkid_get_cache(&cache, NULL);
1211cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	PRS(argc, argv);
1212cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1213cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if (!notitle)
1214cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
1215cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1216cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	fstab = getenv("FSTAB_FILE");
1217cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if (!fstab)
12184bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian		fstab = _PATH_MNTTAB;
12194bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian	load_fs_info(fstab);
12204bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian
12214bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian	/* Update our search path to include uncommon directories. */
12224bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian	if (oldpath) {
12234bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian		fsck_path = malloc (strlen (fsck_prefix_path) + 1 +
12244bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian				    strlen (oldpath) + 1);
12254bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian		strcpy (fsck_path, fsck_prefix_path);
12264bbd3ecf31fdd592d2114e148821ea8150e77e4aflorian		strcat (fsck_path, ":");
1227cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll		strcat (fsck_path, oldpath);
1228cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	} else {
1229cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		fsck_path = string_copy(fsck_prefix_path);
1230cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	}
1231cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1232cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if ((num_devices == 1) || (serialize))
1233cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		interactive = 1;
1234cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1235cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll	/* If -A was specified ("check all"), do that! */
1236cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj	if (doall)
1237cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		return check_all();
1238c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1239c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj	if (num_devices == 0) {
1240c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		serialize++;
12414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj		interactive++;
12424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj		return check_all();
12434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj	}
12444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj	for (i = 0 ; i < num_devices; i++) {
12454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj		if (cancel_requested) {
12464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj			if (!kill_sent) {
12474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj				kill_all(SIGTERM);
12484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj				kill_sent++;
12494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj			}
12504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj			break;
12517deaf9552b546b847528cf39b38898fb7742b5f5carll		}
12527deaf9552b546b847528cf39b38898fb7742b5f5carll		fs = lookup(devices[i]);
12539571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj		if (!fs) {
12549571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj			fs = create_fs_device(devices[i], 0, "auto",
12557deaf9552b546b847528cf39b38898fb7742b5f5carll					      0, -1, -1);
12567deaf9552b546b847528cf39b38898fb7742b5f5carll			if (!fs)
1257cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj				continue;
1258cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		}
1259cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj		fsck_device(fs, interactive);
12605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj		if (serialize ||
12615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj		    (max_running && (num_running >= max_running))) {
12625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj			struct fsck_instance *inst;
1263164f9275c465cd09ecd09276b8542282f5def250sewardj
1264c9a43665879a03886b27a65b68af2a2c11b04f59sewardj			inst = wait_one(0);
1265c9a43665879a03886b27a65b68af2a2c11b04f59sewardj			if (inst) {
1266c9a43665879a03886b27a65b68af2a2c11b04f59sewardj				status |= inst->exit_status;
12679571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj				free_instance(inst);
1268c9a43665879a03886b27a65b68af2a2c11b04f59sewardj			}
12699571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj			if (verbose > 1)
12709571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj				printf("----------------------------------\n");
1271c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		}
12722fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	}
12732fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	status |= wait_many(FLAG_WAIT_ALL);
1274f294eb389e8e703e2d4476aea7ca579a160a0a89cerion	free(fsck_path);
12752fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj	blkid_put_cache(cache);
1276206c36410bd92f385b972e36a3a40e38675294e2cerion	return status;
1277c9a43665879a03886b27a65b68af2a2c11b04f59sewardj}
12782fdd41628b79039a9586c7a601cc7ddcd376fccfsewardj