1175678Smpp/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */ 2175678Smpp 31558Srgrimes/* 41558Srgrimes * Copyright (c) 1990, 1993 51558Srgrimes * The Regents of the University of California. All rights reserved. 61558Srgrimes * 71558Srgrimes * Redistribution and use in source and binary forms, with or without 81558Srgrimes * modification, are permitted provided that the following conditions 91558Srgrimes * are met: 101558Srgrimes * 1. Redistributions of source code must retain the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer. 121558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 131558Srgrimes * notice, this list of conditions and the following disclaimer in the 141558Srgrimes * documentation and/or other materials provided with the distribution. 151558Srgrimes * 4. Neither the name of the University nor the names of its contributors 161558Srgrimes * may be used to endorse or promote products derived from this software 171558Srgrimes * without specific prior written permission. 181558Srgrimes * 191558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 201558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 231558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291558Srgrimes * SUCH DAMAGE. 30175678Smpp * 31175678Smpp * $FreeBSD$ 321558Srgrimes */ 331558Srgrimes 34175678Smpp#include <sys/cdefs.h> 35175678Smpp#ifndef lint 36114589Sobrien#if 0 37175678Smppstatic char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; 38175678Smpp#else 39175678Smpp__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); 40175678Smpp#endif 41114589Sobrien#endif /* not lint */ 421558Srgrimes 431558Srgrimes#include <sys/param.h> 441558Srgrimes#include <sys/stat.h> 451558Srgrimes#include <sys/wait.h> 46175678Smpp#include <sys/queue.h> 4723798Sbde 48207736Smckusick#include <ufs/ufs/quota.h> 49207736Smckusick 50175678Smpp#include <err.h> 5123798Sbde#include <ctype.h> 52207736Smckusick#include <fcntl.h> 531558Srgrimes#include <fstab.h> 54207736Smckusick#include <libutil.h> 551558Srgrimes#include <string.h> 56101592Sphk#include <stdio.h> 57101592Sphk#include <stdlib.h> 58101592Sphk#include <unistd.h> 5923675Speter 60175678Smpp#include "quotacheck.h" 611558Srgrimes 62175678Smppstruct partentry { 63175678Smpp TAILQ_ENTRY(partentry) p_entries; 64180187Sdes char *p_devname; /* device name */ 65207736Smckusick const char *p_mntpt; /* mount point */ 66207736Smckusick struct quotafile *p_qfu; /* user quota file info ptr */ 67207736Smckusick struct quotafile *p_qfg; /* group quota file info */ 68175678Smpp}; 69101592Sphk 70175678SmppTAILQ_HEAD(part, partentry) badh; 711558Srgrimes 72175678Smppstruct diskentry { 73180187Sdes TAILQ_ENTRY(diskentry) d_entries; 74180187Sdes char *d_name; /* disk base name */ 75175678Smpp TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ 76175678Smpp int d_pid; /* 0 or pid of fsck proc */ 77175678Smpp}; 781558Srgrimes 79175678SmppTAILQ_HEAD(disk, diskentry) diskh; 801558Srgrimes 81175678Smppstatic struct diskentry *finddisk(const char *); 82207736Smckusickstatic void addpart(struct fstab *, struct quotafile *, struct quotafile *); 83175678Smppstatic int startdisk(struct diskentry *); 84175678Smppextern void *emalloc(size_t); 85175678Smppextern char *estrdup(const char *); 8623675Speter 877585Sbdeint 88207736Smckusickcheckfstab(int uflag, int gflag) 891558Srgrimes{ 90175678Smpp struct fstab *fs; 91175678Smpp struct diskentry *d, *nextdisk; 92175678Smpp struct partentry *p; 93175678Smpp int ret, pid, retcode, passno, sumstatus, status, nextpass; 94207736Smckusick struct quotafile *qfu, *qfg; 951558Srgrimes 96175678Smpp TAILQ_INIT(&badh); 97175678Smpp TAILQ_INIT(&diskh); 98175678Smpp 991558Srgrimes sumstatus = 0; 100175678Smpp 101175678Smpp nextpass = 0; 102175678Smpp for (passno = 1; nextpass != INT_MAX; passno = nextpass) { 103175678Smpp nextpass = INT_MAX; 1041558Srgrimes if (setfsent() == 0) { 105175678Smpp warnx("Can't open checklist file: %s\n", _PATH_FSTAB); 1061558Srgrimes return (8); 1071558Srgrimes } 108175678Smpp while ((fs = getfsent()) != 0) { 109175678Smpp if (fs->fs_passno > passno && fs->fs_passno < nextpass) 110175678Smpp nextpass = fs->fs_passno; 111175678Smpp 112175678Smpp if (passno != fs->fs_passno) 1131558Srgrimes continue; 114175678Smpp 115207736Smckusick qfu = NULL; 116207736Smckusick if (uflag) 117207736Smckusick qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR); 118207736Smckusick qfg = NULL; 119207736Smckusick if (gflag) 120207736Smckusick qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR); 121207736Smckusick if (qfu == NULL && qfg == NULL) 122175678Smpp continue; 123175678Smpp 124175678Smpp if (passno == 1) { 125207736Smckusick sumstatus = chkquota(fs->fs_spec, qfu, qfg); 126207736Smckusick if (qfu) 127207736Smckusick quota_close(qfu); 128207736Smckusick if (qfg) 129207736Smckusick quota_close(qfg); 130175678Smpp if (sumstatus) 131175678Smpp return (sumstatus); 132175678Smpp continue; 133180187Sdes } 134207736Smckusick addpart(fs, qfu, qfg); 1351558Srgrimes } 136175678Smpp 137175678Smpp if (passno == 1) 138175678Smpp continue; 139175678Smpp 140175678Smpp TAILQ_FOREACH(nextdisk, &diskh, d_entries) { 141175678Smpp if ((ret = startdisk(nextdisk)) != 0) 142175678Smpp return ret; 1431558Srgrimes } 144175678Smpp 1451558Srgrimes while ((pid = wait(&status)) != -1) { 146180187Sdes TAILQ_FOREACH(d, &diskh, d_entries) 147175678Smpp if (d->d_pid == pid) 1481558Srgrimes break; 149175678Smpp 150175678Smpp if (d == NULL) { 151175678Smpp warnx("Unknown pid %d\n", pid); 1521558Srgrimes continue; 1531558Srgrimes } 154175678Smpp 1551558Srgrimes if (WIFEXITED(status)) 1561558Srgrimes retcode = WEXITSTATUS(status); 1571558Srgrimes else 1581558Srgrimes retcode = 0; 159175678Smpp 160175678Smpp p = TAILQ_FIRST(&d->d_part); 161175678Smpp 1621558Srgrimes if (WIFSIGNALED(status)) { 163175678Smpp (void) fprintf(stderr, 164207736Smckusick "%s: (%s): EXITED WITH SIGNAL %d\n", 165207736Smckusick p->p_devname, p->p_mntpt, 166175678Smpp WTERMSIG(status)); 1671558Srgrimes retcode = 8; 1681558Srgrimes } 169175678Smpp 170175678Smpp TAILQ_REMOVE(&d->d_part, p, p_entries); 171175678Smpp 1721558Srgrimes if (retcode != 0) { 173175678Smpp TAILQ_INSERT_TAIL(&badh, p, p_entries); 1741558Srgrimes sumstatus |= retcode; 175175678Smpp } else { 176175678Smpp free(p->p_devname); 177207736Smckusick if (p->p_qfu) 178207736Smckusick quota_close(p->p_qfu); 179207736Smckusick if (p->p_qfg) 180207736Smckusick quota_close(p->p_qfg); 181175678Smpp free(p); 182175678Smpp } 183175678Smpp d->d_pid = 0; 1841558Srgrimes 185175678Smpp if (TAILQ_EMPTY(&d->d_part)) { 186175678Smpp TAILQ_REMOVE(&diskh, d, d_entries); 187175678Smpp } else { 188175678Smpp if ((ret = startdisk(d)) != 0) 189175678Smpp return ret; 1901558Srgrimes } 1911558Srgrimes } 1921558Srgrimes } 193175678Smpp 1941558Srgrimes if (sumstatus) { 195175678Smpp p = TAILQ_FIRST(&badh); 196175678Smpp if (p == NULL) 1971558Srgrimes return (sumstatus); 198175678Smpp 199175678Smpp (void) fprintf(stderr, 200175678Smpp "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 201175678Smpp TAILQ_NEXT(p, p_entries) ? "S" : "", 202175678Smpp "UNEXPECTED INCONSISTENCY:"); 203175678Smpp 204175678Smpp for (; p; p = TAILQ_NEXT(p, p_entries)) 205175678Smpp (void) fprintf(stderr, 206207736Smckusick "%s: (%s)%s", p->p_devname, p->p_mntpt, 207207736Smckusick TAILQ_NEXT(p, p_entries) ? ", " : "\n"); 208175678Smpp 209175678Smpp return sumstatus; 2101558Srgrimes } 211175678Smpp (void) endfsent(); 2121558Srgrimes return (0); 2131558Srgrimes} 2141558Srgrimes 215175678Smpp 216175678Smppstatic struct diskentry * 217175678Smppfinddisk(const char *name) 2181558Srgrimes{ 219175678Smpp const char *p; 220175678Smpp size_t len = 0; 221175678Smpp struct diskentry *d; 2221558Srgrimes 22335095Sbde p = strrchr(name, '/'); 224175678Smpp if (p == NULL) 225175678Smpp p = name; 226175678Smpp else 22735095Sbde p++; 228175678Smpp for (; *p && !isdigit(*p); p++) 229175678Smpp continue; 230175678Smpp for (; *p && isdigit(*p); p++) 231175678Smpp continue; 232175678Smpp len = p - name; 233175678Smpp if (len == 0) 234175678Smpp len = strlen(name); 235175678Smpp 236180187Sdes TAILQ_FOREACH(d, &diskh, d_entries) 237175678Smpp if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) 238175678Smpp return d; 239175678Smpp 240175678Smpp d = emalloc(sizeof(*d)); 241175678Smpp d->d_name = estrdup(name); 242175678Smpp d->d_name[len] = '\0'; 243175678Smpp TAILQ_INIT(&d->d_part); 244175678Smpp d->d_pid = 0; 245175678Smpp 246175678Smpp TAILQ_INSERT_TAIL(&diskh, d, d_entries); 247175678Smpp 248175678Smpp return d; 2491558Srgrimes} 2501558Srgrimes 25123675Speterstatic void 252207736Smckusickaddpart(struct fstab *fs, struct quotafile *qfu, struct quotafile *qfg) 2531558Srgrimes{ 254207736Smckusick struct diskentry *d = finddisk(fs->fs_spec); 255175678Smpp struct partentry *p; 2561558Srgrimes 257175678Smpp TAILQ_FOREACH(p, &d->d_part, p_entries) 258207736Smckusick if (strcmp(p->p_devname, fs->fs_spec) == 0) { 259207736Smckusick warnx("%s in fstab more than once!\n", fs->fs_spec); 2601558Srgrimes return; 2611558Srgrimes } 262175678Smpp 263175678Smpp p = emalloc(sizeof(*p)); 264207736Smckusick p->p_devname = estrdup(blockcheck(fs->fs_spec)); 265207736Smckusick if (qfu != NULL) 266207736Smckusick p->p_mntpt = quota_fsname(qfu); 267207736Smckusick else 268207736Smckusick p->p_mntpt = quota_fsname(qfg); 269207736Smckusick p->p_qfu = qfu; 270207736Smckusick p->p_qfg = qfg; 271175678Smpp 272175678Smpp TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); 2731558Srgrimes} 2741558Srgrimes 275175678Smpp 27623675Speterstatic int 277175678Smppstartdisk(struct diskentry *d) 2781558Srgrimes{ 279175678Smpp struct partentry *p = TAILQ_FIRST(&d->d_part); 2801558Srgrimes 281175678Smpp d->d_pid = fork(); 282175678Smpp if (d->d_pid < 0) { 28341474Sjulian perror("fork"); 2841558Srgrimes return (8); 2851558Srgrimes } 286175678Smpp if (d->d_pid == 0) 287207736Smckusick exit(chkquota(p->p_devname, p->p_qfu, p->p_qfg)); 2881558Srgrimes return (0); 2891558Srgrimes} 290