preen.c revision 92839
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 92839 2002-03-20 22:57:10Z imp $ 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}; 6866869Sadrian 6966869SadrianTAILQ_HEAD(part, partentry) badh; 7066869Sadrian 7166869Sadrianstruct diskentry { 7266869Sadrian TAILQ_ENTRY(diskentry) d_entries; 7366869Sadrian char *d_name; /* disk base name */ 7466869Sadrian TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ 7566869Sadrian int d_pid; /* 0 or pid of fsck proc */ 7666869Sadrian}; 7766869Sadrian 7866869SadrianTAILQ_HEAD(disk, diskentry) diskh; 7966869Sadrian 8066869Sadrianstatic int nrun = 0, ndisks = 0; 8166869Sadrian 8292839Simpstatic struct diskentry *finddisk(const char *); 8392839Simpstatic void addpart(const char *, const char *, const char *); 8492839Simpstatic int startdisk(struct diskentry *, 8592839Simp int (*)(const char *, const char *, const char *, char *, pid_t *)); 8692839Simpstatic void printpart(void); 8766869Sadrian 8866869Sadrianint 8992839Simpcheckfstab(int flags, int (*docheck)(struct fstab *), 9092839Simp int (*checkit)(const char *, const char *, const char *, char *, pid_t *)) 9166869Sadrian{ 9266869Sadrian struct fstab *fs; 9366869Sadrian struct diskentry *d, *nextdisk; 9466869Sadrian struct partentry *p; 9575015Sphk int ret, pid, retcode, passno, sumstatus, status, nextpass; 9666869Sadrian const char *name; 9766869Sadrian 9866869Sadrian TAILQ_INIT(&badh); 9966869Sadrian TAILQ_INIT(&diskh); 10066869Sadrian 10166869Sadrian sumstatus = 0; 10266869Sadrian 10375015Sphk nextpass = 0; 10475015Sphk for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 10575015Sphk if (flags & CHECK_DEBUG) 10675015Sphk printf("pass %d\n", passno); 10775015Sphk 10875015Sphk nextpass = INT_MAX; 10966869Sadrian if (setfsent() == 0) { 11066869Sadrian warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 11166869Sadrian return (8); 11266869Sadrian } 11366869Sadrian while ((fs = getfsent()) != 0) { 11466869Sadrian name = fs->fs_spec; 11575015Sphk if (fs->fs_passno > passno && fs->fs_passno < nextpass) 11675015Sphk nextpass = fs->fs_passno; 11775015Sphk 11875936Smckusick if (passno != fs->fs_passno || (*docheck)(fs) == 0) 11975015Sphk continue; 12075015Sphk 12166869Sadrian if (flags & CHECK_DEBUG) 12266869Sadrian printf("pass %d, name %s\n", passno, name); 12366869Sadrian 12475936Smckusick if ((flags & CHECK_PREEN) == 0 || passno == 1 || 12575936Smckusick (flags & DO_BACKGRD) != 0) { 12666869Sadrian if (name == NULL) { 12766869Sadrian if (flags & CHECK_PREEN) 12866869Sadrian return 8; 12966869Sadrian else 13066869Sadrian continue; 13166869Sadrian } 13266869Sadrian sumstatus = (*checkit)(fs->fs_vfstype, 13375936Smckusick name, fs->fs_file, NULL, NULL); 13466869Sadrian 13566869Sadrian if (sumstatus) 13666869Sadrian return (sumstatus); 13775015Sphk continue; 13875015Sphk } 13975015Sphk if (name == NULL) { 14075015Sphk (void) fprintf(stderr, 14175015Sphk "BAD DISK NAME %s\n", fs->fs_spec); 14275015Sphk sumstatus |= 8; 14375015Sphk continue; 14466869Sadrian } 14575936Smckusick addpart(fs->fs_vfstype, name, fs->fs_file); 14666869Sadrian } 14766869Sadrian 14875936Smckusick if ((flags & CHECK_PREEN) == 0 || passno == 1 || 14975936Smckusick (flags & DO_BACKGRD) != 0) 15075015Sphk continue; 15166869Sadrian 15275015Sphk if (flags & CHECK_DEBUG) { 15375015Sphk printf("Parallel start\n"); 15475015Sphk printpart(); 15575015Sphk } 15675015Sphk 15775015Sphk TAILQ_FOREACH(nextdisk, &diskh, d_entries) { 15866869Sadrian if ((ret = startdisk(nextdisk, checkit)) != 0) 15966869Sadrian return ret; 16066869Sadrian } 16166869Sadrian 16275015Sphk if (flags & CHECK_DEBUG) 16375015Sphk printf("Parallel wait\n"); 16466869Sadrian while ((pid = wait(&status)) != -1) { 16570413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 16666869Sadrian if (d->d_pid == pid) 16766869Sadrian break; 16866869Sadrian 16966869Sadrian if (d == NULL) { 17066869Sadrian warnx("Unknown pid %d\n", pid); 17166869Sadrian continue; 17266869Sadrian } 17366869Sadrian 17466869Sadrian if (WIFEXITED(status)) 17566869Sadrian retcode = WEXITSTATUS(status); 17666869Sadrian else 17766869Sadrian retcode = 0; 17866869Sadrian 17970413Sphk p = TAILQ_FIRST(&d->d_part); 18066869Sadrian 18166869Sadrian if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) 18266869Sadrian (void) printf("done %s: %s (%s) = 0x%x\n", 18366869Sadrian p->p_type, p->p_devname, p->p_mntpt, 18466869Sadrian status); 18566869Sadrian 18666869Sadrian if (WIFSIGNALED(status)) { 18766869Sadrian (void) fprintf(stderr, 18866869Sadrian "%s: %s (%s): EXITED WITH SIGNAL %d\n", 18966869Sadrian p->p_type, p->p_devname, p->p_mntpt, 19066869Sadrian WTERMSIG(status)); 19166869Sadrian retcode = 8; 19266869Sadrian } 19366869Sadrian 19466869Sadrian TAILQ_REMOVE(&d->d_part, p, p_entries); 19566869Sadrian 19666869Sadrian if (retcode != 0) { 19766869Sadrian TAILQ_INSERT_TAIL(&badh, p, p_entries); 19866869Sadrian sumstatus |= retcode; 19966869Sadrian } else { 20066869Sadrian free(p->p_type); 20166869Sadrian free(p->p_devname); 20266869Sadrian free(p); 20366869Sadrian } 20466869Sadrian d->d_pid = 0; 20566869Sadrian nrun--; 20666869Sadrian 20775015Sphk if (TAILQ_EMPTY(&d->d_part)) { 20875015Sphk TAILQ_REMOVE(&diskh, d, d_entries); 20966869Sadrian ndisks--; 21075289Sphk } else { 21175289Sphk if ((ret = startdisk(d, checkit)) != 0) 21275289Sphk return ret; 21366869Sadrian } 21466869Sadrian } 21575015Sphk if (flags & CHECK_DEBUG) { 21675015Sphk printf("Parallel end\n"); 21775015Sphk printpart(); 21875015Sphk } 21966869Sadrian } 22075015Sphk 22175015Sphk if (!(flags & CHECK_PREEN)) 22275015Sphk return 0; 22375015Sphk 22466869Sadrian if (sumstatus) { 22570522Sphk p = TAILQ_FIRST(&badh); 22666869Sadrian if (p == NULL) 22766869Sadrian return (sumstatus); 22866869Sadrian 22966869Sadrian (void) fprintf(stderr, 23066869Sadrian "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 23170413Sphk TAILQ_NEXT(p, p_entries) ? "S" : "", 23266869Sadrian "UNEXPECTED INCONSISTENCY:"); 23366869Sadrian 23470413Sphk for (; p; p = TAILQ_NEXT(p, p_entries)) 23566869Sadrian (void) fprintf(stderr, 23666869Sadrian "%s: %s (%s)%s", p->p_type, p->p_devname, 23770413Sphk p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); 23866869Sadrian 23966869Sadrian return sumstatus; 24066869Sadrian } 24166869Sadrian (void) endfsent(); 24266869Sadrian return (0); 24366869Sadrian} 24466869Sadrian 24566869Sadrian 24666869Sadrianstatic struct diskentry * 24792839Simpfinddisk(const char *name) 24866869Sadrian{ 24966869Sadrian const char *p; 25066869Sadrian size_t len = 0; 25166869Sadrian struct diskentry *d; 25266869Sadrian 25370415Sphk p = strrchr(name, '/'); 25470415Sphk if (p == NULL) 25570415Sphk p = name; 25670415Sphk else 25770415Sphk p++; 25870415Sphk for (; *p && !isdigit(*p); p++) 25970415Sphk continue; 26070415Sphk for (; *p && isdigit(*p); p++) 26170415Sphk continue; 26270415Sphk len = p - name; 26370415Sphk if (len == 0) 26466869Sadrian len = strlen(name); 26566869Sadrian 26670413Sphk TAILQ_FOREACH(d, &diskh, d_entries) 26766869Sadrian if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 26866869Sadrian return d; 26966869Sadrian 27066869Sadrian d = emalloc(sizeof(*d)); 27166869Sadrian d->d_name = estrdup(name); 27266869Sadrian d->d_name[len] = '\0'; 27366869Sadrian TAILQ_INIT(&d->d_part); 27466869Sadrian d->d_pid = 0; 27566869Sadrian 27666869Sadrian TAILQ_INSERT_TAIL(&diskh, d, d_entries); 27766869Sadrian ndisks++; 27866869Sadrian 27966869Sadrian return d; 28066869Sadrian} 28166869Sadrian 28266869Sadrian 28366869Sadrianstatic void 28492839Simpprintpart(void) 28566869Sadrian{ 28666869Sadrian struct diskentry *d; 28766869Sadrian struct partentry *p; 28866869Sadrian 28970413Sphk TAILQ_FOREACH(d, &diskh, d_entries) { 29066869Sadrian (void) printf("disk %s: ", d->d_name); 29170413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 29266869Sadrian (void) printf("%s ", p->p_devname); 29366869Sadrian (void) printf("\n"); 29466869Sadrian } 29566869Sadrian} 29666869Sadrian 29766869Sadrian 29866869Sadrianstatic void 29992839Simpaddpart(const char *type, const char *devname, const char *mntpt) 30066869Sadrian{ 30166869Sadrian struct diskentry *d = finddisk(devname); 30266869Sadrian struct partentry *p; 30366869Sadrian 30470413Sphk TAILQ_FOREACH(p, &d->d_part, p_entries) 30566869Sadrian if (strcmp(p->p_devname, devname) == 0) { 30666869Sadrian warnx("%s in fstab more than once!\n", devname); 30766869Sadrian return; 30866869Sadrian } 30966869Sadrian 31066869Sadrian p = emalloc(sizeof(*p)); 31166869Sadrian p->p_devname = estrdup(devname); 31266869Sadrian p->p_mntpt = estrdup(mntpt); 31366869Sadrian p->p_type = estrdup(type); 31466869Sadrian 31566869Sadrian TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 31666869Sadrian} 31766869Sadrian 31866869Sadrian 31966869Sadrianstatic int 32092839Simpstartdisk(struct diskentry *d, int (*checkit)(const char *, const char *, 32192839Simp const char *, char *, pid_t *)) 32266869Sadrian{ 32370522Sphk struct partentry *p = TAILQ_FIRST(&d->d_part); 32466869Sadrian int rv; 32566869Sadrian 32666869Sadrian while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt, 32775936Smckusick NULL, &d->d_pid)) != 0 && nrun > 0) 32866869Sadrian sleep(10); 32966869Sadrian 33066869Sadrian if (rv == 0) 33166869Sadrian nrun++; 33266869Sadrian 33366869Sadrian return rv; 33466869Sadrian} 335