preen.c revision 128073
1184610Salfred/* 2184610Salfred * Copyright (c) 1990, 1993 3184610Salfred * The Regents of the University of California. All rights reserved. 4184610Salfred * 5184610Salfred * Redistribution and use in source and binary forms, with or without 6184610Salfred * modification, are permitted provided that the following conditions 7184610Salfred * are met: 8184610Salfred * 1. Redistributions of source code must retain the above copyright 9184610Salfred * notice, this list of conditions and the following disclaimer. 10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer in the 12184610Salfred * documentation and/or other materials provided with the distribution. 13184610Salfred * 4. Neither the name of the University nor the names of its contributors 14184610Salfred * may be used to endorse or promote products derived from this software 15184610Salfred * without specific prior written permission. 16184610Salfred * 17184610Salfred * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21184610Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27184610Salfred * SUCH DAMAGE. 28184610Salfred */ 29184610Salfred 30184610Salfred#if 0 31184610Salfred#ifndef lint 32184610Salfredstatic const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; 33184610Salfred#endif /* not lint */ 34184610Salfred#endif 35190185Sthompsa#include <sys/cdefs.h> 36190185Sthompsa__FBSDID("$FreeBSD: head/sbin/quotacheck/preen.c 128073 2004-04-09 19:58:40Z markm $"); 37190180Sthompsa 38190180Sthompsa#include <sys/param.h> 39190180Sthompsa#include <sys/stat.h> 40190180Sthompsa#include <sys/wait.h> 41190180Sthompsa 42184610Salfred#include <ufs/ufs/dinode.h> 43184610Salfred#include <ufs/ffs/fs.h> 44190180Sthompsa 45190180Sthompsa#include <ctype.h> 46190180Sthompsa#include <errno.h> 47190180Sthompsa#include <fstab.h> 48190180Sthompsa#include <string.h> 49190180Sthompsa#include <stdio.h> 50184610Salfred#include <stdlib.h> 51184610Salfred#include <unistd.h> 52190180Sthompsa 53190180Sthompsachar *blockcheck(char *origname); 54190180Sthompsa 55190180Sthompsa 56189599Sthompsastruct part { 57189599Sthompsa struct part *next; /* forward link of partitions on disk */ 58189599Sthompsa char *name; /* device name */ 59189599Sthompsa char *fsname; /* mounted file system name */ 60190180Sthompsa long auxdata; /* auxiliary data for application */ 61190180Sthompsa} *badlist, **badnext = &badlist; 62190180Sthompsa 63190180Sthompsastruct disk { 64190180Sthompsa char *name; /* disk base name */ 65190180Sthompsa struct disk *next; /* forward link for list of disks */ 66190180Sthompsa struct part *part; /* head of list of partitions on disk */ 67190180Sthompsa int pid; /* If != 0, pid of proc working on */ 68190180Sthompsa} *disks; 69190180Sthompsa 70190180Sthompsaint nrun, ndisks; 71190180Sthompsa 72190180Sthompsastatic void addpart(char *name, char *fsname, long auxdata); 73190180Sthompsastatic struct disk *finddisk(char *name); 74190180Sthompsastatic int startdisk(struct disk *dk,int (*checkit)(char *, char *, long, int)); 75190180Sthompsa 76190180Sthompsaint 77190180Sthompsacheckfstab(int preen, int maxrun, int (*docheck)(struct fstab *), 78190180Sthompsa int (*chkit)(char *, char *, long, int)) 79190180Sthompsa{ 80190180Sthompsa struct fstab *fsp; 81190180Sthompsa struct disk *dk, *nextdisk; 82190180Sthompsa struct part *pt; 83190180Sthompsa int ret, pid, retcode, passno, sumstatus, status; 84190180Sthompsa long auxdata; 85190180Sthompsa char *name; 86190180Sthompsa 87190180Sthompsa sumstatus = 0; 88190180Sthompsa for (passno = 1; passno <= 2; passno++) { 89190180Sthompsa if (setfsent() == 0) { 90190180Sthompsa fprintf(stderr, "Can't open checklist file: %s\n", 91190180Sthompsa _PATH_FSTAB); 92190180Sthompsa return (8); 93190180Sthompsa } 94190180Sthompsa while ((fsp = getfsent()) != 0) { 95190180Sthompsa if ((auxdata = (*docheck)(fsp)) == 0) 96190180Sthompsa continue; 97190180Sthompsa if (preen == 0 || 98190180Sthompsa (passno == 1 && fsp->fs_passno == 1)) { 99190180Sthompsa if ((name = blockcheck(fsp->fs_spec)) != 0) { 100190180Sthompsa if ((sumstatus = (*chkit)(name, 101190180Sthompsa fsp->fs_file, auxdata, 0)) != 0) 102190180Sthompsa return (sumstatus); 103190180Sthompsa } else if (preen) 104190180Sthompsa return (8); 105190180Sthompsa } else if (passno == 2 && fsp->fs_passno > 1) { 106190180Sthompsa if ((name = blockcheck(fsp->fs_spec)) == NULL) { 107190180Sthompsa fprintf(stderr, "BAD DISK NAME %s\n", 108190180Sthompsa fsp->fs_spec); 109190180Sthompsa sumstatus |= 8; 110190180Sthompsa continue; 111190180Sthompsa } 112190180Sthompsa addpart(name, fsp->fs_file, auxdata); 113190180Sthompsa } 114190180Sthompsa } 115190734Sthompsa if (preen == 0) 116190734Sthompsa return (0); 117190734Sthompsa } 118190734Sthompsa if (preen) { 119190734Sthompsa if (maxrun == 0) 120190734Sthompsa maxrun = ndisks; 121190734Sthompsa if (maxrun > ndisks) 122190734Sthompsa maxrun = ndisks; 123190734Sthompsa nextdisk = disks; 124190734Sthompsa for (passno = 0; passno < maxrun; ++passno) { 125190734Sthompsa while ((ret = startdisk(nextdisk, chkit)) && nrun > 0) 126190734Sthompsa sleep(10); 127190734Sthompsa if (ret) 128190734Sthompsa return (ret); 129190734Sthompsa nextdisk = nextdisk->next; 130190734Sthompsa } 131184610Salfred while ((pid = wait(&status)) != -1) { 132184610Salfred for (dk = disks; dk; dk = dk->next) 133184610Salfred if (dk->pid == pid) 134184610Salfred break; 135184610Salfred if (dk == 0) { 136184610Salfred printf("Unknown pid %d\n", pid); 137184610Salfred continue; 138184610Salfred } 139184610Salfred if (WIFEXITED(status)) 140184610Salfred retcode = WEXITSTATUS(status); 141184610Salfred else 142184610Salfred retcode = 0; 143184610Salfred if (WIFSIGNALED(status)) { 144184610Salfred printf("%s (%s): EXITED WITH SIGNAL %d\n", 145184610Salfred dk->part->name, dk->part->fsname, 146184610Salfred WTERMSIG(status)); 147184610Salfred retcode = 8; 148184610Salfred } 149184610Salfred if (retcode != 0) { 150184610Salfred sumstatus |= retcode; 151184610Salfred *badnext = dk->part; 152184610Salfred badnext = &dk->part->next; 153184610Salfred dk->part = dk->part->next; 154184610Salfred *badnext = NULL; 155184610Salfred } else 156184610Salfred dk->part = dk->part->next; 157184610Salfred dk->pid = 0; 158184610Salfred nrun--; 159184610Salfred if (dk->part == NULL) 160184610Salfred ndisks--; 161190185Sthompsa 162188942Sthompsa if (nextdisk == NULL) { 163184610Salfred if (dk->part) { 164188942Sthompsa while ((ret = startdisk(dk, chkit)) && 165184610Salfred nrun > 0) 166190185Sthompsa sleep(10); 167184610Salfred if (ret) 168190185Sthompsa return (ret); 169184610Salfred } 170190185Sthompsa } else if (nrun < maxrun && nrun < ndisks) { 171184610Salfred for ( ;; ) { 172190185Sthompsa if ((nextdisk = nextdisk->next) == NULL) 173184610Salfred nextdisk = disks; 174184610Salfred if (nextdisk->part != NULL && 175184610Salfred nextdisk->pid == 0) 176184610Salfred break; 177184610Salfred } 178190185Sthompsa while ((ret = startdisk(nextdisk, chkit)) && 179190185Sthompsa nrun > 0) 180190185Sthompsa sleep(10); 181190185Sthompsa if (ret) 182190185Sthompsa return (ret); 183190185Sthompsa } 184190185Sthompsa } 185190185Sthompsa } 186190185Sthompsa if (sumstatus) { 187190185Sthompsa if (badlist == 0) 188190185Sthompsa return (sumstatus); 189190185Sthompsa fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 190190185Sthompsa badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 191190185Sthompsa for (pt = badlist; pt; pt = pt->next) 192190185Sthompsa fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 193190185Sthompsa pt->next ? ", " : "\n"); 194190185Sthompsa return (sumstatus); 195190185Sthompsa } 196190185Sthompsa (void)endfsent(); 197190185Sthompsa return (0); 198190185Sthompsa} 199190185Sthompsa 200190185Sthompsastatic struct disk * 201190185Sthompsafinddisk(char *name) 202184610Salfred{ 203184610Salfred struct disk *dk, **dkp; 204184610Salfred char *p; 205190185Sthompsa size_t len; 206190185Sthompsa 207190185Sthompsa p = strrchr(name, '/'); 208184610Salfred p = p == NULL ? name : p + 1; 209190181Sthompsa while (*p != '\0' && !isdigit((u_char)*p)) 210190181Sthompsa p++; 211190181Sthompsa while (isdigit((u_char)*p)) 212190181Sthompsa p++; 213184610Salfred len = (size_t)(p - name); 214184610Salfred for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 215184610Salfred if (strncmp(dk->name, name, len) == 0 && 216184610Salfred dk->name[len] == 0) 217184610Salfred return (dk); 218184610Salfred } 219184610Salfred if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 220184610Salfred fprintf(stderr, "out of memory"); 221184610Salfred exit (8); 222184610Salfred } 223184610Salfred dk = *dkp; 224184610Salfred if ((dk->name = malloc(len + 1)) == NULL) { 225184610Salfred fprintf(stderr, "out of memory"); 226184610Salfred exit (8); 227184610Salfred } 228184610Salfred (void)strncpy(dk->name, name, len); 229184610Salfred dk->name[len] = '\0'; 230184610Salfred dk->part = NULL; 231184610Salfred dk->next = NULL; 232184610Salfred dk->pid = 0; 233184610Salfred ndisks++; 234184610Salfred return (dk); 235184610Salfred} 236184610Salfred 237184610Salfredstatic void 238184610Salfredaddpart(char *name, char *fsname, long auxdata) 239184610Salfred{ 240184610Salfred struct disk *dk = finddisk(name); 241184610Salfred struct part *pt, **ppt = &dk->part; 242184610Salfred 243184610Salfred for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 244184610Salfred if (strcmp(pt->name, name) == 0) { 245184610Salfred printf("%s in fstab more than once!\n", name); 246184610Salfred return; 247184610Salfred } 248184610Salfred if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 249184610Salfred fprintf(stderr, "out of memory"); 250184610Salfred exit (8); 251185087Salfred } 252185087Salfred pt = *ppt; 253185087Salfred if ((pt->name = malloc(strlen(name) + 1)) == NULL) { 254187173Sthompsa fprintf(stderr, "out of memory"); 255187173Sthompsa exit (8); 256187173Sthompsa } 257184610Salfred (void)strcpy(pt->name, name); 258184610Salfred if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { 259184610Salfred fprintf(stderr, "out of memory"); 260184610Salfred exit (8); 261184610Salfred } 262184610Salfred (void)strcpy(pt->fsname, fsname); 263184610Salfred pt->next = NULL; 264184610Salfred pt->auxdata = auxdata; 265184610Salfred} 266184610Salfred 267184610Salfredstatic int 268184610Salfredstartdisk(struct disk *dk, int (*checkit)(char *, char *, long, int)) 269184610Salfred{ 270184610Salfred struct part *pt = dk->part; 271190174Sthompsa 272190174Sthompsa dk->pid = fork(); 273190174Sthompsa if (dk->pid < 0) { 274190174Sthompsa perror("fork"); 275190174Sthompsa return (8); 276190174Sthompsa } 277190174Sthompsa if (dk->pid == 0) 278190174Sthompsa exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 279190181Sthompsa nrun++; 280190181Sthompsa return (0); 281190174Sthompsa} 282190174Sthompsa 283190181Sthompsa