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