xref: /freebsd/sbin/fsck/preen.c (revision 5b31cc94b10d4bb7109c6b27940a0fc76a44a331)
19a317438SAdrian Chadd /*	$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $	*/
29a317438SAdrian Chadd 
38a16b7a1SPedro F. Giffuni /*-
48a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni  *
69a317438SAdrian Chadd  * Copyright (c) 1990, 1993
79a317438SAdrian Chadd  *	The Regents of the University of California.  All rights reserved.
89a317438SAdrian Chadd  *
99a317438SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
109a317438SAdrian Chadd  * modification, are permitted provided that the following conditions
119a317438SAdrian Chadd  * are met:
129a317438SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
139a317438SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
149a317438SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
159a317438SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
169a317438SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
17fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
189a317438SAdrian Chadd  *    may be used to endorse or promote products derived from this software
199a317438SAdrian Chadd  *    without specific prior written permission.
209a317438SAdrian Chadd  *
219a317438SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
229a317438SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239a317438SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249a317438SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259a317438SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269a317438SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279a317438SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289a317438SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299a317438SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309a317438SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319a317438SAdrian Chadd  * SUCH DAMAGE.
329a317438SAdrian Chadd  */
339a317438SAdrian Chadd 
34*5b31cc94SWarner Losh /* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
359a317438SAdrian Chadd 
369a317438SAdrian Chadd #include <sys/param.h>
379a317438SAdrian Chadd #include <sys/stat.h>
389a317438SAdrian Chadd #include <sys/wait.h>
399a317438SAdrian Chadd #include <sys/queue.h>
409a317438SAdrian Chadd 
419a317438SAdrian Chadd #include <err.h>
429a317438SAdrian Chadd #include <ctype.h>
439a317438SAdrian Chadd #include <fstab.h>
449a317438SAdrian Chadd #include <string.h>
459a317438SAdrian Chadd #include <stdio.h>
469a317438SAdrian Chadd #include <stdlib.h>
479a317438SAdrian Chadd #include <unistd.h>
489a317438SAdrian Chadd 
499a317438SAdrian Chadd #include "fsutil.h"
509a317438SAdrian Chadd 
519a317438SAdrian Chadd struct partentry {
529a317438SAdrian Chadd 	TAILQ_ENTRY(partentry)	 p_entries;
539a317438SAdrian Chadd 	char		  	*p_devname;	/* device name */
549a317438SAdrian Chadd 	char			*p_mntpt;	/* mount point */
559a317438SAdrian Chadd 	char		  	*p_type;	/* file system type */
56c72372c6SKirk McKusick 	int			 p_failok;	/* failok option set */
579a317438SAdrian Chadd };
589a317438SAdrian Chadd 
591efe3c6bSEd Schouten static TAILQ_HEAD(part, partentry) badh;
609a317438SAdrian Chadd 
619a317438SAdrian Chadd struct diskentry {
629a317438SAdrian Chadd 	TAILQ_ENTRY(diskentry) 	    d_entries;
639a317438SAdrian Chadd 	char		       	   *d_name;	/* disk base name */
649a317438SAdrian Chadd 	TAILQ_HEAD(prt, partentry)  d_part;	/* list of partitions on disk */
659a317438SAdrian Chadd 	int			    d_pid;	/* 0 or pid of fsck proc */
669a317438SAdrian Chadd };
679a317438SAdrian Chadd 
681efe3c6bSEd Schouten static TAILQ_HEAD(disk, diskentry) diskh;
699a317438SAdrian Chadd 
709a317438SAdrian Chadd static int nrun = 0, ndisks = 0;
719a317438SAdrian Chadd 
72b70cd7eeSWarner Losh static struct diskentry *finddisk(const char *);
73c72372c6SKirk McKusick static void addpart(const char *, const char *, const char *, const int);
74b70cd7eeSWarner Losh static int startdisk(struct diskentry *,
753bbc4438SUlrich Spörlein     int (*)(const char *, const char *, const char *, const char *, pid_t *));
76b70cd7eeSWarner Losh static void printpart(void);
779a317438SAdrian Chadd 
789a317438SAdrian Chadd int
checkfstab(int flags,int (* docheck)(struct fstab *),int (* checkit)(const char *,const char *,const char *,const char *,pid_t *))79b70cd7eeSWarner Losh checkfstab(int flags, int (*docheck)(struct fstab *),
803bbc4438SUlrich Spörlein     int (*checkit)(const char *, const char *, const char *, const char *, pid_t *))
819a317438SAdrian Chadd {
829a317438SAdrian Chadd 	struct fstab *fs;
839a317438SAdrian Chadd 	struct diskentry *d, *nextdisk;
849a317438SAdrian Chadd 	struct partentry *p;
850af7bca2SPoul-Henning Kamp 	int ret, pid, retcode, passno, sumstatus, status, nextpass;
869a317438SAdrian Chadd 	const char *name;
879a317438SAdrian Chadd 
889a317438SAdrian Chadd 	TAILQ_INIT(&badh);
899a317438SAdrian Chadd 	TAILQ_INIT(&diskh);
909a317438SAdrian Chadd 
919a317438SAdrian Chadd 	sumstatus = 0;
929a317438SAdrian Chadd 
930af7bca2SPoul-Henning Kamp 	nextpass = 0;
940af7bca2SPoul-Henning Kamp 	for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
950af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG)
960af7bca2SPoul-Henning Kamp 			printf("pass %d\n", passno);
970af7bca2SPoul-Henning Kamp 
980af7bca2SPoul-Henning Kamp 		nextpass = INT_MAX;
999a317438SAdrian Chadd 		if (setfsent() == 0) {
1009a317438SAdrian Chadd 			warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
1019a317438SAdrian Chadd 			return (8);
1029a317438SAdrian Chadd 		}
103cd5f6a0cSMarcelo Araujo 		while ((fs = getfsent()) != NULL) {
1049a317438SAdrian Chadd 			name = fs->fs_spec;
1050af7bca2SPoul-Henning Kamp 			if (fs->fs_passno > passno && fs->fs_passno < nextpass)
1060af7bca2SPoul-Henning Kamp 				nextpass = fs->fs_passno;
1070af7bca2SPoul-Henning Kamp 
1085cb6703eSPoul-Henning Kamp 			if (passno != fs->fs_passno)
1095cb6703eSPoul-Henning Kamp 				continue;
1105cb6703eSPoul-Henning Kamp 
1115cb6703eSPoul-Henning Kamp 			if ((*docheck)(fs) == 0)
1120af7bca2SPoul-Henning Kamp 				continue;
1130af7bca2SPoul-Henning Kamp 
1149a317438SAdrian Chadd 			if (flags & CHECK_DEBUG)
1159a317438SAdrian Chadd 				printf("pass %d, name %s\n", passno, name);
1169a317438SAdrian Chadd 
117a02a0079SKirk McKusick 			if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
118a02a0079SKirk McKusick 			    (flags & DO_BACKGRD) != 0) {
1199a317438SAdrian Chadd 				if (name == NULL) {
1209a317438SAdrian Chadd 					if (flags & CHECK_PREEN)
1219a317438SAdrian Chadd 						return 8;
1229a317438SAdrian Chadd 					else
1239a317438SAdrian Chadd 						continue;
1249a317438SAdrian Chadd 				}
1259a317438SAdrian Chadd 				sumstatus = (*checkit)(fs->fs_vfstype,
126a02a0079SKirk McKusick 				    name, fs->fs_file, NULL, NULL);
1279a317438SAdrian Chadd 				if (sumstatus)
1289a317438SAdrian Chadd 					return (sumstatus);
1290af7bca2SPoul-Henning Kamp 				continue;
1300af7bca2SPoul-Henning Kamp 			}
1319a317438SAdrian Chadd 			if (name == NULL) {
1329a317438SAdrian Chadd 				(void) fprintf(stderr,
1339a317438SAdrian Chadd 				    "BAD DISK NAME %s\n", fs->fs_spec);
1349a317438SAdrian Chadd 				sumstatus |= 8;
1359a317438SAdrian Chadd 				continue;
1369a317438SAdrian Chadd 			}
137c72372c6SKirk McKusick 			addpart(fs->fs_vfstype, name, fs->fs_file,
138c72372c6SKirk McKusick 			    getfsopt(fs, "failok"));
1399a317438SAdrian Chadd 		}
1400af7bca2SPoul-Henning Kamp 
141a02a0079SKirk McKusick 		if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
142a02a0079SKirk McKusick 		    (flags & DO_BACKGRD) != 0)
1430af7bca2SPoul-Henning Kamp 			continue;
1440af7bca2SPoul-Henning Kamp 
1450af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
1460af7bca2SPoul-Henning Kamp 			printf("Parallel start\n");
1470af7bca2SPoul-Henning Kamp 			printpart();
1489a317438SAdrian Chadd 		}
1490af7bca2SPoul-Henning Kamp 
1500af7bca2SPoul-Henning Kamp 		TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
1510af7bca2SPoul-Henning Kamp 			if ((ret = startdisk(nextdisk, checkit)) != 0)
1520af7bca2SPoul-Henning Kamp 				return ret;
1539a317438SAdrian Chadd 		}
1549a317438SAdrian Chadd 
1559a317438SAdrian Chadd 		if (flags & CHECK_DEBUG)
1560af7bca2SPoul-Henning Kamp 			printf("Parallel wait\n");
1579a317438SAdrian Chadd 		while ((pid = wait(&status)) != -1) {
158dab777beSPoul-Henning Kamp 			TAILQ_FOREACH(d, &diskh, d_entries)
1599a317438SAdrian Chadd 				if (d->d_pid == pid)
1609a317438SAdrian Chadd 					break;
1619a317438SAdrian Chadd 
1629a317438SAdrian Chadd 			if (d == NULL) {
1639a317438SAdrian Chadd 				warnx("Unknown pid %d\n", pid);
1649a317438SAdrian Chadd 				continue;
1659a317438SAdrian Chadd 			}
1669a317438SAdrian Chadd 
167dab777beSPoul-Henning Kamp 			p = TAILQ_FIRST(&d->d_part);
1689a317438SAdrian Chadd 
169c72372c6SKirk McKusick 			if (WIFEXITED(status) == 0) {
170c72372c6SKirk McKusick 				retcode = 0;
171c72372c6SKirk McKusick 			} else if (p->p_failok == 0) {
172c72372c6SKirk McKusick 				retcode = WEXITSTATUS(status);
173c72372c6SKirk McKusick 			} else {
174c72372c6SKirk McKusick 				retcode = 0;
175c72372c6SKirk McKusick 				fprintf(stderr, "%s: failok SPECIFIED, FSCK "
176c72372c6SKirk McKusick 				    "ERROR(S) IGNORED\n", p->p_devname);
177c72372c6SKirk McKusick 			}
178c72372c6SKirk McKusick 
1799a317438SAdrian Chadd 			if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
1809a317438SAdrian Chadd 				(void) printf("done %s: %s (%s) = 0x%x\n",
1819a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1829a317438SAdrian Chadd 				    status);
1839a317438SAdrian Chadd 
1849a317438SAdrian Chadd 			if (WIFSIGNALED(status)) {
1859a317438SAdrian Chadd 				(void) fprintf(stderr,
1869a317438SAdrian Chadd 				    "%s: %s (%s): EXITED WITH SIGNAL %d\n",
1879a317438SAdrian Chadd 				    p->p_type, p->p_devname, p->p_mntpt,
1889a317438SAdrian Chadd 				    WTERMSIG(status));
1899a317438SAdrian Chadd 				retcode = 8;
1909a317438SAdrian Chadd 			}
1919a317438SAdrian Chadd 
1929a317438SAdrian Chadd 			TAILQ_REMOVE(&d->d_part, p, p_entries);
1939a317438SAdrian Chadd 
1949a317438SAdrian Chadd 			if (retcode != 0) {
1959a317438SAdrian Chadd 				TAILQ_INSERT_TAIL(&badh, p, p_entries);
1969a317438SAdrian Chadd 				sumstatus |= retcode;
1979a317438SAdrian Chadd 			} else {
1989a317438SAdrian Chadd 				free(p->p_type);
1999a317438SAdrian Chadd 				free(p->p_devname);
2009a317438SAdrian Chadd 				free(p);
2019a317438SAdrian Chadd 			}
2029a317438SAdrian Chadd 			d->d_pid = 0;
2039a317438SAdrian Chadd 			nrun--;
2049a317438SAdrian Chadd 
2050af7bca2SPoul-Henning Kamp 			if (TAILQ_EMPTY(&d->d_part)) {
2060af7bca2SPoul-Henning Kamp 				TAILQ_REMOVE(&diskh, d, d_entries);
2079a317438SAdrian Chadd 				ndisks--;
20846e78a1fSPoul-Henning Kamp 			} else {
20946e78a1fSPoul-Henning Kamp 				if ((ret = startdisk(d, checkit)) != 0)
21046e78a1fSPoul-Henning Kamp 					return ret;
2110af7bca2SPoul-Henning Kamp 			}
2120af7bca2SPoul-Henning Kamp 		}
2130af7bca2SPoul-Henning Kamp 		if (flags & CHECK_DEBUG) {
2140af7bca2SPoul-Henning Kamp 			printf("Parallel end\n");
2150af7bca2SPoul-Henning Kamp 			printpart();
2160af7bca2SPoul-Henning Kamp 		}
2170af7bca2SPoul-Henning Kamp 	}
2189a317438SAdrian Chadd 
2190af7bca2SPoul-Henning Kamp 	if (!(flags & CHECK_PREEN))
2200af7bca2SPoul-Henning Kamp 			return 0;
2210af7bca2SPoul-Henning Kamp 
2229a317438SAdrian Chadd 	if (sumstatus) {
22332ff2662SPoul-Henning Kamp 		p = TAILQ_FIRST(&badh);
2249a317438SAdrian Chadd 		if (p == NULL)
2259a317438SAdrian Chadd 			return (sumstatus);
2269a317438SAdrian Chadd 
2279a317438SAdrian Chadd 		(void) fprintf(stderr,
2289a317438SAdrian Chadd 			"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
229dab777beSPoul-Henning Kamp 			TAILQ_NEXT(p, p_entries) ? "S" : "",
2309a317438SAdrian Chadd 			"UNEXPECTED INCONSISTENCY:");
2319a317438SAdrian Chadd 
232dab777beSPoul-Henning Kamp 		for (; p; p = TAILQ_NEXT(p, p_entries))
2339a317438SAdrian Chadd 			(void) fprintf(stderr,
2349a317438SAdrian Chadd 			    "%s: %s (%s)%s", p->p_type, p->p_devname,
235dab777beSPoul-Henning Kamp 			    p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2369a317438SAdrian Chadd 
2379a317438SAdrian Chadd 		return sumstatus;
2389a317438SAdrian Chadd 	}
2399a317438SAdrian Chadd 	(void) endfsent();
2409a317438SAdrian Chadd 	return (0);
2419a317438SAdrian Chadd }
2429a317438SAdrian Chadd 
2439a317438SAdrian Chadd static struct diskentry *
finddisk(const char * name)244b70cd7eeSWarner Losh finddisk(const char *name)
2459a317438SAdrian Chadd {
2469a317438SAdrian Chadd 	const char *p;
2479a317438SAdrian Chadd 	size_t len = 0;
2489a317438SAdrian Chadd 	struct diskentry *d;
2499a317438SAdrian Chadd 
25028b66787SPoul-Henning Kamp 	p = strrchr(name, '/');
25128b66787SPoul-Henning Kamp 	if (p == NULL)
25228b66787SPoul-Henning Kamp 		p = name;
25328b66787SPoul-Henning Kamp 	else
25428b66787SPoul-Henning Kamp 		p++;
25528b66787SPoul-Henning Kamp 	for (; *p && !isdigit(*p); p++)
25628b66787SPoul-Henning Kamp 		continue;
25728b66787SPoul-Henning Kamp 	for (; *p && isdigit(*p); p++)
25828b66787SPoul-Henning Kamp 		continue;
25928b66787SPoul-Henning Kamp 	len = p - name;
26028b66787SPoul-Henning Kamp 	if (len == 0)
2619a317438SAdrian Chadd 		len = strlen(name);
2629a317438SAdrian Chadd 
263dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries)
2649a317438SAdrian Chadd 		if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2659a317438SAdrian Chadd 			return d;
2669a317438SAdrian Chadd 
2679a317438SAdrian Chadd 	d = emalloc(sizeof(*d));
2689a317438SAdrian Chadd 	d->d_name = estrdup(name);
2699a317438SAdrian Chadd 	d->d_name[len] = '\0';
2709a317438SAdrian Chadd 	TAILQ_INIT(&d->d_part);
2719a317438SAdrian Chadd 	d->d_pid = 0;
2729a317438SAdrian Chadd 
2739a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2749a317438SAdrian Chadd 	ndisks++;
2759a317438SAdrian Chadd 
2769a317438SAdrian Chadd 	return d;
2779a317438SAdrian Chadd }
2789a317438SAdrian Chadd 
2799a317438SAdrian Chadd 
2809a317438SAdrian Chadd static void
printpart(void)281b70cd7eeSWarner Losh printpart(void)
2829a317438SAdrian Chadd {
2839a317438SAdrian Chadd 	struct diskentry *d;
2849a317438SAdrian Chadd 	struct partentry *p;
2859a317438SAdrian Chadd 
286dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(d, &diskh, d_entries) {
2879a317438SAdrian Chadd 		(void) printf("disk %s: ", d->d_name);
288dab777beSPoul-Henning Kamp 		TAILQ_FOREACH(p, &d->d_part, p_entries)
2899a317438SAdrian Chadd 			(void) printf("%s ", p->p_devname);
2909a317438SAdrian Chadd 		(void) printf("\n");
2919a317438SAdrian Chadd 	}
2929a317438SAdrian Chadd }
2939a317438SAdrian Chadd 
2949a317438SAdrian Chadd 
2959a317438SAdrian Chadd static void
addpart(const char * type,const char * dev,const char * mntpt,const int failok)296c72372c6SKirk McKusick addpart(const char *type, const char *dev, const char *mntpt, const int failok)
2979a317438SAdrian Chadd {
2986cf357bcSUlrich Spörlein 	struct diskentry *d = finddisk(dev);
2999a317438SAdrian Chadd 	struct partentry *p;
3009a317438SAdrian Chadd 
301dab777beSPoul-Henning Kamp 	TAILQ_FOREACH(p, &d->d_part, p_entries)
3026cf357bcSUlrich Spörlein 		if (strcmp(p->p_devname, dev) == 0) {
3036cf357bcSUlrich Spörlein 			warnx("%s in fstab more than once!\n", dev);
3049a317438SAdrian Chadd 			return;
3059a317438SAdrian Chadd 		}
3069a317438SAdrian Chadd 
3079a317438SAdrian Chadd 	p = emalloc(sizeof(*p));
3086cf357bcSUlrich Spörlein 	p->p_devname = estrdup(dev);
3099a317438SAdrian Chadd 	p->p_mntpt = estrdup(mntpt);
3109a317438SAdrian Chadd 	p->p_type = estrdup(type);
311c72372c6SKirk McKusick 	p->p_failok = failok;
3129a317438SAdrian Chadd 
3139a317438SAdrian Chadd 	TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
3149a317438SAdrian Chadd }
3159a317438SAdrian Chadd 
3169a317438SAdrian Chadd 
3179a317438SAdrian Chadd static int
startdisk(struct diskentry * d,int (* checkit)(const char *,const char *,const char *,const char *,pid_t *))318b70cd7eeSWarner Losh startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
3193bbc4438SUlrich Spörlein     const char *, const char *, pid_t *))
3209a317438SAdrian Chadd {
32132ff2662SPoul-Henning Kamp 	struct partentry *p = TAILQ_FIRST(&d->d_part);
3229a317438SAdrian Chadd 	int rv;
3239a317438SAdrian Chadd 
3249a317438SAdrian Chadd 	while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
325a02a0079SKirk McKusick 	    NULL, &d->d_pid)) != 0 && nrun > 0)
3269a317438SAdrian Chadd 		sleep(10);
3279a317438SAdrian Chadd 
3289a317438SAdrian Chadd 	if (rv == 0)
3299a317438SAdrian Chadd 		nrun++;
3309a317438SAdrian Chadd 
3319a317438SAdrian Chadd 	return rv;
3329a317438SAdrian Chadd }
333