preen.c revision 8871
1139804Simp/* 2131903Smarcel * Copyright (c) 1990, 1993 3131903Smarcel * The Regents of the University of California. All rights reserved. 4131903Smarcel * 5131903Smarcel * Redistribution and use in source and binary forms, with or without 6131903Smarcel * modification, are permitted provided that the following conditions 7131903Smarcel * are met: 8131903Smarcel * 1. Redistributions of source code must retain the above copyright 9131903Smarcel * notice, this list of conditions and the following disclaimer. 10131903Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11131903Smarcel * notice, this list of conditions and the following disclaimer in the 12131903Smarcel * documentation and/or other materials provided with the distribution. 13131903Smarcel * 3. All advertising materials mentioning features or use of this software 14131903Smarcel * must display the following acknowledgement: 15131903Smarcel * This product includes software developed by the University of 16131903Smarcel * California, Berkeley and its contributors. 17131903Smarcel * 4. Neither the name of the University nor the names of its contributors 18131903Smarcel * may be used to endorse or promote products derived from this software 19131903Smarcel * without specific prior written permission. 20131903Smarcel * 21131903Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22131903Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23131903Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24131903Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25131903Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26131903Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27131903Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28131903Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29131903Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30147674Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31212964Savg * SUCH DAMAGE. 32147674Speter */ 33131903Smarcel 34131903Smarcel#ifndef lint 35228632Savgstatic const char sccsid[] = "@(#)preen.c 8.1 (Berkeley) 6/5/93"; 36131903Smarcel#endif /* not lint */ 37131903Smarcel 38131903Smarcel#include <sys/param.h> 39131903Smarcel#include <sys/stat.h> 40131903Smarcel#include <sys/wait.h> 41218825Smdf#include <ufs/ufs/dinode.h> 42131903Smarcel#include <fstab.h> 43212964Savg#include <string.h> 44131903Smarcel#include <stdio.h> 45131903Smarcel#include <unistd.h> 46131903Smarcel#include <stdlib.h> 47131903Smarcel#include <ctype.h> 48131903Smarcel#include "fsck.h" 49151634Sjhb 50145727Sdwhitestruct part { 51145727Sdwhite struct part *next; /* forward link of partitions on disk */ 52145727Sdwhite char *name; /* device name */ 53131903Smarcel char *fsname; /* mounted filesystem name */ 54191948Simp long auxdata; /* auxillary data for application */ 55131903Smarcel} *badlist, **badnext = &badlist; 56191948Simp 57131903Smarcelstruct disk { 58131903Smarcel char *name; /* disk base name */ 59131903Smarcel struct disk *next; /* forward link for list of disks */ 60131903Smarcel struct part *part; /* head of list of partitions on disk */ 61225203Srwatson int pid; /* If != 0, pid of proc working on */ 62225203Srwatson} *disks; 63225203Srwatson 64225203Srwatsonstatic void addpart __P((char *name, char *fsname, long auxdata)); 65225203Srwatsonstatic int startdisk __P((struct disk *dk, int (*checkit)())); 66225203Srwatsonstatic struct disk *finddisk __P((char *name)); 67225203Srwatsonstatic char *unrawname __P((char *name)); 68225203Srwatsonstatic char *rawname __P((char *name)); 69225203Srwatson 70225203Srwatsonint nrun, ndisks; 71225203Srwatsonchar hotroot; 72225203Srwatson 73225203Srwatsonint 74225203Srwatsoncheckfstab(preen, maxrun, docheck, chkit) 75225203Srwatson int preen, maxrun; 76234190Sjhb int (*docheck)(), (*chkit)(); 77131903Smarcel{ 78131903Smarcel register struct fstab *fsp; 79131903Smarcel register struct disk *dk, *nextdisk; 80131903Smarcel register struct part *pt; 81131903Smarcel int ret, pid, retcode, passno, sumstatus, status; 82151725Speter long auxdata; 83151725Speter char *name; 84159726Syar 85131903Smarcel sumstatus = 0; 86227309Sed for (passno = 1; passno <= 2; passno++) { 87131903Smarcel if (setfsent() == 0) { 88191948Simp fprintf(stderr, "Can't open checklist file: %s\n", 89191948Simp _PATH_FSTAB); 90131903Smarcel return (8); 91191948Simp } 92191948Simp while ((fsp = getfsent()) != 0) { 93131903Smarcel if ((auxdata = (*docheck)(fsp)) == 0) 94226089Sobrien continue; 95226089Sobrien if (!preen || (passno == 1 && fsp->fs_passno == 1)) { 96131903Smarcel name = blockcheck(fsp->fs_spec); 97131903Smarcel if (name) { 98226089Sobrien sumstatus = (*chkit)(name, 99226089Sobrien fsp->fs_file, auxdata, 0); 100151725Speter if (sumstatus) 101151725Speter return (sumstatus); 102226089Sobrien } else if (preen) 103226089Sobrien return (8); 104159726Syar } else if (passno == 2 && fsp->fs_passno > 1) { 105151725Speter if ((name = blockcheck(fsp->fs_spec)) == NULL) { 106226089Sobrien fprintf(stderr, "BAD DISK NAME %s\n", 107226089Sobrien fsp->fs_spec); 108159726Syar sumstatus |= 8; 109159726Syar continue; 110226089Sobrien } 111273736Shselasky addpart(name, fsp->fs_file, auxdata); 112226089Sobrien } 113225203Srwatson } 114225203Srwatson if (preen == 0) 115226089Sobrien return (0); 116273736Shselasky } 117226089Sobrien if (preen) { 118225203Srwatson if (maxrun == 0) 119225203Srwatson maxrun = ndisks; 120133737Srwatson if (maxrun > ndisks) 121174898Srwatson maxrun = ndisks; 122174898Srwatson nextdisk = disks; 123174898Srwatson for (passno = 0; passno < maxrun; ++passno) { 124174898Srwatson while ((ret = startdisk(nextdisk, chkit)) != 0 && 125131903Smarcel nrun > 0) 126131903Smarcel sleep(10); 127131903Smarcel if (ret) 128218825Smdf return (ret); 129218825Smdf nextdisk = nextdisk->next; 130131903Smarcel } 131131903Smarcel while ((pid = wait(&status)) != -1) { 132218825Smdf for (dk = disks; dk; dk = dk->next) 133131903Smarcel if (dk->pid == pid) 134218825Smdf break; 135218825Smdf if (dk == 0) { 136131903Smarcel printf("Unknown pid %d\n", pid); 137218825Smdf continue; 138218825Smdf } 139131903Smarcel if (WIFEXITED(status)) 140131903Smarcel retcode = WEXITSTATUS(status); 141131903Smarcel else 142131903Smarcel retcode = 0; 143131903Smarcel if (WIFSIGNALED(status)) { 144131903Smarcel printf("%s (%s): EXITED WITH SIGNAL %d\n", 145131903Smarcel dk->part->name, dk->part->fsname, 146131903Smarcel WTERMSIG(status)); 147131903Smarcel retcode = 8; 148218825Smdf } 149218825Smdf if (retcode != 0) { 150218825Smdf sumstatus |= retcode; 151131982Smarcel *badnext = dk->part; 152131903Smarcel badnext = &dk->part->next; 153131903Smarcel dk->part = dk->part->next; 154131903Smarcel *badnext = NULL; 155131903Smarcel } else 156131903Smarcel dk->part = dk->part->next; 157132001Smarcel dk->pid = 0; 158131903Smarcel nrun--; 159131903Smarcel if (dk->part == NULL) 160131903Smarcel ndisks--; 161131903Smarcel 162131903Smarcel if (nextdisk == NULL) { 163131903Smarcel if (dk->part) { 164131903Smarcel while ((ret = startdisk(dk, chkit)) != 0 165131903Smarcel && nrun > 0) 166131903Smarcel sleep(10); 167131903Smarcel if (ret) 168131903Smarcel return (ret); 169131903Smarcel } 170131903Smarcel } else if (nrun < maxrun && nrun < ndisks) { 171131903Smarcel for ( ;; ) { 172131903Smarcel if ((nextdisk = nextdisk->next) == NULL) 173131903Smarcel nextdisk = disks; 174174898Srwatson if (nextdisk->part != NULL && 175131903Smarcel nextdisk->pid == 0) 176131903Smarcel break; 177131903Smarcel } 178151725Speter while ((ret = startdisk(nextdisk, chkit)) != 0 179151725Speter && nrun > 0) 180151725Speter sleep(10); 181151725Speter if (ret) 182151725Speter return (ret); 183151725Speter } 184151725Speter } 185151725Speter } 186151725Speter if (sumstatus) { 187151725Speter if (badlist == 0) 188151725Speter return (sumstatus); 189151725Speter fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 190151725Speter badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 191151725Speter for (pt = badlist; pt; pt = pt->next) 192151725Speter fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 193151725Speter pt->next ? ", " : "\n"); 194151725Speter return (sumstatus); 195151725Speter } 196151725Speter (void)endfsent(); 197151725Speter return (0); 198151725Speter} 199151725Speter 200151725Speterstruct disk * 201151725Speterfinddisk(name) 202151725Speter char *name; 203151725Speter{ 204151725Speter register struct disk *dk, **dkp; 205151725Speter register char *p; 206151725Speter size_t len = 0; 207151725Speter 208151725Speter for (p = name + strlen(name) - 1; p >= name; --p) 209151725Speter if (isdigit(*p)) { 210159726Syar len = p - name + 1; 211159726Syar break; 212159726Syar } 213159726Syar if (p < name) 214159726Syar len = strlen(name); 215159726Syar 216159726Syar for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 217159726Syar if (strncmp(dk->name, name, len) == 0 && 218159726Syar dk->name[len] == 0) 219159726Syar return (dk); 220159726Syar } 221159726Syar if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 222159726Syar fprintf(stderr, "out of memory"); 223159726Syar exit (8); 224159726Syar } 225159726Syar dk = *dkp; 226159726Syar if ((dk->name = malloc(len + 1)) == NULL) { 227178766Speter fprintf(stderr, "out of memory"); 228178766Speter exit (8); 229178766Speter } 230223758Sattilio (void)strncpy(dk->name, name, len); 231178766Speter dk->name[len] = '\0'; 232209062Savg dk->part = NULL; 233178766Speter dk->next = NULL; 234178766Speter dk->pid = 0; 235178766Speter ndisks++; 236178766Speter return (dk); 237178766Speter} 238178766Speter 239178766Spetervoid 240178766Speteraddpart(name, fsname, auxdata) 241178766Speter char *name, *fsname; 242178766Speter long auxdata; 243131903Smarcel{ 244131903Smarcel struct disk *dk = finddisk(name); 245131903Smarcel register struct part *pt, **ppt = &dk->part; 246131903Smarcel 247131903Smarcel for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 248131903Smarcel if (strcmp(pt->name, name) == 0) { 249131903Smarcel printf("%s in fstab more than once!\n", name); 250131903Smarcel return; 251131903Smarcel } 252131903Smarcel if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 253131903Smarcel fprintf(stderr, "out of memory"); 254131903Smarcel exit (8); 255131903Smarcel } 256131903Smarcel pt = *ppt; 257178766Speter if ((pt->name = malloc(strlen(name) + 1)) == NULL) { 258178766Speter fprintf(stderr, "out of memory"); 259131903Smarcel exit (8); 260223099Sgibbs } 261223099Sgibbs (void)strcpy(pt->name, name); 262223099Sgibbs if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { 263223099Sgibbs fprintf(stderr, "out of memory"); 264223099Sgibbs exit (8); 265223099Sgibbs } 266223099Sgibbs (void)strcpy(pt->fsname, fsname); 267131903Smarcel pt->next = NULL; 268225203Srwatson pt->auxdata = auxdata; 269131903Smarcel} 270225203Srwatson 271225203Srwatsonint 272225203Srwatsonstartdisk(dk, checkit) 273225203Srwatson register struct disk *dk; 274225203Srwatson int (*checkit)(); 275225203Srwatson{ 276225203Srwatson register struct part *pt = dk->part; 277225203Srwatson 278225203Srwatson dk->pid = fork(); 279225203Srwatson if (dk->pid < 0) { 280131903Smarcel perror("fork"); 281131903Smarcel return (8); 282223099Sgibbs } 283223099Sgibbs if (dk->pid == 0) 284223099Sgibbs exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 285223099Sgibbs nrun++; 286223099Sgibbs return (0); 287223099Sgibbs} 288131903Smarcel 289178766Speterchar * 290223099Sgibbsblockcheck(name) 291223099Sgibbs char *name; 292178766Speter{ 293223099Sgibbs struct stat stslash, stblock, stchar; 294131903Smarcel char *raw; 295223099Sgibbs int retried = 0; 296223099Sgibbs 297178766Speter hotroot = 0; 298178766Speter if (stat("/", &stslash) < 0) { 299178766Speter perror("/"); 300178766Speter printf("Can't stat root\n"); 301178766Speter return (0); 302178766Speter } 303223099Sgibbsretry: 304223099Sgibbs if (stat(name, &stblock) < 0) { 305223099Sgibbs perror(name); 306223099Sgibbs printf("Can't stat %s\n", name); 307223099Sgibbs return (0); 308131903Smarcel } 309131903Smarcel if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 310131903Smarcel if (stslash.st_dev == stblock.st_rdev) 311131903Smarcel hotroot++; 312225203Srwatson raw = rawname(name); 313225203Srwatson if (stat(raw, &stchar) < 0) { 314225203Srwatson perror(raw); 315225203Srwatson printf("Can't stat %s\n", raw); 316225203Srwatson return (name); 317225203Srwatson } 318225203Srwatson if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 319225203Srwatson return (raw); 320225203Srwatson } else { 321225203Srwatson printf("%s is not a character device\n", raw); 322225203Srwatson return (name); 323225203Srwatson } 324225203Srwatson } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 325225203Srwatson name = unrawname(name); 326225203Srwatson retried++; 327225203Srwatson goto retry; 328225203Srwatson } 329225203Srwatson printf("Can't make sense out of name %s\n", name); 330225203Srwatson return (0); 331225203Srwatson} 332225203Srwatson 333225203Srwatsonchar * 334225203Srwatsonunrawname(name) 335225203Srwatson char *name; 336225203Srwatson{ 337225203Srwatson char *dp; 338225203Srwatson struct stat stb; 339225203Srwatson 340225203Srwatson if ((dp = rindex(name, '/')) == 0) 341225203Srwatson return (name); 342225203Srwatson if (stat(name, &stb) < 0) 343225203Srwatson return (name); 344225203Srwatson if ((stb.st_mode & S_IFMT) != S_IFCHR) 345225203Srwatson return (name); 346225203Srwatson if (dp[1] != 'r') 347131903Smarcel return (name); 348225203Srwatson (void)strcpy(&dp[1], &dp[2]); 349225203Srwatson return (name); 350225203Srwatson} 351225203Srwatson 352225203Srwatsonchar * 353225203Srwatsonrawname(name) 354225203Srwatson char *name; 355225203Srwatson{ 356225203Srwatson static char rawbuf[32]; 357225203Srwatson char *dp; 358225203Srwatson 359225203Srwatson if ((dp = rindex(name, '/')) == 0) 360131903Smarcel return (0); 361131903Smarcel *dp = 0; 362131903Smarcel (void)strcpy(rawbuf, name); 363131903Smarcel *dp = '/'; 364131903Smarcel (void)strcat(rawbuf, "/r"); 365131903Smarcel (void)strcat(rawbuf, &dp[1]); 366131903Smarcel return (rawbuf); 367191948Simp} 368131903Smarcel