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