preen.c revision 75289
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 * 3. All advertising materials mentioning features or use of this software 1666869Sadrian * must display the following acknowledgement: 1766869Sadrian * This product includes software developed by the University of 1866869Sadrian * California, Berkeley and its contributors. 1966869Sadrian * 4. Neither the name of the University nor the names of its contributors 2066869Sadrian * may be used to endorse or promote products derived from this software 2166869Sadrian * without specific prior written permission. 2266869Sadrian * 2366869Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2466869Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2566869Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2666869Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2766869Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2866869Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2966869Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3066869Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3166869Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3266869Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3366869Sadrian * SUCH DAMAGE. 3466869Sadrian * 3566869Sadrian * $FreeBSD: head/sbin/fsck/preen.c 75289 2001-04-07 13:24:59Z phk $ 3666869Sadrian */ 3766869Sadrian 3866869Sadrian#include <sys/cdefs.h> 3966869Sadrian#ifndef lint 4066869Sadrian#if 0 4166869Sadrianstatic char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; 4266869Sadrian#else 4366869Sadrian__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); 4466869Sadrian#endif 4566869Sadrian#endif /* not lint */ 4666869Sadrian 4766869Sadrian#include <sys/param.h> 4866869Sadrian#include <sys/stat.h> 4966869Sadrian#include <sys/wait.h> 5066869Sadrian#include <sys/queue.h> 5166869Sadrian 5266869Sadrian#include <err.h> 5366869Sadrian#include <ctype.h> 5466869Sadrian#include <fstab.h> 5566869Sadrian#include <string.h> 5666869Sadrian#include <stdio.h> 5766869Sadrian#include <stdlib.h> 5866869Sadrian#include <unistd.h> 5966869Sadrian 6066869Sadrian#include "fsutil.h" 6166869Sadrian 6266869Sadrianstruct partentry { 6366869Sadrian TAILQ_ENTRY(partentry) p_entries; 6466869Sadrian char *p_devname; /* device name */ 6566869Sadrian char *p_mntpt; /* mount point */ 6666869Sadrian char *p_type; /* filesystem type */ 6766869Sadrian void *p_auxarg; /* auxiliary argument */ 6866869Sadrian}; 6966869Sadrian 7066869SadrianTAILQ_HEAD(part, partentry) badh; 7166869Sadrian 7266869Sadrianstruct diskentry { 7366869Sadrian TAILQ_ENTRY(diskentry) d_entries; 7466869Sadrian char *d_name; /* disk base name */ 7566869Sadrian TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ 7666869Sadrian int d_pid; /* 0 or pid of fsck proc */ 7766869Sadrian}; 7866869Sadrian 7966869SadrianTAILQ_HEAD(disk, diskentry) diskh; 8066869Sadrian 8166869Sadrianstatic int nrun = 0, ndisks = 0; 8266869Sadrian 8366869Sadrianstatic struct diskentry *finddisk __P((const char *)); 8466869Sadrianstatic void addpart __P((const char *, const char *, const char *, void *)); 8566869Sadrianstatic int startdisk __P((struct diskentry *, 8666869Sadrian int (*)(const char *, const char *, const char *, void *, pid_t *))); 8766869Sadrianstatic void printpart __P((void)); 8866869Sadrian 8966869Sadrianint 9075015Sphkcheckfstab(flags, docheck, checkit) 9175015Sphk int flags; 9266869Sadrian void *(*docheck) __P((struct fstab *)); 9366869Sadrian int (*checkit) __P((const char *, const char *, const char *, void *, 9466869Sadrian pid_t *)); 9566869Sadrian{ 9666869Sadrian struct fstab *fs; 9766869Sadrian struct diskentry *d, *nextdisk; 9866869Sadrian struct partentry *p; 9975015Sphk int ret, pid, retcode, passno, sumstatus, status, nextpass; 10066869Sadrian void *auxarg; 10166869Sadrian const char *name; 10266869Sadrian 10366869Sadrian TAILQ_INIT(&badh); 10466869Sadrian TAILQ_INIT(&diskh); 10566869Sadrian 10666869Sadrian sumstatus = 0; 10766869Sadrian 10875015Sphk nextpass = 0; 10975015Sphk for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 11075015Sphk if (flags & CHECK_DEBUG) 11175015Sphk printf("pass %d\n", passno); 11275015Sphk 11375015Sphk nextpass = INT_MAX; 11466869Sadrian if (setfsent() == 0) { 11566869Sadrian warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 11666869Sadrian return (8); 11766869Sadrian } 11866869Sadrian while ((fs = getfsent()) != 0) { 11966869Sadrian if ((auxarg = (*docheck)(fs)) == NULL) 12066869Sadrian continue; 12166869Sadrian 12266869Sadrian name = fs->fs_spec; 12375015Sphk if (fs->fs_passno > passno && fs->fs_passno < nextpass) 12475015Sphk nextpass = fs->fs_passno; 12575015Sphk 12675015Sphk if (passno != fs->fs_passno) 12775015Sphk continue; 12875015Sphk 12966869Sadrian if (flags & CHECK_DEBUG) 13066869Sadrian printf("pass %d, name %s\n", passno, name); 13166869Sadrian 13275015Sphk if ((flags & CHECK_PREEN) == 0 || passno == 1) { 13366869Sadrian if (name == NULL) { 13466869Sadrian if (flags & CHECK_PREEN) 13566869Sadrian return 8; 13666869Sadrian else 13766869Sadrian continue; 13866869Sadrian } 13966869Sadrian sumstatus = (*checkit)(fs->fs_vfstype, 14066869Sadrian name, fs->fs_file, auxarg, NULL); 14166869Sadrian 14266869Sadrian if (sumstatus) 14366869Sadrian return (sumstatus); 14475015Sphk continue; 14575015Sphk } 14675015Sphk if (name == NULL) { 14775015Sphk (void) fprintf(stderr, 14875015Sphk "BAD DISK NAME %s\n", fs->fs_spec); 14975015Sphk sumstatus |= 8; 15075015Sphk continue; 15166869Sadrian } 15275015Sphk addpart(fs->fs_vfstype, name, fs->fs_file, 15375015Sphk auxarg); 15466869Sadrian } 15566869Sadrian 15675015Sphk if ((flags & CHECK_PREEN) == 0 || passno == 1) 15775015Sphk continue; 15866869Sadrian 15975015Sphk if (flags & CHECK_DEBUG) { 16075015Sphk printf("Parallel start\n"); 16175015Sphk printpart(); 16275015Sphk } 16375015Sphk 16475015Sphk TAILQ_FOREACH(nextdisk, &diskh, d_entries) { 16566869Sadrian if ((ret = startdisk(nextdisk, checkit)) != 0) 16666869Sadrian return ret; 16766869Sadrian } 16866869Sadrian 16975015Sphk if (flags & CHECK_DEBUG) 17075015Sphk printf("Parallel wait\n"); 17166869Sadrian while ((pid = wait(&status)) != -1) { 17270413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 17366869Sadrian if (d->d_pid == pid) 17466869Sadrian break; 17566869Sadrian 17666869Sadrian if (d == NULL) { 17766869Sadrian warnx("Unknown pid %d\n", pid); 17866869Sadrian continue; 17966869Sadrian } 18066869Sadrian 18166869Sadrian if (WIFEXITED(status)) 18266869Sadrian retcode = WEXITSTATUS(status); 18366869Sadrian else 18466869Sadrian retcode = 0; 18566869Sadrian 18670413Sphk p = TAILQ_FIRST(&d->d_part); 18766869Sadrian 18866869Sadrian if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) 18966869Sadrian (void) printf("done %s: %s (%s) = 0x%x\n", 19066869Sadrian p->p_type, p->p_devname, p->p_mntpt, 19166869Sadrian status); 19266869Sadrian 19366869Sadrian if (WIFSIGNALED(status)) { 19466869Sadrian (void) fprintf(stderr, 19566869Sadrian "%s: %s (%s): EXITED WITH SIGNAL %d\n", 19666869Sadrian p->p_type, p->p_devname, p->p_mntpt, 19766869Sadrian WTERMSIG(status)); 19866869Sadrian retcode = 8; 19966869Sadrian } 20066869Sadrian 20166869Sadrian TAILQ_REMOVE(&d->d_part, p, p_entries); 20266869Sadrian 20366869Sadrian if (retcode != 0) { 20466869Sadrian TAILQ_INSERT_TAIL(&badh, p, p_entries); 20566869Sadrian sumstatus |= retcode; 20666869Sadrian } else { 20766869Sadrian free(p->p_type); 20866869Sadrian free(p->p_devname); 20966869Sadrian free(p); 21066869Sadrian } 21166869Sadrian d->d_pid = 0; 21266869Sadrian nrun--; 21366869Sadrian 21475015Sphk if (TAILQ_EMPTY(&d->d_part)) { 21575015Sphk TAILQ_REMOVE(&diskh, d, d_entries); 21666869Sadrian ndisks--; 21775289Sphk } else { 21875289Sphk if ((ret = startdisk(d, checkit)) != 0) 21975289Sphk return ret; 22066869Sadrian } 22166869Sadrian } 22275015Sphk if (flags & CHECK_DEBUG) { 22375015Sphk printf("Parallel end\n"); 22475015Sphk printpart(); 22575015Sphk } 22666869Sadrian } 22775015Sphk 22875015Sphk if (!(flags & CHECK_PREEN)) 22975015Sphk return 0; 23075015Sphk 23166869Sadrian if (sumstatus) { 23270522Sphk p = TAILQ_FIRST(&badh); 23366869Sadrian if (p == NULL) 23466869Sadrian return (sumstatus); 23566869Sadrian 23666869Sadrian (void) fprintf(stderr, 23766869Sadrian "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 23870413Sphk TAILQ_NEXT(p, p_entries) ? "S" : "", 23966869Sadrian "UNEXPECTED INCONSISTENCY:"); 24066869Sadrian 24170413Sphk for (; p; p = TAILQ_NEXT(p, p_entries)) 24266869Sadrian (void) fprintf(stderr, 24366869Sadrian "%s: %s (%s)%s", p->p_type, p->p_devname, 24470413Sphk p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); 24566869Sadrian 24666869Sadrian return sumstatus; 24766869Sadrian } 24866869Sadrian (void) endfsent(); 24966869Sadrian return (0); 25066869Sadrian} 25166869Sadrian 25266869Sadrian 25366869Sadrianstatic struct diskentry * 25466869Sadrianfinddisk(name) 25566869Sadrian const char *name; 25666869Sadrian{ 25766869Sadrian const char *p; 25866869Sadrian size_t len = 0; 25966869Sadrian struct diskentry *d; 26066869Sadrian 26170415Sphk p = strrchr(name, '/'); 26270415Sphk if (p == NULL) 26370415Sphk p = name; 26470415Sphk else 26570415Sphk p++; 26670415Sphk for (; *p && !isdigit(*p); p++) 26770415Sphk continue; 26870415Sphk for (; *p && isdigit(*p); p++) 26970415Sphk continue; 27070415Sphk len = p - name; 27170415Sphk if (len == 0) 27266869Sadrian len = strlen(name); 27366869Sadrian 27470413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 27566869Sadrian if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 27666869Sadrian return d; 27766869Sadrian 27866869Sadrian d = emalloc(sizeof(*d)); 27966869Sadrian d->d_name = estrdup(name); 28066869Sadrian d->d_name[len] = '\0'; 28166869Sadrian TAILQ_INIT(&d->d_part); 28266869Sadrian d->d_pid = 0; 28366869Sadrian 28466869Sadrian TAILQ_INSERT_TAIL(&diskh, d, d_entries); 28566869Sadrian ndisks++; 28666869Sadrian 28766869Sadrian return d; 28866869Sadrian} 28966869Sadrian 29066869Sadrian 29166869Sadrianstatic void 29266869Sadrianprintpart() 29366869Sadrian{ 29466869Sadrian struct diskentry *d; 29566869Sadrian struct partentry *p; 29666869Sadrian 29770413Sphk TAILQ_FOREACH(d, &diskh, d_entries) { 29866869Sadrian (void) printf("disk %s: ", d->d_name); 29970413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 30066869Sadrian (void) printf("%s ", p->p_devname); 30166869Sadrian (void) printf("\n"); 30266869Sadrian } 30366869Sadrian} 30466869Sadrian 30566869Sadrian 30666869Sadrianstatic void 30766869Sadrianaddpart(type, devname, mntpt, auxarg) 30866869Sadrian const char *type, *devname, *mntpt; 30966869Sadrian void *auxarg; 31066869Sadrian{ 31166869Sadrian struct diskentry *d = finddisk(devname); 31266869Sadrian struct partentry *p; 31366869Sadrian 31470413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 31566869Sadrian if (strcmp(p->p_devname, devname) == 0) { 31666869Sadrian warnx("%s in fstab more than once!\n", devname); 31766869Sadrian return; 31866869Sadrian } 31966869Sadrian 32066869Sadrian p = emalloc(sizeof(*p)); 32166869Sadrian p->p_devname = estrdup(devname); 32266869Sadrian p->p_mntpt = estrdup(mntpt); 32366869Sadrian p->p_type = estrdup(type); 32466869Sadrian p->p_auxarg = auxarg; 32566869Sadrian 32666869Sadrian TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 32766869Sadrian} 32866869Sadrian 32966869Sadrian 33066869Sadrianstatic int 33166869Sadrianstartdisk(d, checkit) 33266869Sadrian struct diskentry *d; 33366869Sadrian int (*checkit) __P((const char *, const char *, const char *, void *, 33466869Sadrian pid_t *)); 33566869Sadrian{ 33670522Sphk struct partentry *p = TAILQ_FIRST(&d->d_part); 33766869Sadrian int rv; 33866869Sadrian 33966869Sadrian while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt, 34066869Sadrian p->p_auxarg, &d->d_pid)) != 0 && nrun > 0) 34166869Sadrian sleep(10); 34266869Sadrian 34366869Sadrian if (rv == 0) 34466869Sadrian nrun++; 34566869Sadrian 34666869Sadrian return rv; 34766869Sadrian} 348