xref: /freebsd/sbin/fsck/preen.c (revision 5cb6703e2984ef4ad9d57bf0470aa9570800b5d9)
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;	/* file system type */
679a317438SAdrian Chadd };
689a317438SAdrian Chadd 
699a317438SAdrian Chadd TAILQ_HEAD(part, partentry) badh;
709a317438SAdrian Chadd 
719a317438SAdrian Chadd struct diskentry {
729a317438SAdrian Chadd 	TAILQ_ENTRY(diskentry) 	    d_entries;
739a317438SAdrian Chadd 	char		       	   *d_name;	/* disk base name */
749a317438SAdrian Chadd 	TAILQ_HEAD(prt, partentry)  d_part;	/* list of partitions on disk */
759a317438SAdrian Chadd 	int			    d_pid;	/* 0 or pid of fsck proc */
769a317438SAdrian Chadd };
779a317438SAdrian Chadd 
789a317438SAdrian Chadd TAILQ_HEAD(disk, diskentry) diskh;
799a317438SAdrian Chadd 
809a317438SAdrian Chadd static int nrun = 0, ndisks = 0;
819a317438SAdrian Chadd 
82b70cd7eeSWarner Losh static struct diskentry *finddisk(const char *);
83b70cd7eeSWarner Losh static void addpart(const char *, const char *, const char *);
84b70cd7eeSWarner Losh static int startdisk(struct diskentry *,
85b70cd7eeSWarner Losh     int (*)(const char *, const char *, const char *, char *, pid_t *));
86b70cd7eeSWarner Losh static void printpart(void);
879a317438SAdrian Chadd 
889a317438SAdrian Chadd int
89b70cd7eeSWarner Losh checkfstab(int flags, int (*docheck)(struct fstab *),
90b70cd7eeSWarner Losh     int (*checkit)(const char *, const char *, const char *, char *, pid_t *))
919a317438SAdrian Chadd {
929a317438SAdrian Chadd 	struct fstab *fs;
939a317438SAdrian Chadd 	struct diskentry *d, *nextdisk;
949a317438SAdrian Chadd 	struct partentry *p;
950af7bca2SPoul-Henning Kamp 	int ret, pid, retcode, passno, sumstatus, status, nextpass;
969a317438SAdrian Chadd 	const char *name;
979a317438SAdrian Chadd 
989a317438SAdrian Chadd 	TAILQ_INIT(&badh);
999a317438SAdrian Chadd 	TAILQ_INIT(&diskh);
1009a317438SAdrian Chadd 
1019a317438SAdrian Chadd 	sumstatus = 0;
1029a317438SAdrian Chadd 
1030af7bca2SPoul-Henning Kamp 	nextpass = 0;
1040af7bca2SPoul-Henning Kamp 	for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
1050af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG)
1060af7bca2SPoul-Henning Kamp 			printf("pass %d\n", passno);
1070af7bca2SPoul-Henning Kamp 
1080af7bca2SPoul-Henning Kamp 		nextpass = INT_MAX;
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 			name = fs->fs_spec;
1150af7bca2SPoul-Henning Kamp 			if (fs->fs_passno > passno && fs->fs_passno < nextpass)
1160af7bca2SPoul-Henning Kamp 				nextpass = fs->fs_passno;
1170af7bca2SPoul-Henning Kamp 
1185cb6703eSPoul-Henning Kamp 			if (passno != fs->fs_passno)
1195cb6703eSPoul-Henning Kamp 				continue;
1205cb6703eSPoul-Henning Kamp 
1215cb6703eSPoul-Henning Kamp 			if ((*docheck)(fs) == 0)
1220af7bca2SPoul-Henning Kamp 				continue;
1230af7bca2SPoul-Henning Kamp 
1249a317438SAdrian Chadd 			if (flags & CHECK_DEBUG)
1259a317438SAdrian Chadd 				printf("pass %d, name %s\n", passno, name);
1269a317438SAdrian Chadd 
127a02a0079SKirk McKusick 			if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
128a02a0079SKirk McKusick 			    (flags & DO_BACKGRD) != 0) {
1299a317438SAdrian Chadd 				if (name == NULL) {
1309a317438SAdrian Chadd 					if (flags & CHECK_PREEN)
1319a317438SAdrian Chadd 						return 8;
1329a317438SAdrian Chadd 					else
1339a317438SAdrian Chadd 						continue;
1349a317438SAdrian Chadd 				}
1359a317438SAdrian Chadd 				sumstatus = (*checkit)(fs->fs_vfstype,
136a02a0079SKirk McKusick 				    name, fs->fs_file, NULL, NULL);
1379a317438SAdrian Chadd 
1389a317438SAdrian Chadd 				if (sumstatus)
1399a317438SAdrian Chadd 					return (sumstatus);
1400af7bca2SPoul-Henning Kamp 				continue;
1410af7bca2SPoul-Henning Kamp 			}
1429a317438SAdrian Chadd 			if (name == NULL) {
1439a317438SAdrian Chadd 				(void) fprintf(stderr,
1449a317438SAdrian Chadd 				    "BAD DISK NAME %s\n", fs->fs_spec);
1459a317438SAdrian Chadd 				sumstatus |= 8;
1469a317438SAdrian Chadd 				continue;
1479a317438SAdrian Chadd 			}
148a02a0079SKirk McKusick 			addpart(fs->fs_vfstype, name, fs->fs_file);
1499a317438SAdrian Chadd 		}
1500af7bca2SPoul-Henning Kamp 
151a02a0079SKirk McKusick 		if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
152a02a0079SKirk McKusick 		    (flags & DO_BACKGRD) != 0)
1530af7bca2SPoul-Henning Kamp 			continue;
1540af7bca2SPoul-Henning Kamp 
1550af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
1560af7bca2SPoul-Henning Kamp 			printf("Parallel start\n");
1570af7bca2SPoul-Henning Kamp 			printpart();
1589a317438SAdrian Chadd 		}
1590af7bca2SPoul-Henning Kamp 
1600af7bca2SPoul-Henning Kamp 		TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
1610af7bca2SPoul-Henning Kamp 			if ((ret = startdisk(nextdisk, checkit)) != 0)
1620af7bca2SPoul-Henning Kamp 				return ret;
1639a317438SAdrian Chadd 		}
1649a317438SAdrian Chadd 
1659a317438SAdrian Chadd 		if (flags & CHECK_DEBUG)
1660af7bca2SPoul-Henning Kamp 			printf("Parallel wait\n");
1679a317438SAdrian Chadd 		while ((pid = wait(&status)) != -1) {
168dab777beSPoul-Henning Kamp 			TAILQ_FOREACH(d, &diskh, d_entries)
1699a317438SAdrian Chadd 				if (d->d_pid == pid)
1709a317438SAdrian Chadd 					break;
1719a317438SAdrian Chadd 
1729a317438SAdrian Chadd 			if (d == NULL) {
1739a317438SAdrian Chadd 				warnx("Unknown pid %d\n", pid);
1749a317438SAdrian Chadd 				continue;
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 
2100af7bca2SPoul-Henning Kamp 			if (TAILQ_EMPTY(&d->d_part)) {
2110af7bca2SPoul-Henning Kamp 				TAILQ_REMOVE(&diskh, d, d_entries);
2129a317438SAdrian Chadd 				ndisks--;
21346e78a1fSPoul-Henning Kamp 			} else {
21446e78a1fSPoul-Henning Kamp 				if ((ret = startdisk(d, checkit)) != 0)
21546e78a1fSPoul-Henning Kamp 					return ret;
2160af7bca2SPoul-Henning Kamp 			}
2170af7bca2SPoul-Henning Kamp 		}
2180af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
2190af7bca2SPoul-Henning Kamp 			printf("Parallel end\n");
2200af7bca2SPoul-Henning Kamp 			printpart();
2210af7bca2SPoul-Henning Kamp 		}
2220af7bca2SPoul-Henning Kamp 	}
2239a317438SAdrian Chadd 
2240af7bca2SPoul-Henning Kamp 	if (!(flags & CHECK_PREEN))
2250af7bca2SPoul-Henning Kamp 			return 0;
2260af7bca2SPoul-Henning Kamp 
2279a317438SAdrian Chadd 	if (sumstatus) {
22832ff2662SPoul-Henning Kamp 		p = TAILQ_FIRST(&badh);
2299a317438SAdrian Chadd 		if (p == NULL)
2309a317438SAdrian Chadd 			return (sumstatus);
2319a317438SAdrian Chadd 
2329a317438SAdrian Chadd 		(void) fprintf(stderr,
2339a317438SAdrian Chadd 			"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
234dab777beSPoul-Henning Kamp 			TAILQ_NEXT(p, p_entries) ? "S" : "",
2359a317438SAdrian Chadd 			"UNEXPECTED INCONSISTENCY:");
2369a317438SAdrian Chadd 
237dab777beSPoul-Henning Kamp 		for (; p; p = TAILQ_NEXT(p, p_entries))
2389a317438SAdrian Chadd 			(void) fprintf(stderr,
2399a317438SAdrian Chadd 			    "%s: %s (%s)%s", p->p_type, p->p_devname,
240dab777beSPoul-Henning Kamp 			    p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2419a317438SAdrian Chadd 
2429a317438SAdrian Chadd 		return sumstatus;
2439a317438SAdrian Chadd 	}
2449a317438SAdrian Chadd 	(void) endfsent();
2459a317438SAdrian Chadd 	return (0);
2469a317438SAdrian Chadd }
2479a317438SAdrian Chadd 
2489a317438SAdrian Chadd 
2499a317438SAdrian Chadd static struct diskentry *
250b70cd7eeSWarner Losh finddisk(const char *name)
2519a317438SAdrian Chadd {
2529a317438SAdrian Chadd 	const char *p;
2539a317438SAdrian Chadd 	size_t len = 0;
2549a317438SAdrian Chadd 	struct diskentry *d;
2559a317438SAdrian Chadd 
25628b66787SPoul-Henning Kamp 	p = strrchr(name, '/');
25728b66787SPoul-Henning Kamp 	if (p == NULL)
25828b66787SPoul-Henning Kamp 		p = name;
25928b66787SPoul-Henning Kamp 	else
26028b66787SPoul-Henning Kamp 		p++;
26128b66787SPoul-Henning Kamp 	for (; *p && !isdigit(*p); p++)
26228b66787SPoul-Henning Kamp 		continue;
26328b66787SPoul-Henning Kamp 	for (; *p && isdigit(*p); p++)
26428b66787SPoul-Henning Kamp 		continue;
26528b66787SPoul-Henning Kamp 	len = p - name;
26628b66787SPoul-Henning Kamp 	if (len == 0)
2679a317438SAdrian Chadd 		len = strlen(name);
2689a317438SAdrian Chadd 
269dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries)
2709a317438SAdrian Chadd 		if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2719a317438SAdrian Chadd 			return d;
2729a317438SAdrian Chadd 
2739a317438SAdrian Chadd 	d = emalloc(sizeof(*d));
2749a317438SAdrian Chadd 	d->d_name = estrdup(name);
2759a317438SAdrian Chadd 	d->d_name[len] = '\0';
2769a317438SAdrian Chadd 	TAILQ_INIT(&d->d_part);
2779a317438SAdrian Chadd 	d->d_pid = 0;
2789a317438SAdrian Chadd 
2799a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2809a317438SAdrian Chadd 	ndisks++;
2819a317438SAdrian Chadd 
2829a317438SAdrian Chadd 	return d;
2839a317438SAdrian Chadd }
2849a317438SAdrian Chadd 
2859a317438SAdrian Chadd 
2869a317438SAdrian Chadd static void
287b70cd7eeSWarner Losh printpart(void)
2889a317438SAdrian Chadd {
2899a317438SAdrian Chadd 	struct diskentry *d;
2909a317438SAdrian Chadd 	struct partentry *p;
2919a317438SAdrian Chadd 
292dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries) {
2939a317438SAdrian Chadd 		(void) printf("disk %s: ", d->d_name);
294dab777beSPoul-Henning Kamp 		TAILQ_FOREACH(p, &d->d_part, p_entries)
2959a317438SAdrian Chadd 			(void) printf("%s ", p->p_devname);
2969a317438SAdrian Chadd 		(void) printf("\n");
2979a317438SAdrian Chadd 	}
2989a317438SAdrian Chadd }
2999a317438SAdrian Chadd 
3009a317438SAdrian Chadd 
3019a317438SAdrian Chadd static void
302b70cd7eeSWarner Losh addpart(const char *type, const char *devname, const char *mntpt)
3039a317438SAdrian Chadd {
3049a317438SAdrian Chadd 	struct diskentry *d = finddisk(devname);
3059a317438SAdrian Chadd 	struct partentry *p;
3069a317438SAdrian Chadd 
307dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(p, &d->d_part, p_entries)
3089a317438SAdrian Chadd 		if (strcmp(p->p_devname, devname) == 0) {
3099a317438SAdrian Chadd 			warnx("%s in fstab more than once!\n", devname);
3109a317438SAdrian Chadd 			return;
3119a317438SAdrian Chadd 		}
3129a317438SAdrian Chadd 
3139a317438SAdrian Chadd 	p = emalloc(sizeof(*p));
3149a317438SAdrian Chadd 	p->p_devname = estrdup(devname);
3159a317438SAdrian Chadd 	p->p_mntpt = estrdup(mntpt);
3169a317438SAdrian Chadd 	p->p_type = estrdup(type);
3179a317438SAdrian Chadd 
3189a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
3199a317438SAdrian Chadd }
3209a317438SAdrian Chadd 
3219a317438SAdrian Chadd 
3229a317438SAdrian Chadd static int
323b70cd7eeSWarner Losh startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
324b70cd7eeSWarner Losh     const char *, char *, pid_t *))
3259a317438SAdrian Chadd {
32632ff2662SPoul-Henning Kamp 	struct partentry *p = TAILQ_FIRST(&d->d_part);
3279a317438SAdrian Chadd 	int rv;
3289a317438SAdrian Chadd 
3299a317438SAdrian Chadd 	while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
330a02a0079SKirk McKusick 	    NULL, &d->d_pid)) != 0 && nrun > 0)
3319a317438SAdrian Chadd 		sleep(10);
3329a317438SAdrian Chadd 
3339a317438SAdrian Chadd 	if (rv == 0)
3349a317438SAdrian Chadd 		nrun++;
3359a317438SAdrian Chadd 
3369a317438SAdrian Chadd 	return rv;
3379a317438SAdrian Chadd }
338