166869Sadrian/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */ 266869Sadrian 366869Sadrian/* 466869Sadrian * Copyright (c) 1990, 1993 566869Sadrian * The Regents of the University of California. All rights reserved. 666869Sadrian * 766869Sadrian * Redistribution and use in source and binary forms, with or without 866869Sadrian * modification, are permitted provided that the following conditions 966869Sadrian * are met: 1066869Sadrian * 1. Redistributions of source code must retain the above copyright 1166869Sadrian * notice, this list of conditions and the following disclaimer. 1266869Sadrian * 2. Redistributions in binary form must reproduce the above copyright 1366869Sadrian * notice, this list of conditions and the following disclaimer in the 1466869Sadrian * documentation and/or other materials provided with the distribution. 1566869Sadrian * 4. Neither the name of the University nor the names of its contributors 1666869Sadrian * may be used to endorse or promote products derived from this software 1766869Sadrian * without specific prior written permission. 1866869Sadrian * 1966869Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2066869Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2166869Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2266869Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2366869Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2466869Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2566869Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2666869Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2766869Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2866869Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2966869Sadrian * SUCH DAMAGE. 3066869Sadrian * 3166869Sadrian * $FreeBSD$ 3266869Sadrian */ 3366869Sadrian 3466869Sadrian#include <sys/cdefs.h> 3566869Sadrian#ifndef lint 3666869Sadrian#if 0 3766869Sadrianstatic char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; 3866869Sadrian#else 3966869Sadrian__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); 4066869Sadrian#endif 4166869Sadrian#endif /* not lint */ 4266869Sadrian 4366869Sadrian#include <sys/param.h> 4466869Sadrian#include <sys/stat.h> 4566869Sadrian#include <sys/wait.h> 4666869Sadrian#include <sys/queue.h> 4766869Sadrian 4866869Sadrian#include <err.h> 4966869Sadrian#include <ctype.h> 5066869Sadrian#include <fstab.h> 5166869Sadrian#include <string.h> 5266869Sadrian#include <stdio.h> 5366869Sadrian#include <stdlib.h> 5466869Sadrian#include <unistd.h> 5566869Sadrian 5666869Sadrian#include "fsutil.h" 5766869Sadrian 5866869Sadrianstruct partentry { 5966869Sadrian TAILQ_ENTRY(partentry) p_entries; 6066869Sadrian char *p_devname; /* device name */ 6166869Sadrian char *p_mntpt; /* mount point */ 62102231Strhodes char *p_type; /* file system type */ 6366869Sadrian}; 6466869Sadrian 65227081Sedstatic TAILQ_HEAD(part, partentry) badh; 6666869Sadrian 6766869Sadrianstruct diskentry { 6866869Sadrian TAILQ_ENTRY(diskentry) d_entries; 6966869Sadrian char *d_name; /* disk base name */ 7066869Sadrian TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ 7166869Sadrian int d_pid; /* 0 or pid of fsck proc */ 7266869Sadrian}; 7366869Sadrian 74227081Sedstatic TAILQ_HEAD(disk, diskentry) diskh; 7566869Sadrian 7666869Sadrianstatic int nrun = 0, ndisks = 0; 7766869Sadrian 7892839Simpstatic struct diskentry *finddisk(const char *); 7992839Simpstatic void addpart(const char *, const char *, const char *); 8092839Simpstatic int startdisk(struct diskentry *, 81241807Suqs int (*)(const char *, const char *, const char *, const char *, pid_t *)); 8292839Simpstatic void printpart(void); 8366869Sadrian 8466869Sadrianint 8592839Simpcheckfstab(int flags, int (*docheck)(struct fstab *), 86241807Suqs int (*checkit)(const char *, const char *, const char *, const char *, pid_t *)) 8766869Sadrian{ 8866869Sadrian struct fstab *fs; 8966869Sadrian struct diskentry *d, *nextdisk; 9066869Sadrian struct partentry *p; 9175015Sphk int ret, pid, retcode, passno, sumstatus, status, nextpass; 9266869Sadrian const char *name; 9366869Sadrian 9466869Sadrian TAILQ_INIT(&badh); 9566869Sadrian TAILQ_INIT(&diskh); 9666869Sadrian 9766869Sadrian sumstatus = 0; 9866869Sadrian 9975015Sphk nextpass = 0; 10075015Sphk for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 10175015Sphk if (flags & CHECK_DEBUG) 10275015Sphk printf("pass %d\n", passno); 10375015Sphk 10475015Sphk nextpass = INT_MAX; 10566869Sadrian if (setfsent() == 0) { 10666869Sadrian warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 10766869Sadrian return (8); 10866869Sadrian } 10966869Sadrian while ((fs = getfsent()) != 0) { 11066869Sadrian name = fs->fs_spec; 11175015Sphk if (fs->fs_passno > passno && fs->fs_passno < nextpass) 11275015Sphk nextpass = fs->fs_passno; 11375015Sphk 114107987Sphk if (passno != fs->fs_passno) 11575015Sphk continue; 11675015Sphk 117107987Sphk if ((*docheck)(fs) == 0) 118107987Sphk continue; 119107987Sphk 12066869Sadrian if (flags & CHECK_DEBUG) 12166869Sadrian printf("pass %d, name %s\n", passno, name); 12266869Sadrian 12375936Smckusick if ((flags & CHECK_PREEN) == 0 || passno == 1 || 12475936Smckusick (flags & DO_BACKGRD) != 0) { 12566869Sadrian if (name == NULL) { 12666869Sadrian if (flags & CHECK_PREEN) 12766869Sadrian return 8; 12866869Sadrian else 12966869Sadrian continue; 13066869Sadrian } 13166869Sadrian sumstatus = (*checkit)(fs->fs_vfstype, 13275936Smckusick name, fs->fs_file, NULL, NULL); 13366869Sadrian 13466869Sadrian if (sumstatus) 13566869Sadrian return (sumstatus); 13675015Sphk continue; 13775015Sphk } 13875015Sphk if (name == NULL) { 13975015Sphk (void) fprintf(stderr, 14075015Sphk "BAD DISK NAME %s\n", fs->fs_spec); 14175015Sphk sumstatus |= 8; 14275015Sphk continue; 14366869Sadrian } 14475936Smckusick addpart(fs->fs_vfstype, name, fs->fs_file); 14566869Sadrian } 14666869Sadrian 14775936Smckusick if ((flags & CHECK_PREEN) == 0 || passno == 1 || 14875936Smckusick (flags & DO_BACKGRD) != 0) 14975015Sphk continue; 15066869Sadrian 15175015Sphk if (flags & CHECK_DEBUG) { 15275015Sphk printf("Parallel start\n"); 15375015Sphk printpart(); 15475015Sphk } 15575015Sphk 15675015Sphk TAILQ_FOREACH(nextdisk, &diskh, d_entries) { 15766869Sadrian if ((ret = startdisk(nextdisk, checkit)) != 0) 15866869Sadrian return ret; 15966869Sadrian } 16066869Sadrian 16175015Sphk if (flags & CHECK_DEBUG) 16275015Sphk printf("Parallel wait\n"); 16366869Sadrian while ((pid = wait(&status)) != -1) { 16470413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 16566869Sadrian if (d->d_pid == pid) 16666869Sadrian break; 16766869Sadrian 16866869Sadrian if (d == NULL) { 16966869Sadrian warnx("Unknown pid %d\n", pid); 17066869Sadrian continue; 17166869Sadrian } 17266869Sadrian 17366869Sadrian if (WIFEXITED(status)) 17466869Sadrian retcode = WEXITSTATUS(status); 17566869Sadrian else 17666869Sadrian retcode = 0; 17766869Sadrian 17870413Sphk p = TAILQ_FIRST(&d->d_part); 17966869Sadrian 18066869Sadrian if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) 18166869Sadrian (void) printf("done %s: %s (%s) = 0x%x\n", 18266869Sadrian p->p_type, p->p_devname, p->p_mntpt, 18366869Sadrian status); 18466869Sadrian 18566869Sadrian if (WIFSIGNALED(status)) { 18666869Sadrian (void) fprintf(stderr, 18766869Sadrian "%s: %s (%s): EXITED WITH SIGNAL %d\n", 18866869Sadrian p->p_type, p->p_devname, p->p_mntpt, 18966869Sadrian WTERMSIG(status)); 19066869Sadrian retcode = 8; 19166869Sadrian } 19266869Sadrian 19366869Sadrian TAILQ_REMOVE(&d->d_part, p, p_entries); 19466869Sadrian 19566869Sadrian if (retcode != 0) { 19666869Sadrian TAILQ_INSERT_TAIL(&badh, p, p_entries); 19766869Sadrian sumstatus |= retcode; 19866869Sadrian } else { 19966869Sadrian free(p->p_type); 20066869Sadrian free(p->p_devname); 20166869Sadrian free(p); 20266869Sadrian } 20366869Sadrian d->d_pid = 0; 20466869Sadrian nrun--; 20566869Sadrian 20675015Sphk if (TAILQ_EMPTY(&d->d_part)) { 20775015Sphk TAILQ_REMOVE(&diskh, d, d_entries); 20866869Sadrian ndisks--; 20975289Sphk } else { 21075289Sphk if ((ret = startdisk(d, checkit)) != 0) 21175289Sphk return ret; 21266869Sadrian } 21366869Sadrian } 21475015Sphk if (flags & CHECK_DEBUG) { 21575015Sphk printf("Parallel end\n"); 21675015Sphk printpart(); 21775015Sphk } 21866869Sadrian } 21975015Sphk 22075015Sphk if (!(flags & CHECK_PREEN)) 22175015Sphk return 0; 22275015Sphk 22366869Sadrian if (sumstatus) { 22470522Sphk p = TAILQ_FIRST(&badh); 22566869Sadrian if (p == NULL) 22666869Sadrian return (sumstatus); 22766869Sadrian 22866869Sadrian (void) fprintf(stderr, 22966869Sadrian "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 23070413Sphk TAILQ_NEXT(p, p_entries) ? "S" : "", 23166869Sadrian "UNEXPECTED INCONSISTENCY:"); 23266869Sadrian 23370413Sphk for (; p; p = TAILQ_NEXT(p, p_entries)) 23466869Sadrian (void) fprintf(stderr, 23566869Sadrian "%s: %s (%s)%s", p->p_type, p->p_devname, 23670413Sphk p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); 23766869Sadrian 23866869Sadrian return sumstatus; 23966869Sadrian } 24066869Sadrian (void) endfsent(); 24166869Sadrian return (0); 24266869Sadrian} 24366869Sadrian 24466869Sadrian 24566869Sadrianstatic struct diskentry * 24692839Simpfinddisk(const char *name) 24766869Sadrian{ 24866869Sadrian const char *p; 24966869Sadrian size_t len = 0; 25066869Sadrian struct diskentry *d; 25166869Sadrian 25270415Sphk p = strrchr(name, '/'); 25370415Sphk if (p == NULL) 25470415Sphk p = name; 25570415Sphk else 25670415Sphk p++; 25770415Sphk for (; *p && !isdigit(*p); p++) 25870415Sphk continue; 25970415Sphk for (; *p && isdigit(*p); p++) 26070415Sphk continue; 26170415Sphk len = p - name; 26270415Sphk if (len == 0) 26366869Sadrian len = strlen(name); 26466869Sadrian 26570413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 26666869Sadrian if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 26766869Sadrian return d; 26866869Sadrian 26966869Sadrian d = emalloc(sizeof(*d)); 27066869Sadrian d->d_name = estrdup(name); 27166869Sadrian d->d_name[len] = '\0'; 27266869Sadrian TAILQ_INIT(&d->d_part); 27366869Sadrian d->d_pid = 0; 27466869Sadrian 27566869Sadrian TAILQ_INSERT_TAIL(&diskh, d, d_entries); 27666869Sadrian ndisks++; 27766869Sadrian 27866869Sadrian return d; 27966869Sadrian} 28066869Sadrian 28166869Sadrian 28266869Sadrianstatic void 28392839Simpprintpart(void) 28466869Sadrian{ 28566869Sadrian struct diskentry *d; 28666869Sadrian struct partentry *p; 28766869Sadrian 28870413Sphk TAILQ_FOREACH(d, &diskh, d_entries) { 28966869Sadrian (void) printf("disk %s: ", d->d_name); 29070413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 29166869Sadrian (void) printf("%s ", p->p_devname); 29266869Sadrian (void) printf("\n"); 29366869Sadrian } 29466869Sadrian} 29566869Sadrian 29666869Sadrian 29766869Sadrianstatic void 298241806Suqsaddpart(const char *type, const char *dev, const char *mntpt) 29966869Sadrian{ 300241806Suqs struct diskentry *d = finddisk(dev); 30166869Sadrian struct partentry *p; 30266869Sadrian 30370413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 304241806Suqs if (strcmp(p->p_devname, dev) == 0) { 305241806Suqs warnx("%s in fstab more than once!\n", dev); 30666869Sadrian return; 30766869Sadrian } 30866869Sadrian 30966869Sadrian p = emalloc(sizeof(*p)); 310241806Suqs p->p_devname = estrdup(dev); 31166869Sadrian p->p_mntpt = estrdup(mntpt); 31266869Sadrian p->p_type = estrdup(type); 31366869Sadrian 31466869Sadrian TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 31566869Sadrian} 31666869Sadrian 31766869Sadrian 31866869Sadrianstatic int 31992839Simpstartdisk(struct diskentry *d, int (*checkit)(const char *, const char *, 320241807Suqs const char *, const char *, pid_t *)) 32166869Sadrian{ 32270522Sphk struct partentry *p = TAILQ_FIRST(&d->d_part); 32366869Sadrian int rv; 32466869Sadrian 32566869Sadrian while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt, 32675936Smckusick NULL, &d->d_pid)) != 0 && nrun > 0) 32766869Sadrian sleep(10); 32866869Sadrian 32966869Sadrian if (rv == 0) 33066869Sadrian nrun++; 33166869Sadrian 33266869Sadrian return rv; 33366869Sadrian} 334