preen.c revision 175678
1219560Savg/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */ 2219560Savg 3219560Savg/* 4219560Savg * Copyright (c) 1990, 1993 5219560Savg * The Regents of the University of California. All rights reserved. 6255676Srdivacky * 7219560Savg * Redistribution and use in source and binary forms, with or without 8219560Savg * modification, are permitted provided that the following conditions 9219560Savg * are met: 10219560Savg * 1. Redistributions of source code must retain the above copyright 11219560Savg * notice, this list of conditions and the following disclaimer. 12219560Savg * 2. Redistributions in binary form must reproduce the above copyright 13219560Savg * notice, this list of conditions and the following disclaimer in the 14219560Savg * documentation and/or other materials provided with the distribution. 15219560Savg * 4. Neither the name of the University nor the names of its contributors 16219560Savg * may be used to endorse or promote products derived from this software 17219560Savg * without specific prior written permission. 18219560Savg * 19219560Savg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20219560Savg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21219560Savg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22219560Savg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23219560Savg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24219560Savg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25219560Savg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26219560Savg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27219560Savg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28219560Savg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29219560Savg * SUCH DAMAGE. 30219560Savg * 31219560Savg * $FreeBSD: head/sbin/quotacheck/preen.c 175678 2008-01-26 12:03:26Z mpp $ 32219560Savg */ 33219560Savg 34219560Savg#include <sys/cdefs.h> 35219560Savg#ifndef lint 36219560Savg#if 0 37219560Savgstatic char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; 38219560Savg#else 39219560Savg__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); 40219560Savg#endif 41219560Savg#endif /* not lint */ 42219560Savg 43219560Savg#include <sys/param.h> 44219560Savg#include <sys/stat.h> 45219560Savg#include <sys/wait.h> 46219560Savg#include <sys/queue.h> 47219560Savg 48219560Savg#include <err.h> 49219560Savg#include <ctype.h> 50219560Savg#include <fstab.h> 51219560Savg#include <string.h> 52219560Savg#include <stdio.h> 53219560Savg#include <stdlib.h> 54219560Savg#include <unistd.h> 55219560Savg 56219560Savg#include "quotacheck.h" 57219560Savg 58219560Savgstruct partentry { 59219560Savg TAILQ_ENTRY(partentry) p_entries; 60219560Savg char *p_devname; /* device name */ 61219560Savg char *p_mntpt; /* mount point */ 62219560Savg char *p_type; /* file system type */ 63219560Savg struct quotaname *p_quota; /* quota file info ptr */ 64219560Savg}; 65219560Savg 66219560SavgTAILQ_HEAD(part, partentry) badh; 67219560Savg 68219560Savgstruct diskentry { 69219560Savg TAILQ_ENTRY(diskentry) d_entries; 70219560Savg char *d_name; /* disk base name */ 71219560Savg TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ 72219560Savg int d_pid; /* 0 or pid of fsck proc */ 73219560Savg}; 74219560Savg 75219560SavgTAILQ_HEAD(disk, diskentry) diskh; 76219560Savg 77219560Savgstatic struct diskentry *finddisk(const char *); 78219560Savgstatic void addpart(const char *, const char *, const char *, 79219560Savg struct quotaname *); 80219560Savgstatic int startdisk(struct diskentry *); 81219560Savgextern void *emalloc(size_t); 82219560Savgextern char *estrdup(const char *); 83219560Savg 84219560Savgint 85219560Savgcheckfstab() 86219560Savg{ 87219560Savg struct fstab *fs; 88219560Savg struct diskentry *d, *nextdisk; 89219560Savg struct partentry *p; 90219560Savg int ret, pid, retcode, passno, sumstatus, status, nextpass; 91219560Savg char *name; 92219560Savg struct quotaname *qnp; 93219560Savg 94219560Savg TAILQ_INIT(&badh); 95219560Savg TAILQ_INIT(&diskh); 96219560Savg 97219560Savg sumstatus = 0; 98219560Savg 99219560Savg nextpass = 0; 100219560Savg for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 101219560Savg nextpass = INT_MAX; 102219560Savg if (setfsent() == 0) { 103219560Savg warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 104219560Savg return (8); 105219560Savg } 106219560Savg while ((fs = getfsent()) != 0) { 107219560Savg name = fs->fs_spec; 108219560Savg if (fs->fs_passno > passno && fs->fs_passno < nextpass) 109219560Savg nextpass = fs->fs_passno; 110219560Savg 111219560Savg if (passno != fs->fs_passno) 112219560Savg continue; 113219560Savg 114219560Savg if ((qnp = needchk(fs)) == NULL) 115219560Savg continue; 116219560Savg 117219560Savg if (passno == 1) { 118219560Savg sumstatus = chkquota(name, fs->fs_file, qnp); 119219560Savg 120219560Savg if (sumstatus) 121219560Savg return (sumstatus); 122219560Savg continue; 123219560Savg } 124219560Savg if (name == NULL) { 125219560Savg (void) fprintf(stderr, 126219560Savg "BAD DISK NAME %s\n", fs->fs_spec); 127219560Savg sumstatus |= 8; 128219560Savg continue; 129219560Savg } 130219560Savg addpart(fs->fs_vfstype, name, fs->fs_file, qnp); 131219560Savg } 132219560Savg 133219560Savg if (passno == 1) 134219560Savg continue; 135219560Savg 136219560Savg TAILQ_FOREACH(nextdisk, &diskh, d_entries) { 137219560Savg if ((ret = startdisk(nextdisk)) != 0) 138219560Savg return ret; 139219560Savg } 140219560Savg 141219560Savg while ((pid = wait(&status)) != -1) { 142219560Savg TAILQ_FOREACH(d, &diskh, d_entries) 143219560Savg if (d->d_pid == pid) 144219560Savg break; 145219560Savg 146219560Savg if (d == NULL) { 147219560Savg warnx("Unknown pid %d\n", pid); 148219560Savg continue; 149219560Savg } 150219560Savg 151219560Savg if (WIFEXITED(status)) 152219560Savg retcode = WEXITSTATUS(status); 153219560Savg else 154219560Savg retcode = 0; 155219560Savg 156219560Savg p = TAILQ_FIRST(&d->d_part); 157219560Savg 158219560Savg if (WIFSIGNALED(status)) { 159219560Savg (void) fprintf(stderr, 160219560Savg "%s: %s (%s): EXITED WITH SIGNAL %d\n", 161219560Savg p->p_type, p->p_devname, p->p_mntpt, 162219560Savg WTERMSIG(status)); 163219560Savg retcode = 8; 164219560Savg } 165219560Savg 166219560Savg TAILQ_REMOVE(&d->d_part, p, p_entries); 167219560Savg 168219560Savg if (retcode != 0) { 169219560Savg TAILQ_INSERT_TAIL(&badh, p, p_entries); 170219560Savg sumstatus |= retcode; 171219560Savg } else { 172219560Savg free(p->p_type); 173219560Savg free(p->p_devname); 174219560Savg free(p); 175219560Savg } 176219560Savg d->d_pid = 0; 177219560Savg 178219560Savg if (TAILQ_EMPTY(&d->d_part)) { 179219560Savg TAILQ_REMOVE(&diskh, d, d_entries); 180219560Savg } else { 181219560Savg if ((ret = startdisk(d)) != 0) 182219560Savg return ret; 183219560Savg } 184219560Savg } 185219560Savg } 186219560Savg 187219560Savg if (sumstatus) { 188219560Savg p = TAILQ_FIRST(&badh); 189219560Savg if (p == NULL) 190219560Savg return (sumstatus); 191219560Savg 192219560Savg (void) fprintf(stderr, 193219560Savg "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 194219560Savg TAILQ_NEXT(p, p_entries) ? "S" : "", 195219560Savg "UNEXPECTED INCONSISTENCY:"); 196219560Savg 197219560Savg for (; p; p = TAILQ_NEXT(p, p_entries)) 198219560Savg (void) fprintf(stderr, 199219560Savg "%s: %s (%s)%s", p->p_type, p->p_devname, 200219560Savg p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); 201219560Savg 202219560Savg return sumstatus; 203219560Savg } 204219560Savg (void) endfsent(); 205219560Savg return (0); 206219560Savg} 207219560Savg 208219560Savg 209219560Savgstatic struct diskentry * 210219560Savgfinddisk(const char *name) 211219560Savg{ 212219560Savg const char *p; 213219560Savg size_t len = 0; 214219560Savg struct diskentry *d; 215219560Savg 216219560Savg p = strrchr(name, '/'); 217219560Savg if (p == NULL) 218219560Savg p = name; 219219560Savg else 220219560Savg p++; 221219560Savg for (; *p && !isdigit(*p); p++) 222219560Savg continue; 223219560Savg for (; *p && isdigit(*p); p++) 224219560Savg continue; 225219560Savg len = p - name; 226219560Savg if (len == 0) 227219560Savg len = strlen(name); 228219560Savg 229219560Savg TAILQ_FOREACH(d, &diskh, d_entries) 230219560Savg if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 231219560Savg return d; 232219560Savg 233219560Savg d = emalloc(sizeof(*d)); 234219560Savg d->d_name = estrdup(name); 235219560Savg d->d_name[len] = '\0'; 236219560Savg TAILQ_INIT(&d->d_part); 237219560Savg d->d_pid = 0; 238219560Savg 239219560Savg TAILQ_INSERT_TAIL(&diskh, d, d_entries); 240219560Savg 241219560Savg return d; 242219560Savg} 243219560Savg 244219560Savgstatic void 245219560Savgaddpart(const char *type, const char *devname, const char *mntpt, 246219560Savg struct quotaname *qnp) 247219560Savg{ 248219560Savg struct diskentry *d = finddisk(devname); 249219560Savg struct partentry *p; 250219560Savg 251219560Savg TAILQ_FOREACH(p, &d->d_part, p_entries) 252219560Savg if (strcmp(p->p_devname, devname) == 0) { 253219560Savg warnx("%s in fstab more than once!\n", devname); 254219560Savg return; 255219560Savg } 256219560Savg 257219560Savg p = emalloc(sizeof(*p)); 258219560Savg p->p_devname = estrdup(devname); 259219560Savg p->p_mntpt = estrdup(mntpt); 260219560Savg p->p_type = estrdup(type); 261219560Savg p->p_quota = qnp; 262219560Savg 263219560Savg TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 264219560Savg} 265219560Savg 266219560Savg 267219560Savgstatic int 268219560Savgstartdisk(struct diskentry *d) 269219560Savg{ 270219560Savg struct partentry *p = TAILQ_FIRST(&d->d_part); 271219560Savg 272219560Savg d->d_pid = fork(); 273219560Savg if (d->d_pid < 0) { 274219560Savg perror("fork"); 275219560Savg return (8); 276219560Savg } 277219560Savg if (d->d_pid == 0) 278219560Savg exit(chkquota(p->p_devname, p->p_mntpt, p->p_quota)); 279219560Savg return (0); 280219560Savg} 281219560Savg