xref: /freebsd/sbin/fsck/preen.c (revision 32ff2662d1b3fb19665d77d35c81fb637436fe3f)
19a317438SAdrian Chadd /*	$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $	*/
29a317438SAdrian Chadd 
39a317438SAdrian Chadd /*
49a317438SAdrian Chadd  * Copyright (c) 1990, 1993
59a317438SAdrian Chadd  *	The Regents of the University of California.  All rights reserved.
69a317438SAdrian Chadd  *
79a317438SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
89a317438SAdrian Chadd  * modification, are permitted provided that the following conditions
99a317438SAdrian Chadd  * are met:
109a317438SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
119a317438SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
129a317438SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
139a317438SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
149a317438SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
159a317438SAdrian Chadd  * 3. All advertising materials mentioning features or use of this software
169a317438SAdrian Chadd  *    must display the following acknowledgement:
179a317438SAdrian Chadd  *	This product includes software developed by the University of
189a317438SAdrian Chadd  *	California, Berkeley and its contributors.
199a317438SAdrian Chadd  * 4. Neither the name of the University nor the names of its contributors
209a317438SAdrian Chadd  *    may be used to endorse or promote products derived from this software
219a317438SAdrian Chadd  *    without specific prior written permission.
229a317438SAdrian Chadd  *
239a317438SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
249a317438SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
259a317438SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
269a317438SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
279a317438SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
289a317438SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
299a317438SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
309a317438SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
319a317438SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
329a317438SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
339a317438SAdrian Chadd  * SUCH DAMAGE.
349a317438SAdrian Chadd  *
359a317438SAdrian Chadd  * $FreeBSD$
369a317438SAdrian Chadd  */
379a317438SAdrian Chadd 
389a317438SAdrian Chadd #include <sys/cdefs.h>
399a317438SAdrian Chadd #ifndef lint
409a317438SAdrian Chadd #if 0
419a317438SAdrian Chadd static char sccsid[] = "@(#)preen.c	8.5 (Berkeley) 4/28/95";
429a317438SAdrian Chadd #else
439a317438SAdrian Chadd __RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $");
449a317438SAdrian Chadd #endif
459a317438SAdrian Chadd #endif /* not lint */
469a317438SAdrian Chadd 
479a317438SAdrian Chadd #include <sys/param.h>
489a317438SAdrian Chadd #include <sys/stat.h>
499a317438SAdrian Chadd #include <sys/wait.h>
509a317438SAdrian Chadd #include <sys/queue.h>
519a317438SAdrian Chadd 
529a317438SAdrian Chadd #include <err.h>
539a317438SAdrian Chadd #include <ctype.h>
549a317438SAdrian Chadd #include <fstab.h>
559a317438SAdrian Chadd #include <string.h>
569a317438SAdrian Chadd #include <stdio.h>
579a317438SAdrian Chadd #include <stdlib.h>
589a317438SAdrian Chadd #include <unistd.h>
599a317438SAdrian Chadd 
609a317438SAdrian Chadd #include "fsutil.h"
619a317438SAdrian Chadd 
629a317438SAdrian Chadd struct partentry {
639a317438SAdrian Chadd 	TAILQ_ENTRY(partentry)	 p_entries;
649a317438SAdrian Chadd 	char		  	*p_devname;	/* device name */
659a317438SAdrian Chadd 	char			*p_mntpt;	/* mount point */
669a317438SAdrian Chadd 	char		  	*p_type;	/* filesystem type */
679a317438SAdrian Chadd 	void			*p_auxarg;	/* auxiliary argument */
689a317438SAdrian Chadd };
699a317438SAdrian Chadd 
709a317438SAdrian Chadd TAILQ_HEAD(part, partentry) badh;
719a317438SAdrian Chadd 
729a317438SAdrian Chadd struct diskentry {
739a317438SAdrian Chadd 	TAILQ_ENTRY(diskentry) 	    d_entries;
749a317438SAdrian Chadd 	char		       	   *d_name;	/* disk base name */
759a317438SAdrian Chadd 	TAILQ_HEAD(prt, partentry)  d_part;	/* list of partitions on disk */
769a317438SAdrian Chadd 	int			    d_pid;	/* 0 or pid of fsck proc */
779a317438SAdrian Chadd };
789a317438SAdrian Chadd 
799a317438SAdrian Chadd TAILQ_HEAD(disk, diskentry) diskh;
809a317438SAdrian Chadd 
819a317438SAdrian Chadd static int nrun = 0, ndisks = 0;
829a317438SAdrian Chadd 
839a317438SAdrian Chadd static struct diskentry *finddisk __P((const char *));
849a317438SAdrian Chadd static void addpart __P((const char *, const char *, const char *, void *));
859a317438SAdrian Chadd static int startdisk __P((struct diskentry *,
869a317438SAdrian Chadd     int (*)(const char *, const char *, const char *, void *, pid_t *)));
879a317438SAdrian Chadd static void printpart __P((void));
889a317438SAdrian Chadd 
899a317438SAdrian Chadd int
909a317438SAdrian Chadd checkfstab(flags, maxrun, docheck, checkit)
919a317438SAdrian Chadd 	int flags, maxrun;
929a317438SAdrian Chadd 	void *(*docheck) __P((struct fstab *));
939a317438SAdrian Chadd 	int (*checkit) __P((const char *, const char *, const char *, void *,
949a317438SAdrian Chadd 	    pid_t *));
959a317438SAdrian Chadd {
969a317438SAdrian Chadd 	struct fstab *fs;
979a317438SAdrian Chadd 	struct diskentry *d, *nextdisk;
989a317438SAdrian Chadd 	struct partentry *p;
999a317438SAdrian Chadd 	int ret, pid, retcode, passno, sumstatus, status;
1009a317438SAdrian Chadd 	void *auxarg;
1019a317438SAdrian Chadd 	const char *name;
1029a317438SAdrian Chadd 
1039a317438SAdrian Chadd 	TAILQ_INIT(&badh);
1049a317438SAdrian Chadd 	TAILQ_INIT(&diskh);
1059a317438SAdrian Chadd 
1069a317438SAdrian Chadd 	sumstatus = 0;
1079a317438SAdrian Chadd 
1089a317438SAdrian Chadd 	for (passno = 1; passno <= 2; passno++) {
1099a317438SAdrian Chadd 		if (setfsent() == 0) {
1109a317438SAdrian Chadd 			warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
1119a317438SAdrian Chadd 			return (8);
1129a317438SAdrian Chadd 		}
1139a317438SAdrian Chadd 		while ((fs = getfsent()) != 0) {
1149a317438SAdrian Chadd 			if ((auxarg = (*docheck)(fs)) == NULL)
1159a317438SAdrian Chadd 				continue;
1169a317438SAdrian Chadd 
1179a317438SAdrian Chadd 			/* XXX We don't need to search for blockdevs .. */
1189a317438SAdrian Chadd 			/* name = blockcheck(fs->fs_spec); */
1199a317438SAdrian Chadd 			name = fs->fs_spec;
1209a317438SAdrian Chadd 			if (flags & CHECK_DEBUG)
1219a317438SAdrian Chadd 				printf("pass %d, name %s\n", passno, name);
1229a317438SAdrian Chadd 
1239a317438SAdrian Chadd 			if ((flags & CHECK_PREEN) == 0 ||
1249a317438SAdrian Chadd 			    (passno == 1 && fs->fs_passno == 1)) {
1259a317438SAdrian Chadd 				if (name == NULL) {
1269a317438SAdrian Chadd 					if (flags & CHECK_PREEN)
1279a317438SAdrian Chadd 						return 8;
1289a317438SAdrian Chadd 					else
1299a317438SAdrian Chadd 						continue;
1309a317438SAdrian Chadd 				}
1319a317438SAdrian Chadd 				sumstatus = (*checkit)(fs->fs_vfstype,
1329a317438SAdrian Chadd 				    name, fs->fs_file, auxarg, NULL);
1339a317438SAdrian Chadd 
1349a317438SAdrian Chadd 				if (sumstatus)
1359a317438SAdrian Chadd 					return (sumstatus);
1369a317438SAdrian Chadd 			} else if (passno == 2 && fs->fs_passno > 1) {
1379a317438SAdrian Chadd 				if (name == NULL) {
1389a317438SAdrian Chadd 					(void) fprintf(stderr,
1399a317438SAdrian Chadd 					    "BAD DISK NAME %s\n", fs->fs_spec);
1409a317438SAdrian Chadd 					sumstatus |= 8;
1419a317438SAdrian Chadd 					continue;
1429a317438SAdrian Chadd 				}
1439a317438SAdrian Chadd 				addpart(fs->fs_vfstype, name, fs->fs_file,
1449a317438SAdrian Chadd 				    auxarg);
1459a317438SAdrian Chadd 			}
1469a317438SAdrian Chadd 		}
1479a317438SAdrian Chadd 		if ((flags & CHECK_PREEN) == 0)
1489a317438SAdrian Chadd 			return 0;
1499a317438SAdrian Chadd 	}
1509a317438SAdrian Chadd 
1519a317438SAdrian Chadd 	if (flags & CHECK_DEBUG)
1529a317438SAdrian Chadd 		printpart();
1539a317438SAdrian Chadd 
1549a317438SAdrian Chadd 	if (flags & CHECK_PREEN) {
1559a317438SAdrian Chadd 		if (maxrun == 0)
1569a317438SAdrian Chadd 			maxrun = ndisks;
1579a317438SAdrian Chadd 		if (maxrun > ndisks)
1589a317438SAdrian Chadd 			maxrun = ndisks;
159dab777beSPoul-Henning Kamp 		nextdisk = TAILQ_FIRST(&diskh);
1609a317438SAdrian Chadd 		for (passno = 0; passno < maxrun; ++passno) {
1619a317438SAdrian Chadd 			if ((ret = startdisk(nextdisk, checkit)) != 0)
1629a317438SAdrian Chadd 				return ret;
163dab777beSPoul-Henning Kamp 			nextdisk = TAILQ_NEXT(nextdisk, d_entries);
1649a317438SAdrian Chadd 		}
1659a317438SAdrian Chadd 
1669a317438SAdrian Chadd 		while ((pid = wait(&status)) != -1) {
167dab777beSPoul-Henning Kamp 			TAILQ_FOREACH(d, &diskh, d_entries)
1689a317438SAdrian Chadd 				if (d->d_pid == pid)
1699a317438SAdrian Chadd 					break;
1709a317438SAdrian Chadd 
1719a317438SAdrian Chadd 			if (d == NULL) {
1729a317438SAdrian Chadd 				warnx("Unknown pid %d\n", pid);
1739a317438SAdrian Chadd 				continue;
1749a317438SAdrian Chadd 			}
1759a317438SAdrian Chadd 
1769a317438SAdrian Chadd 
1779a317438SAdrian Chadd 			if (WIFEXITED(status))
1789a317438SAdrian Chadd 				retcode = WEXITSTATUS(status);
1799a317438SAdrian Chadd 			else
1809a317438SAdrian Chadd 				retcode = 0;
1819a317438SAdrian Chadd 
182dab777beSPoul-Henning Kamp 			p = TAILQ_FIRST(&d->d_part);
1839a317438SAdrian Chadd 
1849a317438SAdrian Chadd 			if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
1859a317438SAdrian Chadd 				(void) printf("done %s: %s (%s) = 0x%x\n",
1869a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1879a317438SAdrian Chadd 				    status);
1889a317438SAdrian Chadd 
1899a317438SAdrian Chadd 			if (WIFSIGNALED(status)) {
1909a317438SAdrian Chadd 				(void) fprintf(stderr,
1919a317438SAdrian Chadd 				    "%s: %s (%s): EXITED WITH SIGNAL %d\n",
1929a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1939a317438SAdrian Chadd 				    WTERMSIG(status));
1949a317438SAdrian Chadd 				retcode = 8;
1959a317438SAdrian Chadd 			}
1969a317438SAdrian Chadd 
1979a317438SAdrian Chadd 			TAILQ_REMOVE(&d->d_part, p, p_entries);
1989a317438SAdrian Chadd 
1999a317438SAdrian Chadd 			if (retcode != 0) {
2009a317438SAdrian Chadd 				TAILQ_INSERT_TAIL(&badh, p, p_entries);
2019a317438SAdrian Chadd 				sumstatus |= retcode;
2029a317438SAdrian Chadd 			} else {
2039a317438SAdrian Chadd 				free(p->p_type);
2049a317438SAdrian Chadd 				free(p->p_devname);
2059a317438SAdrian Chadd 				free(p);
2069a317438SAdrian Chadd 			}
2079a317438SAdrian Chadd 			d->d_pid = 0;
2089a317438SAdrian Chadd 			nrun--;
2099a317438SAdrian Chadd 
210dab777beSPoul-Henning Kamp 			if (TAILQ_EMPTY(&d->d_part))
2119a317438SAdrian Chadd 				ndisks--;
2129a317438SAdrian Chadd 
2139a317438SAdrian Chadd 			if (nextdisk == NULL) {
214dab777beSPoul-Henning Kamp 				if (!TAILQ_EMPTY(&d->d_part)) {
2159a317438SAdrian Chadd 					if ((ret = startdisk(d, checkit)) != 0)
2169a317438SAdrian Chadd 						return ret;
2179a317438SAdrian Chadd 				}
2189a317438SAdrian Chadd 			} else if (nrun < maxrun && nrun < ndisks) {
2199a317438SAdrian Chadd 				for ( ;; ) {
220dab777beSPoul-Henning Kamp 					nextdisk = TAILQ_NEXT(nextdisk, d_entries);
2219a317438SAdrian Chadd 					if (nextdisk == NULL)
222dab777beSPoul-Henning Kamp 						nextdisk = TAILQ_FIRST(&diskh);
223dab777beSPoul-Henning Kamp 					if (!TAILQ_EMPTY(&nextdisk->d_part)
2249a317438SAdrian Chadd 					    && nextdisk->d_pid == 0)
2259a317438SAdrian Chadd 						break;
2269a317438SAdrian Chadd 				}
2279a317438SAdrian Chadd 				if ((ret = startdisk(nextdisk, checkit)) != 0)
2289a317438SAdrian Chadd 					return ret;
2299a317438SAdrian Chadd 			}
2309a317438SAdrian Chadd 		}
2319a317438SAdrian Chadd 	}
2329a317438SAdrian Chadd 	if (sumstatus) {
23332ff2662SPoul-Henning Kamp 		p = TAILQ_FIRST(&badh);
2349a317438SAdrian Chadd 		if (p == NULL)
2359a317438SAdrian Chadd 			return (sumstatus);
2369a317438SAdrian Chadd 
2379a317438SAdrian Chadd 		(void) fprintf(stderr,
2389a317438SAdrian Chadd 			"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
239dab777beSPoul-Henning Kamp 			TAILQ_NEXT(p, p_entries) ? "S" : "",
2409a317438SAdrian Chadd 			"UNEXPECTED INCONSISTENCY:");
2419a317438SAdrian Chadd 
242dab777beSPoul-Henning Kamp 		for (; p; p = TAILQ_NEXT(p, p_entries))
2439a317438SAdrian Chadd 			(void) fprintf(stderr,
2449a317438SAdrian Chadd 			    "%s: %s (%s)%s", p->p_type, p->p_devname,
245dab777beSPoul-Henning Kamp 			    p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2469a317438SAdrian Chadd 
2479a317438SAdrian Chadd 		return sumstatus;
2489a317438SAdrian Chadd 	}
2499a317438SAdrian Chadd 	(void) endfsent();
2509a317438SAdrian Chadd 	return (0);
2519a317438SAdrian Chadd }
2529a317438SAdrian Chadd 
2539a317438SAdrian Chadd 
2549a317438SAdrian Chadd static struct diskentry *
2559a317438SAdrian Chadd finddisk(name)
2569a317438SAdrian Chadd 	const char *name;
2579a317438SAdrian Chadd {
2589a317438SAdrian Chadd 	const char *p;
2599a317438SAdrian Chadd 	size_t len = 0;
2609a317438SAdrian Chadd 	struct diskentry *d;
2619a317438SAdrian Chadd 
26228b66787SPoul-Henning Kamp 	p = strrchr(name, '/');
26328b66787SPoul-Henning Kamp 	if (p == NULL)
26428b66787SPoul-Henning Kamp 		p = name;
26528b66787SPoul-Henning Kamp 	else
26628b66787SPoul-Henning Kamp 		p++;
26728b66787SPoul-Henning Kamp 	for (; *p && !isdigit(*p); p++)
26828b66787SPoul-Henning Kamp 		continue;
26928b66787SPoul-Henning Kamp 	for (; *p && isdigit(*p); p++)
27028b66787SPoul-Henning Kamp 		continue;
27128b66787SPoul-Henning Kamp 	len = p - name;
27228b66787SPoul-Henning Kamp 	if (len == 0)
2739a317438SAdrian Chadd 		len = strlen(name);
2749a317438SAdrian Chadd 
275dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries)
2769a317438SAdrian Chadd 		if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2779a317438SAdrian Chadd 			return d;
2789a317438SAdrian Chadd 
2799a317438SAdrian Chadd 	d = emalloc(sizeof(*d));
2809a317438SAdrian Chadd 	d->d_name = estrdup(name);
2819a317438SAdrian Chadd 	d->d_name[len] = '\0';
2829a317438SAdrian Chadd 	TAILQ_INIT(&d->d_part);
2839a317438SAdrian Chadd 	d->d_pid = 0;
2849a317438SAdrian Chadd 
2859a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2869a317438SAdrian Chadd 	ndisks++;
2879a317438SAdrian Chadd 
2889a317438SAdrian Chadd 	return d;
2899a317438SAdrian Chadd }
2909a317438SAdrian Chadd 
2919a317438SAdrian Chadd 
2929a317438SAdrian Chadd static void
2939a317438SAdrian Chadd printpart()
2949a317438SAdrian Chadd {
2959a317438SAdrian Chadd 	struct diskentry *d;
2969a317438SAdrian Chadd 	struct partentry *p;
2979a317438SAdrian Chadd 
298dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries) {
2999a317438SAdrian Chadd 		(void) printf("disk %s: ", d->d_name);
300dab777beSPoul-Henning Kamp 		TAILQ_FOREACH(p, &d->d_part, p_entries)
3019a317438SAdrian Chadd 			(void) printf("%s ", p->p_devname);
3029a317438SAdrian Chadd 		(void) printf("\n");
3039a317438SAdrian Chadd 	}
3049a317438SAdrian Chadd }
3059a317438SAdrian Chadd 
3069a317438SAdrian Chadd 
3079a317438SAdrian Chadd static void
3089a317438SAdrian Chadd addpart(type, devname, mntpt, auxarg)
3099a317438SAdrian Chadd 	const char *type, *devname, *mntpt;
3109a317438SAdrian Chadd 	void *auxarg;
3119a317438SAdrian Chadd {
3129a317438SAdrian Chadd 	struct diskentry *d = finddisk(devname);
3139a317438SAdrian Chadd 	struct partentry *p;
3149a317438SAdrian Chadd 
315dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(p, &d->d_part, p_entries)
3169a317438SAdrian Chadd 		if (strcmp(p->p_devname, devname) == 0) {
3179a317438SAdrian Chadd 			warnx("%s in fstab more than once!\n", devname);
3189a317438SAdrian Chadd 			return;
3199a317438SAdrian Chadd 		}
3209a317438SAdrian Chadd 
3219a317438SAdrian Chadd 	p = emalloc(sizeof(*p));
3229a317438SAdrian Chadd 	p->p_devname = estrdup(devname);
3239a317438SAdrian Chadd 	p->p_mntpt = estrdup(mntpt);
3249a317438SAdrian Chadd 	p->p_type = estrdup(type);
3259a317438SAdrian Chadd 	p->p_auxarg = auxarg;
3269a317438SAdrian Chadd 
3279a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
3289a317438SAdrian Chadd }
3299a317438SAdrian Chadd 
3309a317438SAdrian Chadd 
3319a317438SAdrian Chadd static int
3329a317438SAdrian Chadd startdisk(d, checkit)
3339a317438SAdrian Chadd 	struct diskentry *d;
3349a317438SAdrian Chadd 	int (*checkit) __P((const char *, const char *, const char *, void *,
3359a317438SAdrian Chadd 	    pid_t *));
3369a317438SAdrian Chadd {
33732ff2662SPoul-Henning Kamp 	struct partentry *p = TAILQ_FIRST(&d->d_part);
3389a317438SAdrian Chadd 	int rv;
3399a317438SAdrian Chadd 
3409a317438SAdrian Chadd 	while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
3419a317438SAdrian Chadd 	    p->p_auxarg, &d->d_pid)) != 0 && nrun > 0)
3429a317438SAdrian Chadd 		sleep(10);
3439a317438SAdrian Chadd 
3449a317438SAdrian Chadd 	if (rv == 0)
3459a317438SAdrian Chadd 		nrun++;
3469a317438SAdrian Chadd 
3479a317438SAdrian Chadd 	return rv;
3489a317438SAdrian Chadd }
349