preen.c revision 7585
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1990, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 357585Sbdestatic const char sccsid[] = "@(#)preen.c 8.1 (Berkeley) 6/5/93"; 361558Srgrimes#endif /* not lint */ 371558Srgrimes 381558Srgrimes#include <sys/param.h> 391558Srgrimes#include <sys/stat.h> 401558Srgrimes#include <sys/wait.h> 417585Sbde#include <ufs/ufs/dinode.h> 421558Srgrimes#include <fstab.h> 431558Srgrimes#include <string.h> 441558Srgrimes#include <stdio.h> 457585Sbde#include <unistd.h> 461558Srgrimes#include <stdlib.h> 471558Srgrimes#include <ctype.h> 487585Sbde#include "fsck.h" 491558Srgrimes 501558Srgrimesstruct part { 511558Srgrimes struct part *next; /* forward link of partitions on disk */ 521558Srgrimes char *name; /* device name */ 531558Srgrimes char *fsname; /* mounted filesystem name */ 541558Srgrimes long auxdata; /* auxillary data for application */ 551558Srgrimes} *badlist, **badnext = &badlist; 561558Srgrimes 571558Srgrimesstruct disk { 581558Srgrimes char *name; /* disk base name */ 591558Srgrimes struct disk *next; /* forward link for list of disks */ 601558Srgrimes struct part *part; /* head of list of partitions on disk */ 611558Srgrimes int pid; /* If != 0, pid of proc working on */ 621558Srgrimes} *disks; 631558Srgrimes 647585Sbdestatic void addpart __P((char *name, char *fsname, long auxdata)); 657585Sbdestatic int startdisk __P((struct disk *dk, int (*checkit)())); 667585Sbdestatic struct disk *finddisk __P((char *name)); 677585Sbdestatic char *unrawname __P((char *name)); 687585Sbdestatic char *rawname __P((char *name)); 697585Sbde 701558Srgrimesint nrun, ndisks; 711558Srgrimeschar hotroot; 721558Srgrimes 737585Sbdeint 741558Srgrimescheckfstab(preen, maxrun, docheck, chkit) 751558Srgrimes int preen, maxrun; 761558Srgrimes int (*docheck)(), (*chkit)(); 771558Srgrimes{ 781558Srgrimes register struct fstab *fsp; 791558Srgrimes register struct disk *dk, *nextdisk; 801558Srgrimes register struct part *pt; 811558Srgrimes int ret, pid, retcode, passno, sumstatus, status; 821558Srgrimes long auxdata; 831558Srgrimes char *name; 841558Srgrimes 851558Srgrimes sumstatus = 0; 861558Srgrimes for (passno = 1; passno <= 2; passno++) { 871558Srgrimes if (setfsent() == 0) { 881558Srgrimes fprintf(stderr, "Can't open checklist file: %s\n", 891558Srgrimes _PATH_FSTAB); 901558Srgrimes return (8); 911558Srgrimes } 921558Srgrimes while ((fsp = getfsent()) != 0) { 931558Srgrimes if ((auxdata = (*docheck)(fsp)) == 0) 941558Srgrimes continue; 957585Sbde if (!preen || (passno == 1 && fsp->fs_passno == 1)) { 967585Sbde name = blockcheck(fsp->fs_spec); 977585Sbde if (name) { 987585Sbde sumstatus = (*chkit)(name, 997585Sbde fsp->fs_file, auxdata, 0); 1007585Sbde if (sumstatus) 1011558Srgrimes return (sumstatus); 1021558Srgrimes } else if (preen) 1031558Srgrimes return (8); 1041558Srgrimes } else if (passno == 2 && fsp->fs_passno > 1) { 1051558Srgrimes if ((name = blockcheck(fsp->fs_spec)) == NULL) { 1061558Srgrimes fprintf(stderr, "BAD DISK NAME %s\n", 1071558Srgrimes fsp->fs_spec); 1081558Srgrimes sumstatus |= 8; 1091558Srgrimes continue; 1101558Srgrimes } 1111558Srgrimes addpart(name, fsp->fs_file, auxdata); 1121558Srgrimes } 1131558Srgrimes } 1141558Srgrimes if (preen == 0) 1151558Srgrimes return (0); 1161558Srgrimes } 1171558Srgrimes if (preen) { 1181558Srgrimes if (maxrun == 0) 1191558Srgrimes maxrun = ndisks; 1201558Srgrimes if (maxrun > ndisks) 1211558Srgrimes maxrun = ndisks; 1221558Srgrimes nextdisk = disks; 1231558Srgrimes for (passno = 0; passno < maxrun; ++passno) { 1247585Sbde while ((ret = startdisk(nextdisk, chkit)) != 0 && 1257585Sbde nrun > 0) 1261558Srgrimes sleep(10); 1271558Srgrimes if (ret) 1281558Srgrimes return (ret); 1291558Srgrimes nextdisk = nextdisk->next; 1301558Srgrimes } 1311558Srgrimes while ((pid = wait(&status)) != -1) { 1321558Srgrimes for (dk = disks; dk; dk = dk->next) 1331558Srgrimes if (dk->pid == pid) 1341558Srgrimes break; 1351558Srgrimes if (dk == 0) { 1361558Srgrimes printf("Unknown pid %d\n", pid); 1371558Srgrimes continue; 1381558Srgrimes } 1391558Srgrimes if (WIFEXITED(status)) 1401558Srgrimes retcode = WEXITSTATUS(status); 1411558Srgrimes else 1421558Srgrimes retcode = 0; 1431558Srgrimes if (WIFSIGNALED(status)) { 1441558Srgrimes printf("%s (%s): EXITED WITH SIGNAL %d\n", 1451558Srgrimes dk->part->name, dk->part->fsname, 1461558Srgrimes WTERMSIG(status)); 1471558Srgrimes retcode = 8; 1481558Srgrimes } 1491558Srgrimes if (retcode != 0) { 1501558Srgrimes sumstatus |= retcode; 1511558Srgrimes *badnext = dk->part; 1521558Srgrimes badnext = &dk->part->next; 1531558Srgrimes dk->part = dk->part->next; 1541558Srgrimes *badnext = NULL; 1551558Srgrimes } else 1561558Srgrimes dk->part = dk->part->next; 1571558Srgrimes dk->pid = 0; 1581558Srgrimes nrun--; 1591558Srgrimes if (dk->part == NULL) 1601558Srgrimes ndisks--; 1611558Srgrimes 1621558Srgrimes if (nextdisk == NULL) { 1631558Srgrimes if (dk->part) { 1647585Sbde while ((ret = startdisk(dk, chkit)) != 0 1657585Sbde && nrun > 0) 1661558Srgrimes sleep(10); 1671558Srgrimes if (ret) 1681558Srgrimes return (ret); 1691558Srgrimes } 1701558Srgrimes } else if (nrun < maxrun && nrun < ndisks) { 1711558Srgrimes for ( ;; ) { 1721558Srgrimes if ((nextdisk = nextdisk->next) == NULL) 1731558Srgrimes nextdisk = disks; 1741558Srgrimes if (nextdisk->part != NULL && 1751558Srgrimes nextdisk->pid == 0) 1761558Srgrimes break; 1771558Srgrimes } 1787585Sbde while ((ret = startdisk(nextdisk, chkit)) != 0 1797585Sbde && nrun > 0) 1801558Srgrimes sleep(10); 1811558Srgrimes if (ret) 1821558Srgrimes return (ret); 1831558Srgrimes } 1841558Srgrimes } 1851558Srgrimes } 1861558Srgrimes if (sumstatus) { 1871558Srgrimes if (badlist == 0) 1881558Srgrimes return (sumstatus); 1891558Srgrimes fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 1901558Srgrimes badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 1911558Srgrimes for (pt = badlist; pt; pt = pt->next) 1921558Srgrimes fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 1931558Srgrimes pt->next ? ", " : "\n"); 1941558Srgrimes return (sumstatus); 1951558Srgrimes } 1961558Srgrimes (void)endfsent(); 1971558Srgrimes return (0); 1981558Srgrimes} 1991558Srgrimes 2001558Srgrimesstruct disk * 2011558Srgrimesfinddisk(name) 2021558Srgrimes char *name; 2031558Srgrimes{ 2041558Srgrimes register struct disk *dk, **dkp; 2051558Srgrimes register char *p; 2067585Sbde size_t len = 0; 2071558Srgrimes 2081558Srgrimes for (p = name + strlen(name) - 1; p >= name; --p) 2091558Srgrimes if (isdigit(*p)) { 2101558Srgrimes len = p - name + 1; 2111558Srgrimes break; 2121558Srgrimes } 2131558Srgrimes if (p < name) 2141558Srgrimes len = strlen(name); 2151558Srgrimes 2161558Srgrimes for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 2171558Srgrimes if (strncmp(dk->name, name, len) == 0 && 2181558Srgrimes dk->name[len] == 0) 2191558Srgrimes return (dk); 2201558Srgrimes } 2211558Srgrimes if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 2221558Srgrimes fprintf(stderr, "out of memory"); 2231558Srgrimes exit (8); 2241558Srgrimes } 2251558Srgrimes dk = *dkp; 2261558Srgrimes if ((dk->name = malloc(len + 1)) == NULL) { 2271558Srgrimes fprintf(stderr, "out of memory"); 2281558Srgrimes exit (8); 2291558Srgrimes } 2301558Srgrimes (void)strncpy(dk->name, name, len); 2311558Srgrimes dk->name[len] = '\0'; 2321558Srgrimes dk->part = NULL; 2331558Srgrimes dk->next = NULL; 2341558Srgrimes dk->pid = 0; 2351558Srgrimes ndisks++; 2361558Srgrimes return (dk); 2371558Srgrimes} 2381558Srgrimes 2397585Sbdevoid 2401558Srgrimesaddpart(name, fsname, auxdata) 2411558Srgrimes char *name, *fsname; 2421558Srgrimes long auxdata; 2431558Srgrimes{ 2441558Srgrimes struct disk *dk = finddisk(name); 2451558Srgrimes register struct part *pt, **ppt = &dk->part; 2461558Srgrimes 2471558Srgrimes for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 2481558Srgrimes if (strcmp(pt->name, name) == 0) { 2491558Srgrimes printf("%s in fstab more than once!\n", name); 2501558Srgrimes return; 2511558Srgrimes } 2521558Srgrimes if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 2531558Srgrimes fprintf(stderr, "out of memory"); 2541558Srgrimes exit (8); 2551558Srgrimes } 2561558Srgrimes pt = *ppt; 2571558Srgrimes if ((pt->name = malloc(strlen(name) + 1)) == NULL) { 2581558Srgrimes fprintf(stderr, "out of memory"); 2591558Srgrimes exit (8); 2601558Srgrimes } 2611558Srgrimes (void)strcpy(pt->name, name); 2621558Srgrimes if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { 2631558Srgrimes fprintf(stderr, "out of memory"); 2641558Srgrimes exit (8); 2651558Srgrimes } 2661558Srgrimes (void)strcpy(pt->fsname, fsname); 2671558Srgrimes pt->next = NULL; 2681558Srgrimes pt->auxdata = auxdata; 2691558Srgrimes} 2701558Srgrimes 2717585Sbdeint 2721558Srgrimesstartdisk(dk, checkit) 2731558Srgrimes register struct disk *dk; 2741558Srgrimes int (*checkit)(); 2751558Srgrimes{ 2761558Srgrimes register struct part *pt = dk->part; 2771558Srgrimes 2781558Srgrimes dk->pid = fork(); 2791558Srgrimes if (dk->pid < 0) { 2801558Srgrimes perror("fork"); 2811558Srgrimes return (8); 2821558Srgrimes } 2831558Srgrimes if (dk->pid == 0) 2841558Srgrimes exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 2851558Srgrimes nrun++; 2861558Srgrimes return (0); 2871558Srgrimes} 2881558Srgrimes 2891558Srgrimeschar * 2901558Srgrimesblockcheck(name) 2911558Srgrimes char *name; 2921558Srgrimes{ 2931558Srgrimes struct stat stslash, stblock, stchar; 2941558Srgrimes char *raw; 2951558Srgrimes int retried = 0; 2961558Srgrimes 2971558Srgrimes hotroot = 0; 2981558Srgrimes if (stat("/", &stslash) < 0) { 2991558Srgrimes perror("/"); 3001558Srgrimes printf("Can't stat root\n"); 3011558Srgrimes return (0); 3021558Srgrimes } 3031558Srgrimesretry: 3041558Srgrimes if (stat(name, &stblock) < 0) { 3051558Srgrimes perror(name); 3061558Srgrimes printf("Can't stat %s\n", name); 3071558Srgrimes return (0); 3081558Srgrimes } 3091558Srgrimes if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 3101558Srgrimes if (stslash.st_dev == stblock.st_rdev) 3111558Srgrimes hotroot++; 3121558Srgrimes raw = rawname(name); 3131558Srgrimes if (stat(raw, &stchar) < 0) { 3141558Srgrimes perror(raw); 3151558Srgrimes printf("Can't stat %s\n", raw); 3161558Srgrimes return (name); 3171558Srgrimes } 3181558Srgrimes if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 3191558Srgrimes return (raw); 3201558Srgrimes } else { 3211558Srgrimes printf("%s is not a character device\n", raw); 3221558Srgrimes return (name); 3231558Srgrimes } 3241558Srgrimes } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 3251558Srgrimes name = unrawname(name); 3261558Srgrimes retried++; 3271558Srgrimes goto retry; 3281558Srgrimes } 3291558Srgrimes printf("Can't make sense out of name %s\n", name); 3301558Srgrimes return (0); 3311558Srgrimes} 3321558Srgrimes 3331558Srgrimeschar * 3341558Srgrimesunrawname(name) 3351558Srgrimes char *name; 3361558Srgrimes{ 3371558Srgrimes char *dp; 3381558Srgrimes struct stat stb; 3391558Srgrimes 3401558Srgrimes if ((dp = rindex(name, '/')) == 0) 3411558Srgrimes return (name); 3421558Srgrimes if (stat(name, &stb) < 0) 3431558Srgrimes return (name); 3441558Srgrimes if ((stb.st_mode & S_IFMT) != S_IFCHR) 3451558Srgrimes return (name); 3461558Srgrimes if (dp[1] != 'r') 3471558Srgrimes return (name); 3481558Srgrimes (void)strcpy(&dp[1], &dp[2]); 3491558Srgrimes return (name); 3501558Srgrimes} 3511558Srgrimes 3521558Srgrimeschar * 3531558Srgrimesrawname(name) 3541558Srgrimes char *name; 3551558Srgrimes{ 3561558Srgrimes static char rawbuf[32]; 3571558Srgrimes char *dp; 3581558Srgrimes 3591558Srgrimes if ((dp = rindex(name, '/')) == 0) 3601558Srgrimes return (0); 3611558Srgrimes *dp = 0; 3621558Srgrimes (void)strcpy(rawbuf, name); 3631558Srgrimes *dp = '/'; 3641558Srgrimes (void)strcat(rawbuf, "/r"); 3651558Srgrimes (void)strcat(rawbuf, &dp[1]); 3661558Srgrimes return (rawbuf); 3671558Srgrimes} 368