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 }; 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 829a317438SAdrian Chadd static struct diskentry *finddisk __P((const char *)); 83a02a0079SKirk McKusick static void addpart __P((const char *, const char *, const char *)); 849a317438SAdrian Chadd static int startdisk __P((struct diskentry *, 85a02a0079SKirk McKusick int (*)(const char *, const char *, const char *, char *, pid_t *))); 869a317438SAdrian Chadd static void printpart __P((void)); 879a317438SAdrian Chadd 889a317438SAdrian Chadd int 890af7bca2SPoul-Henning Kamp checkfstab(flags, docheck, checkit) 900af7bca2SPoul-Henning Kamp int flags; 91a02a0079SKirk McKusick int (*docheck) __P((struct fstab *)); 92a02a0079SKirk McKusick int (*checkit) __P((const char *, const char *, const char *, char *, 939a317438SAdrian Chadd pid_t *)); 949a317438SAdrian Chadd { 959a317438SAdrian Chadd struct fstab *fs; 969a317438SAdrian Chadd struct diskentry *d, *nextdisk; 979a317438SAdrian Chadd struct partentry *p; 980af7bca2SPoul-Henning Kamp int ret, pid, retcode, passno, sumstatus, status, nextpass; 999a317438SAdrian Chadd const char *name; 1009a317438SAdrian Chadd 1019a317438SAdrian Chadd TAILQ_INIT(&badh); 1029a317438SAdrian Chadd TAILQ_INIT(&diskh); 1039a317438SAdrian Chadd 1049a317438SAdrian Chadd sumstatus = 0; 1059a317438SAdrian Chadd 1060af7bca2SPoul-Henning Kamp nextpass = 0; 1070af7bca2SPoul-Henning Kamp for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 1080af7bca2SPoul-Henning Kamp if (flags & CHECK_DEBUG) 1090af7bca2SPoul-Henning Kamp printf("pass %d\n", passno); 1100af7bca2SPoul-Henning Kamp 1110af7bca2SPoul-Henning Kamp nextpass = INT_MAX; 1129a317438SAdrian Chadd if (setfsent() == 0) { 1139a317438SAdrian Chadd warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 1149a317438SAdrian Chadd return (8); 1159a317438SAdrian Chadd } 1169a317438SAdrian Chadd while ((fs = getfsent()) != 0) { 1179a317438SAdrian Chadd name = fs->fs_spec; 1180af7bca2SPoul-Henning Kamp if (fs->fs_passno > passno && fs->fs_passno < nextpass) 1190af7bca2SPoul-Henning Kamp nextpass = fs->fs_passno; 1200af7bca2SPoul-Henning Kamp 121a02a0079SKirk McKusick if (passno != fs->fs_passno || (*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 * 2509a317438SAdrian Chadd finddisk(name) 2519a317438SAdrian Chadd const char *name; 2529a317438SAdrian Chadd { 2539a317438SAdrian Chadd const char *p; 2549a317438SAdrian Chadd size_t len = 0; 2559a317438SAdrian Chadd struct diskentry *d; 2569a317438SAdrian Chadd 25728b66787SPoul-Henning Kamp p = strrchr(name, '/'); 25828b66787SPoul-Henning Kamp if (p == NULL) 25928b66787SPoul-Henning Kamp p = name; 26028b66787SPoul-Henning Kamp else 26128b66787SPoul-Henning Kamp p++; 26228b66787SPoul-Henning Kamp for (; *p && !isdigit(*p); p++) 26328b66787SPoul-Henning Kamp continue; 26428b66787SPoul-Henning Kamp for (; *p && isdigit(*p); p++) 26528b66787SPoul-Henning Kamp continue; 26628b66787SPoul-Henning Kamp len = p - name; 26728b66787SPoul-Henning Kamp if (len == 0) 2689a317438SAdrian Chadd len = strlen(name); 2699a317438SAdrian Chadd 270dab777beSPoul-Henning Kamp TAILQ_FOREACH(d, &diskh, d_entries) 2719a317438SAdrian Chadd if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 2729a317438SAdrian Chadd return d; 2739a317438SAdrian Chadd 2749a317438SAdrian Chadd d = emalloc(sizeof(*d)); 2759a317438SAdrian Chadd d->d_name = estrdup(name); 2769a317438SAdrian Chadd d->d_name[len] = '\0'; 2779a317438SAdrian Chadd TAILQ_INIT(&d->d_part); 2789a317438SAdrian Chadd d->d_pid = 0; 2799a317438SAdrian Chadd 2809a317438SAdrian Chadd TAILQ_INSERT_TAIL(&diskh, d, d_entries); 2819a317438SAdrian Chadd ndisks++; 2829a317438SAdrian Chadd 2839a317438SAdrian Chadd return d; 2849a317438SAdrian Chadd } 2859a317438SAdrian Chadd 2869a317438SAdrian Chadd 2879a317438SAdrian Chadd static void 2889a317438SAdrian Chadd printpart() 2899a317438SAdrian Chadd { 2909a317438SAdrian Chadd struct diskentry *d; 2919a317438SAdrian Chadd struct partentry *p; 2929a317438SAdrian Chadd 293dab777beSPoul-Henning Kamp TAILQ_FOREACH(d, &diskh, d_entries) { 2949a317438SAdrian Chadd (void) printf("disk %s: ", d->d_name); 295dab777beSPoul-Henning Kamp TAILQ_FOREACH(p, &d->d_part, p_entries) 2969a317438SAdrian Chadd (void) printf("%s ", p->p_devname); 2979a317438SAdrian Chadd (void) printf("\n"); 2989a317438SAdrian Chadd } 2999a317438SAdrian Chadd } 3009a317438SAdrian Chadd 3019a317438SAdrian Chadd 3029a317438SAdrian Chadd static void 303a02a0079SKirk McKusick addpart(type, devname, mntpt) 3049a317438SAdrian Chadd const char *type, *devname, *mntpt; 3059a317438SAdrian Chadd { 3069a317438SAdrian Chadd struct diskentry *d = finddisk(devname); 3079a317438SAdrian Chadd struct partentry *p; 3089a317438SAdrian Chadd 309dab777beSPoul-Henning Kamp TAILQ_FOREACH(p, &d->d_part, p_entries) 3109a317438SAdrian Chadd if (strcmp(p->p_devname, devname) == 0) { 3119a317438SAdrian Chadd warnx("%s in fstab more than once!\n", devname); 3129a317438SAdrian Chadd return; 3139a317438SAdrian Chadd } 3149a317438SAdrian Chadd 3159a317438SAdrian Chadd p = emalloc(sizeof(*p)); 3169a317438SAdrian Chadd p->p_devname = estrdup(devname); 3179a317438SAdrian Chadd p->p_mntpt = estrdup(mntpt); 3189a317438SAdrian Chadd p->p_type = estrdup(type); 3199a317438SAdrian Chadd 3209a317438SAdrian Chadd TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 3219a317438SAdrian Chadd } 3229a317438SAdrian Chadd 3239a317438SAdrian Chadd 3249a317438SAdrian Chadd static int 3259a317438SAdrian Chadd startdisk(d, checkit) 3269a317438SAdrian Chadd struct diskentry *d; 327a02a0079SKirk McKusick int (*checkit) __P((const char *, const char *, const char *, char *, 3289a317438SAdrian Chadd pid_t *)); 3299a317438SAdrian Chadd { 33032ff2662SPoul-Henning Kamp struct partentry *p = TAILQ_FIRST(&d->d_part); 3319a317438SAdrian Chadd int rv; 3329a317438SAdrian Chadd 3339a317438SAdrian Chadd while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt, 334a02a0079SKirk McKusick NULL, &d->d_pid)) != 0 && nrun > 0) 3359a317438SAdrian Chadd sleep(10); 3369a317438SAdrian Chadd 3379a317438SAdrian Chadd if (rv == 0) 3389a317438SAdrian Chadd nrun++; 3399a317438SAdrian Chadd 3409a317438SAdrian Chadd return rv; 3419a317438SAdrian Chadd } 342