xref: /freebsd/sbin/fsck/preen.c (revision 1efe3c6b58ea5d0e5a0d49039d84d00f2370c7de)
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  * 4. Neither the name of the University nor the names of its contributors
169a317438SAdrian Chadd  *    may be used to endorse or promote products derived from this software
179a317438SAdrian Chadd  *    without specific prior written permission.
189a317438SAdrian Chadd  *
199a317438SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209a317438SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219a317438SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229a317438SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239a317438SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249a317438SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259a317438SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269a317438SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279a317438SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289a317438SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299a317438SAdrian Chadd  * SUCH DAMAGE.
309a317438SAdrian Chadd  *
319a317438SAdrian Chadd  * $FreeBSD$
329a317438SAdrian Chadd  */
339a317438SAdrian Chadd 
349a317438SAdrian Chadd #include <sys/cdefs.h>
359a317438SAdrian Chadd #ifndef lint
369a317438SAdrian Chadd #if 0
379a317438SAdrian Chadd static char sccsid[] = "@(#)preen.c	8.5 (Berkeley) 4/28/95";
389a317438SAdrian Chadd #else
399a317438SAdrian Chadd __RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $");
409a317438SAdrian Chadd #endif
419a317438SAdrian Chadd #endif /* not lint */
429a317438SAdrian Chadd 
439a317438SAdrian Chadd #include <sys/param.h>
449a317438SAdrian Chadd #include <sys/stat.h>
459a317438SAdrian Chadd #include <sys/wait.h>
469a317438SAdrian Chadd #include <sys/queue.h>
479a317438SAdrian Chadd 
489a317438SAdrian Chadd #include <err.h>
499a317438SAdrian Chadd #include <ctype.h>
509a317438SAdrian Chadd #include <fstab.h>
519a317438SAdrian Chadd #include <string.h>
529a317438SAdrian Chadd #include <stdio.h>
539a317438SAdrian Chadd #include <stdlib.h>
549a317438SAdrian Chadd #include <unistd.h>
559a317438SAdrian Chadd 
569a317438SAdrian Chadd #include "fsutil.h"
579a317438SAdrian Chadd 
589a317438SAdrian Chadd struct partentry {
599a317438SAdrian Chadd 	TAILQ_ENTRY(partentry)	 p_entries;
609a317438SAdrian Chadd 	char		  	*p_devname;	/* device name */
619a317438SAdrian Chadd 	char			*p_mntpt;	/* mount point */
629a317438SAdrian Chadd 	char		  	*p_type;	/* file system type */
639a317438SAdrian Chadd };
649a317438SAdrian Chadd 
65*1efe3c6bSEd Schouten static TAILQ_HEAD(part, partentry) badh;
669a317438SAdrian Chadd 
679a317438SAdrian Chadd struct diskentry {
689a317438SAdrian Chadd 	TAILQ_ENTRY(diskentry) 	    d_entries;
699a317438SAdrian Chadd 	char		       	   *d_name;	/* disk base name */
709a317438SAdrian Chadd 	TAILQ_HEAD(prt, partentry)  d_part;	/* list of partitions on disk */
719a317438SAdrian Chadd 	int			    d_pid;	/* 0 or pid of fsck proc */
729a317438SAdrian Chadd };
739a317438SAdrian Chadd 
74*1efe3c6bSEd Schouten static TAILQ_HEAD(disk, diskentry) diskh;
759a317438SAdrian Chadd 
769a317438SAdrian Chadd static int nrun = 0, ndisks = 0;
779a317438SAdrian Chadd 
78b70cd7eeSWarner Losh static struct diskentry *finddisk(const char *);
79b70cd7eeSWarner Losh static void addpart(const char *, const char *, const char *);
80b70cd7eeSWarner Losh static int startdisk(struct diskentry *,
81b70cd7eeSWarner Losh     int (*)(const char *, const char *, const char *, char *, pid_t *));
82b70cd7eeSWarner Losh static void printpart(void);
839a317438SAdrian Chadd 
849a317438SAdrian Chadd int
85b70cd7eeSWarner Losh checkfstab(int flags, int (*docheck)(struct fstab *),
86b70cd7eeSWarner Losh     int (*checkit)(const char *, const char *, const char *, char *, pid_t *))
879a317438SAdrian Chadd {
889a317438SAdrian Chadd 	struct fstab *fs;
899a317438SAdrian Chadd 	struct diskentry *d, *nextdisk;
909a317438SAdrian Chadd 	struct partentry *p;
910af7bca2SPoul-Henning Kamp 	int ret, pid, retcode, passno, sumstatus, status, nextpass;
929a317438SAdrian Chadd 	const char *name;
939a317438SAdrian Chadd 
949a317438SAdrian Chadd 	TAILQ_INIT(&badh);
959a317438SAdrian Chadd 	TAILQ_INIT(&diskh);
969a317438SAdrian Chadd 
979a317438SAdrian Chadd 	sumstatus = 0;
989a317438SAdrian Chadd 
990af7bca2SPoul-Henning Kamp 	nextpass = 0;
1000af7bca2SPoul-Henning Kamp 	for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
1010af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG)
1020af7bca2SPoul-Henning Kamp 			printf("pass %d\n", passno);
1030af7bca2SPoul-Henning Kamp 
1040af7bca2SPoul-Henning Kamp 		nextpass = INT_MAX;
1059a317438SAdrian Chadd 		if (setfsent() == 0) {
1069a317438SAdrian Chadd 			warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
1079a317438SAdrian Chadd 			return (8);
1089a317438SAdrian Chadd 		}
1099a317438SAdrian Chadd 		while ((fs = getfsent()) != 0) {
1109a317438SAdrian Chadd 			name = fs->fs_spec;
1110af7bca2SPoul-Henning Kamp 			if (fs->fs_passno > passno && fs->fs_passno < nextpass)
1120af7bca2SPoul-Henning Kamp 				nextpass = fs->fs_passno;
1130af7bca2SPoul-Henning Kamp 
1145cb6703eSPoul-Henning Kamp 			if (passno != fs->fs_passno)
1155cb6703eSPoul-Henning Kamp 				continue;
1165cb6703eSPoul-Henning Kamp 
1175cb6703eSPoul-Henning Kamp 			if ((*docheck)(fs) == 0)
1180af7bca2SPoul-Henning Kamp 				continue;
1190af7bca2SPoul-Henning Kamp 
1209a317438SAdrian Chadd 			if (flags & CHECK_DEBUG)
1219a317438SAdrian Chadd 				printf("pass %d, name %s\n", passno, name);
1229a317438SAdrian Chadd 
123a02a0079SKirk McKusick 			if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
124a02a0079SKirk McKusick 			    (flags & DO_BACKGRD) != 0) {
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,
132a02a0079SKirk McKusick 				    name, fs->fs_file, NULL, NULL);
1339a317438SAdrian Chadd 
1349a317438SAdrian Chadd 				if (sumstatus)
1359a317438SAdrian Chadd 					return (sumstatus);
1360af7bca2SPoul-Henning Kamp 				continue;
1370af7bca2SPoul-Henning Kamp 			}
1389a317438SAdrian Chadd 			if (name == NULL) {
1399a317438SAdrian Chadd 				(void) fprintf(stderr,
1409a317438SAdrian Chadd 				    "BAD DISK NAME %s\n", fs->fs_spec);
1419a317438SAdrian Chadd 				sumstatus |= 8;
1429a317438SAdrian Chadd 				continue;
1439a317438SAdrian Chadd 			}
144a02a0079SKirk McKusick 			addpart(fs->fs_vfstype, name, fs->fs_file);
1459a317438SAdrian Chadd 		}
1460af7bca2SPoul-Henning Kamp 
147a02a0079SKirk McKusick 		if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
148a02a0079SKirk McKusick 		    (flags & DO_BACKGRD) != 0)
1490af7bca2SPoul-Henning Kamp 			continue;
1500af7bca2SPoul-Henning Kamp 
1510af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
1520af7bca2SPoul-Henning Kamp 			printf("Parallel start\n");
1530af7bca2SPoul-Henning Kamp 			printpart();
1549a317438SAdrian Chadd 		}
1550af7bca2SPoul-Henning Kamp 
1560af7bca2SPoul-Henning Kamp 		TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
1570af7bca2SPoul-Henning Kamp 			if ((ret = startdisk(nextdisk, checkit)) != 0)
1580af7bca2SPoul-Henning Kamp 				return ret;
1599a317438SAdrian Chadd 		}
1609a317438SAdrian Chadd 
1619a317438SAdrian Chadd 		if (flags & CHECK_DEBUG)
1620af7bca2SPoul-Henning Kamp 			printf("Parallel wait\n");
1639a317438SAdrian Chadd 		while ((pid = wait(&status)) != -1) {
164dab777beSPoul-Henning Kamp 			TAILQ_FOREACH(d, &diskh, d_entries)
1659a317438SAdrian Chadd 				if (d->d_pid == pid)
1669a317438SAdrian Chadd 					break;
1679a317438SAdrian Chadd 
1689a317438SAdrian Chadd 			if (d == NULL) {
1699a317438SAdrian Chadd 				warnx("Unknown pid %d\n", pid);
1709a317438SAdrian Chadd 				continue;
1719a317438SAdrian Chadd 			}
1729a317438SAdrian Chadd 
1739a317438SAdrian Chadd 			if (WIFEXITED(status))
1749a317438SAdrian Chadd 				retcode = WEXITSTATUS(status);
1759a317438SAdrian Chadd 			else
1769a317438SAdrian Chadd 				retcode = 0;
1779a317438SAdrian Chadd 
178dab777beSPoul-Henning Kamp 			p = TAILQ_FIRST(&d->d_part);
1799a317438SAdrian Chadd 
1809a317438SAdrian Chadd 			if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
1819a317438SAdrian Chadd 				(void) printf("done %s: %s (%s) = 0x%x\n",
1829a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1839a317438SAdrian Chadd 				    status);
1849a317438SAdrian Chadd 
1859a317438SAdrian Chadd 			if (WIFSIGNALED(status)) {
1869a317438SAdrian Chadd 				(void) fprintf(stderr,
1879a317438SAdrian Chadd 				    "%s: %s (%s): EXITED WITH SIGNAL %d\n",
1889a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1899a317438SAdrian Chadd 				    WTERMSIG(status));
1909a317438SAdrian Chadd 				retcode = 8;
1919a317438SAdrian Chadd 			}
1929a317438SAdrian Chadd 
1939a317438SAdrian Chadd 			TAILQ_REMOVE(&d->d_part, p, p_entries);
1949a317438SAdrian Chadd 
1959a317438SAdrian Chadd 			if (retcode != 0) {
1969a317438SAdrian Chadd 				TAILQ_INSERT_TAIL(&badh, p, p_entries);
1979a317438SAdrian Chadd 				sumstatus |= retcode;
1989a317438SAdrian Chadd 			} else {
1999a317438SAdrian Chadd 				free(p->p_type);
2009a317438SAdrian Chadd 				free(p->p_devname);
2019a317438SAdrian Chadd 				free(p);
2029a317438SAdrian Chadd 			}
2039a317438SAdrian Chadd 			d->d_pid = 0;
2049a317438SAdrian Chadd 			nrun--;
2059a317438SAdrian Chadd 
2060af7bca2SPoul-Henning Kamp 			if (TAILQ_EMPTY(&d->d_part)) {
2070af7bca2SPoul-Henning Kamp 				TAILQ_REMOVE(&diskh, d, d_entries);
2089a317438SAdrian Chadd 				ndisks--;
20946e78a1fSPoul-Henning Kamp 			} else {
21046e78a1fSPoul-Henning Kamp 				if ((ret = startdisk(d, checkit)) != 0)
21146e78a1fSPoul-Henning Kamp 					return ret;
2120af7bca2SPoul-Henning Kamp 			}
2130af7bca2SPoul-Henning Kamp 		}
2140af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
2150af7bca2SPoul-Henning Kamp 			printf("Parallel end\n");
2160af7bca2SPoul-Henning Kamp 			printpart();
2170af7bca2SPoul-Henning Kamp 		}
2180af7bca2SPoul-Henning Kamp 	}
2199a317438SAdrian Chadd 
2200af7bca2SPoul-Henning Kamp 	if (!(flags & CHECK_PREEN))
2210af7bca2SPoul-Henning Kamp 			return 0;
2220af7bca2SPoul-Henning Kamp 
2239a317438SAdrian Chadd 	if (sumstatus) {
22432ff2662SPoul-Henning Kamp 		p = TAILQ_FIRST(&badh);
2259a317438SAdrian Chadd 		if (p == NULL)
2269a317438SAdrian Chadd 			return (sumstatus);
2279a317438SAdrian Chadd 
2289a317438SAdrian Chadd 		(void) fprintf(stderr,
2299a317438SAdrian Chadd 			"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
230dab777beSPoul-Henning Kamp 			TAILQ_NEXT(p, p_entries) ? "S" : "",
2319a317438SAdrian Chadd 			"UNEXPECTED INCONSISTENCY:");
2329a317438SAdrian Chadd 
233dab777beSPoul-Henning Kamp 		for (; p; p = TAILQ_NEXT(p, p_entries))
2349a317438SAdrian Chadd 			(void) fprintf(stderr,
2359a317438SAdrian Chadd 			    "%s: %s (%s)%s", p->p_type, p->p_devname,
236dab777beSPoul-Henning Kamp 			    p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2379a317438SAdrian Chadd 
2389a317438SAdrian Chadd 		return sumstatus;
2399a317438SAdrian Chadd 	}
2409a317438SAdrian Chadd 	(void) endfsent();
2419a317438SAdrian Chadd 	return (0);
2429a317438SAdrian Chadd }
2439a317438SAdrian Chadd 
2449a317438SAdrian Chadd 
2459a317438SAdrian Chadd static struct diskentry *
246b70cd7eeSWarner Losh finddisk(const char *name)
2479a317438SAdrian Chadd {
2489a317438SAdrian Chadd 	const char *p;
2499a317438SAdrian Chadd 	size_t len = 0;
2509a317438SAdrian Chadd 	struct diskentry *d;
2519a317438SAdrian Chadd 
25228b66787SPoul-Henning Kamp 	p = strrchr(name, '/');
25328b66787SPoul-Henning Kamp 	if (p == NULL)
25428b66787SPoul-Henning Kamp 		p = name;
25528b66787SPoul-Henning Kamp 	else
25628b66787SPoul-Henning Kamp 		p++;
25728b66787SPoul-Henning Kamp 	for (; *p && !isdigit(*p); p++)
25828b66787SPoul-Henning Kamp 		continue;
25928b66787SPoul-Henning Kamp 	for (; *p && isdigit(*p); p++)
26028b66787SPoul-Henning Kamp 		continue;
26128b66787SPoul-Henning Kamp 	len = p - name;
26228b66787SPoul-Henning Kamp 	if (len == 0)
2639a317438SAdrian Chadd 		len = strlen(name);
2649a317438SAdrian Chadd 
265dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries)
2669a317438SAdrian Chadd 		if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2679a317438SAdrian Chadd 			return d;
2689a317438SAdrian Chadd 
2699a317438SAdrian Chadd 	d = emalloc(sizeof(*d));
2709a317438SAdrian Chadd 	d->d_name = estrdup(name);
2719a317438SAdrian Chadd 	d->d_name[len] = '\0';
2729a317438SAdrian Chadd 	TAILQ_INIT(&d->d_part);
2739a317438SAdrian Chadd 	d->d_pid = 0;
2749a317438SAdrian Chadd 
2759a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2769a317438SAdrian Chadd 	ndisks++;
2779a317438SAdrian Chadd 
2789a317438SAdrian Chadd 	return d;
2799a317438SAdrian Chadd }
2809a317438SAdrian Chadd 
2819a317438SAdrian Chadd 
2829a317438SAdrian Chadd static void
283b70cd7eeSWarner Losh printpart(void)
2849a317438SAdrian Chadd {
2859a317438SAdrian Chadd 	struct diskentry *d;
2869a317438SAdrian Chadd 	struct partentry *p;
2879a317438SAdrian Chadd 
288dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries) {
2899a317438SAdrian Chadd 		(void) printf("disk %s: ", d->d_name);
290dab777beSPoul-Henning Kamp 		TAILQ_FOREACH(p, &d->d_part, p_entries)
2919a317438SAdrian Chadd 			(void) printf("%s ", p->p_devname);
2929a317438SAdrian Chadd 		(void) printf("\n");
2939a317438SAdrian Chadd 	}
2949a317438SAdrian Chadd }
2959a317438SAdrian Chadd 
2969a317438SAdrian Chadd 
2979a317438SAdrian Chadd static void
298b70cd7eeSWarner Losh addpart(const char *type, const char *devname, const char *mntpt)
2999a317438SAdrian Chadd {
3009a317438SAdrian Chadd 	struct diskentry *d = finddisk(devname);
3019a317438SAdrian Chadd 	struct partentry *p;
3029a317438SAdrian Chadd 
303dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(p, &d->d_part, p_entries)
3049a317438SAdrian Chadd 		if (strcmp(p->p_devname, devname) == 0) {
3059a317438SAdrian Chadd 			warnx("%s in fstab more than once!\n", devname);
3069a317438SAdrian Chadd 			return;
3079a317438SAdrian Chadd 		}
3089a317438SAdrian Chadd 
3099a317438SAdrian Chadd 	p = emalloc(sizeof(*p));
3109a317438SAdrian Chadd 	p->p_devname = estrdup(devname);
3119a317438SAdrian Chadd 	p->p_mntpt = estrdup(mntpt);
3129a317438SAdrian Chadd 	p->p_type = estrdup(type);
3139a317438SAdrian Chadd 
3149a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
3159a317438SAdrian Chadd }
3169a317438SAdrian Chadd 
3179a317438SAdrian Chadd 
3189a317438SAdrian Chadd static int
319b70cd7eeSWarner Losh startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
320b70cd7eeSWarner Losh     const char *, char *, pid_t *))
3219a317438SAdrian Chadd {
32232ff2662SPoul-Henning Kamp 	struct partentry *p = TAILQ_FIRST(&d->d_part);
3239a317438SAdrian Chadd 	int rv;
3249a317438SAdrian Chadd 
3259a317438SAdrian Chadd 	while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
326a02a0079SKirk McKusick 	    NULL, &d->d_pid)) != 0 && nrun > 0)
3279a317438SAdrian Chadd 		sleep(10);
3289a317438SAdrian Chadd 
3299a317438SAdrian Chadd 	if (rv == 0)
3309a317438SAdrian Chadd 		nrun++;
3319a317438SAdrian Chadd 
3329a317438SAdrian Chadd 	return rv;
3339a317438SAdrian Chadd }
334