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