1: /* 2: * Copyright (c) 1990, 1993 3: * The Regents of the University of California. All rights reserved. 4: * 5: * Redistribution and use in source and binary forms, with or without 6: * modification, are permitted provided that the following conditions 7: * are met: 8: * 1. Redistributions of source code must retain the above copyright 9: * notice, this list of conditions and the following disclaimer. 10: * 2. Redistributions in binary form must reproduce the above copyright 11: * notice, this list of conditions and the following disclaimer in the 12: * documentation and/or other materials provided with the distribution. 13: * 3. All advertising materials mentioning features or use of this software 14: * must display the following acknowledgement: 15: * This product includes software developed by the University of 16: * California, Berkeley and its contributors. 17: * 4. Neither the name of the University nor the names of its contributors 18: * may be used to endorse or promote products derived from this software 19: * without specific prior written permission. 20: * 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31: * SUCH DAMAGE. 32: */ 33: 34: #if !defined(lint) && defined(DOSCCS) 35: static char sccsid[] = "@(#)preen.c 8.1.1 (2.11BSD) 1996/1/23"; 36: #endif /* not lint */ 37: 38: #include <sys/param.h> 39: #include <sys/stat.h> 40: #include <sys/wait.h> 41: #include <fstab.h> 42: #include <string.h> 43: #include <stdio.h> 44: #include <stdlib.h> 45: #include <ctype.h> 46: 47: char *rawname(), *unrawname(), *blockcheck(); 48: 49: struct part { 50: struct part *next; /* forward link of partitions on disk */ 51: char *name; /* device name */ 52: char *fsname; /* mounted filesystem name */ 53: int auxdata; /* auxillary data for application */ 54: } *badlist, **badnext = &badlist; 55: 56: struct disk { 57: char *name; /* disk base name */ 58: struct disk *next; /* forward link for list of disks */ 59: struct part *part; /* head of list of partitions on disk */ 60: int pid; /* If != 0, pid of proc working on */ 61: } *disks; 62: 63: int nrun, ndisks; 64: char hotroot; 65: 66: checkfstab(preen, maxrun, docheck, chkit) 67: int preen, maxrun; 68: int (*docheck)(), (*chkit)(); 69: { 70: register struct fstab *fsp; 71: register struct disk *dk, *nextdisk; 72: struct part *pt; 73: int ret, pid, retcode, passno, sumstatus; 74: union wait status; 75: int auxdata; 76: char *name; 77: 78: sumstatus = 0; 79: for (passno = 1; passno <= 2; passno++) { 80: if (setfsent() == 0) { 81: warn("Can't open %s\n", _PATH_FSTAB); 82: return (8); 83: } 84: while ((fsp = getfsent()) != 0) { 85: if ((auxdata = (*docheck)(fsp)) == 0) 86: continue; 87: if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { 88: if (name = blockcheck(fsp->fs_spec)) { 89: if (sumstatus = (*chkit)(name, 90: fsp->fs_file, auxdata, 0)) 91: return (sumstatus); 92: } else if (preen) 93: return (8); 94: } else if (passno == 2 && fsp->fs_passno > 1) { 95: if ((name = blockcheck(fsp->fs_spec)) == NULL) { 96: warn("BAD DISK NAME %s\n",fsp->fs_spec); 97: sumstatus |= 8; 98: continue; 99: } 100: addpart(name, fsp->fs_file, auxdata); 101: } 102: } 103: if (preen == 0) 104: return (0); 105: } 106: if (preen) { 107: if (maxrun == 0) 108: maxrun = ndisks; 109: if (maxrun > ndisks) 110: maxrun = ndisks; 111: nextdisk = disks; 112: for (passno = 0; passno < maxrun; ++passno) { 113: while (ret = startdisk(nextdisk, chkit) && nrun > 0) 114: sleep(10); 115: if (ret) 116: return (ret); 117: nextdisk = nextdisk->next; 118: } 119: while ((pid = wait(&status)) != -1) { 120: for (dk = disks; dk; dk = dk->next) 121: if (dk->pid == pid) 122: break; 123: if (dk == 0) { 124: warn("Unknown pid %d\n", pid); 125: continue; 126: } 127: if (WIFEXITED(status)) 128: retcode = WEXITSTATUS(status); 129: else 130: retcode = 0; 131: if (WIFSIGNALED(status)) { 132: warn("%s (%s): EXITED WITH SIGNAL %d\n", 133: dk->part->name, dk->part->fsname, 134: status.w_termsig); 135: retcode = 8; 136: } 137: if (retcode != 0) { 138: sumstatus |= retcode; 139: *badnext = dk->part; 140: badnext = &dk->part->next; 141: dk->part = dk->part->next; 142: *badnext = NULL; 143: } else 144: dk->part = dk->part->next; 145: dk->pid = 0; 146: nrun--; 147: if (dk->part == NULL) 148: ndisks--; 149: 150: if (nextdisk == NULL) { 151: if (dk->part) { 152: while (ret = startdisk(dk, chkit) && 153: nrun > 0) 154: sleep(10); 155: if (ret) 156: return (ret); 157: } 158: } else if (nrun < maxrun && nrun < ndisks) { 159: for ( ;; ) { 160: if ((nextdisk = nextdisk->next) == NULL) 161: nextdisk = disks; 162: if (nextdisk->part != NULL && 163: nextdisk->pid == 0) 164: break; 165: } 166: while (ret = startdisk(nextdisk, chkit) && 167: nrun > 0) 168: sleep(10); 169: if (ret) 170: return (ret); 171: } 172: } 173: } 174: (void)endfsent(); 175: if (badlist) { 176: warn("FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 177: badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 178: for (pt = badlist; pt; pt = pt->next) 179: warn("%s (%s)%s", pt->name, pt->fsname, 180: pt->next ? ", " : "\n"); 181: } 182: return(sumstatus); 183: } 184: 185: struct disk * 186: finddisk(name) 187: char *name; 188: { 189: register struct disk *dk, **dkp; 190: register char *p; 191: size_t len; 192: 193: for (p = name + strlen(name) - 1; p >= name; --p) 194: if (isdigit(*p)) { 195: len = p - name + 1; 196: break; 197: } 198: if (p < name) 199: len = strlen(name); 200: 201: for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 202: if (strncmp(dk->name, name, len) == 0 && 203: dk->name[len] == 0) 204: return (dk); 205: } 206: if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) 207: nomem(); 208: dk = *dkp; 209: if ((dk->name = (char *)malloc(len + 1)) == NULL) 210: nomem(); 211: (void)strncpy(dk->name, name, len); 212: dk->name[len] = '\0'; 213: dk->part = NULL; 214: dk->next = NULL; 215: dk->pid = 0; 216: ndisks++; 217: return (dk); 218: } 219: 220: addpart(name, fsname, auxdata) 221: char *name, *fsname; 222: int auxdata; 223: { 224: struct disk *dk = finddisk(name); 225: register struct part *pt, **ppt = &dk->part; 226: 227: for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 228: if (strcmp(pt->name, name) == 0) { 229: warn("%s in fstab more than once!\n", name); 230: return; 231: } 232: if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) 233: nomem(); 234: pt = *ppt; 235: if ((pt->name = (char *)malloc(strlen(name) + 1)) == NULL) 236: nomem(); 237: (void)strcpy(pt->name, name); 238: if ((pt->fsname = (char *)malloc(strlen(fsname) + 1)) == NULL) 239: nomem(); 240: (void)strcpy(pt->fsname, fsname); 241: pt->next = NULL; 242: pt->auxdata = auxdata; 243: } 244: 245: startdisk(dk, checkit) 246: register struct disk *dk; 247: int (*checkit)(); 248: { 249: register struct part *pt = dk->part; 250: 251: dk->pid = fork(); 252: if (dk->pid < 0) { 253: perror("fork"); 254: return (8); 255: } 256: if (dk->pid == 0) 257: exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 258: nrun++; 259: return (0); 260: } 261: 262: char * 263: blockcheck(name) 264: char *name; 265: { 266: struct stat stslash, stblock, stchar; 267: char *raw; 268: int retried = 0; 269: 270: hotroot = 0; 271: if (stat("/", &stslash) < 0) { 272: perror("/"); 273: warn("Can't stat root\n"); 274: return (0); 275: } 276: retry: 277: if (stat(name, &stblock) < 0) { 278: perror(name); 279: warn("Can't stat %s\n", name); 280: return (0); 281: } 282: if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 283: if (stslash.st_dev == stblock.st_rdev) 284: hotroot++; 285: raw = rawname(name); 286: if (stat(raw, &stchar) < 0) { 287: perror(raw); 288: warn("Can't stat %s\n", raw); 289: return (name); 290: } 291: if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 292: return (raw); 293: } else { 294: warn("%s not a character device\n", raw); 295: return (name); 296: } 297: } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 298: name = unrawname(name); 299: retried++; 300: goto retry; 301: } 302: warn("Can't make sense of name %s\n", name); 303: return (0); 304: } 305: 306: char * 307: unrawname(name) 308: char *name; 309: { 310: char *dp; 311: struct stat stb; 312: 313: if ((dp = rindex(name, '/')) == 0) 314: return (name); 315: if (stat(name, &stb) < 0) 316: return (name); 317: if ((stb.st_mode & S_IFMT) != S_IFCHR) 318: return (name); 319: if (dp[1] != 'r') 320: return (name); 321: (void)strcpy(&dp[1], &dp[2]); 322: return (name); 323: } 324: 325: char * 326: rawname(name) 327: char *name; 328: { 329: static char rawbuf[32]; 330: char *dp; 331: 332: if ((dp = rindex(name, '/')) == 0) 333: return (0); 334: *dp = 0; 335: (void)strcpy(rawbuf, name); 336: *dp = '/'; 337: (void)strcat(rawbuf, "/r"); 338: (void)strcat(rawbuf, &dp[1]); 339: return (rawbuf); 340: } 341: 342: nomem() 343: { 344: err(8, "out of memory"); 345: /* NOTREACHED */ 346: }