141098Smckusick /* 261492Sbostic * Copyright (c) 1990, 1993 361492Sbostic * The Regents of the University of California. All rights reserved. 441098Smckusick * 542702Sbostic * %sccs.include.redist.c% 641098Smckusick */ 741098Smckusick 841098Smckusick #ifndef lint 9*68908Smckusick static char sccsid[] = "@(#)preen.c 8.4 (Berkeley) 04/27/95"; 1041098Smckusick #endif /* not lint */ 1141098Smckusick 1241098Smckusick #include <sys/param.h> 1341098Smckusick #include <sys/stat.h> 1441098Smckusick #include <sys/wait.h> 15*68908Smckusick 16*68908Smckusick #include <ufs/ufs/dinode.h> 17*68908Smckusick 18*68908Smckusick #include <ctype.h> 1941098Smckusick #include <fstab.h> 2042041Sbostic #include <string.h> 2141098Smckusick 22*68908Smckusick #include "fsck.h" 2341098Smckusick 2441098Smckusick struct part { 2541098Smckusick struct part *next; /* forward link of partitions on disk */ 2641098Smckusick char *name; /* device name */ 2741098Smckusick char *fsname; /* mounted filesystem name */ 2841098Smckusick long auxdata; /* auxillary data for application */ 2941098Smckusick } *badlist, **badnext = &badlist; 3041098Smckusick 3141098Smckusick struct disk { 3241098Smckusick char *name; /* disk base name */ 3341098Smckusick struct disk *next; /* forward link for list of disks */ 3441098Smckusick struct part *part; /* head of list of partitions on disk */ 3541098Smckusick int pid; /* If != 0, pid of proc working on */ 3641098Smckusick } *disks; 3741098Smckusick 3841416Smckusick int nrun, ndisks; 3941416Smckusick char hotroot; 4041098Smckusick 41*68908Smckusick static void addpart __P((char *name, char *fsname, long auxdata)); 42*68908Smckusick static struct disk *finddisk __P((char *name)); 43*68908Smckusick static char *rawname __P((char *name)); 44*68908Smckusick static int startdisk __P((struct disk *dk, 45*68908Smckusick int (*checkit)(char *, char *, long, int))); 46*68908Smckusick static char *unrawname __P((char *name)); 47*68908Smckusick 48*68908Smckusick int 4941098Smckusick checkfstab(preen, maxrun, docheck, chkit) 50*68908Smckusick int preen; 51*68908Smckusick int maxrun; 52*68908Smckusick int (*docheck)(struct fstab *); 53*68908Smckusick int (*chkit)(char *, char *, long, int); 5441098Smckusick { 5541098Smckusick register struct fstab *fsp; 5641098Smckusick register struct disk *dk, *nextdisk; 5741098Smckusick register struct part *pt; 5841098Smckusick int ret, pid, retcode, passno, sumstatus, status; 5941098Smckusick long auxdata; 6041098Smckusick char *name; 6141098Smckusick 6241098Smckusick sumstatus = 0; 6341098Smckusick for (passno = 1; passno <= 2; passno++) { 6441098Smckusick if (setfsent() == 0) { 6541098Smckusick fprintf(stderr, "Can't open checklist file: %s\n", 6641098Smckusick _PATH_FSTAB); 6741098Smckusick return (8); 6841098Smckusick } 6941098Smckusick while ((fsp = getfsent()) != 0) { 7041098Smckusick if ((auxdata = (*docheck)(fsp)) == 0) 7141098Smckusick continue; 72*68908Smckusick if (preen == 0 || 73*68908Smckusick (passno == 1 && fsp->fs_passno == 1)) { 74*68908Smckusick if ((name = blockcheck(fsp->fs_spec)) != 0) { 75*68908Smckusick if ((sumstatus = (*chkit)(name, 76*68908Smckusick fsp->fs_file, auxdata, 0)) != 0) 7741098Smckusick return (sumstatus); 7841098Smckusick } else if (preen) 7941098Smckusick return (8); 8041098Smckusick } else if (passno == 2 && fsp->fs_passno > 1) { 8141098Smckusick if ((name = blockcheck(fsp->fs_spec)) == NULL) { 8241098Smckusick fprintf(stderr, "BAD DISK NAME %s\n", 8341098Smckusick fsp->fs_spec); 8441098Smckusick sumstatus |= 8; 8541098Smckusick continue; 8641098Smckusick } 8741098Smckusick addpart(name, fsp->fs_file, auxdata); 8841098Smckusick } 8941098Smckusick } 9041098Smckusick if (preen == 0) 9141098Smckusick return (0); 9241098Smckusick } 9341098Smckusick if (preen) { 9441098Smckusick if (maxrun == 0) 9541098Smckusick maxrun = ndisks; 9641098Smckusick if (maxrun > ndisks) 9741098Smckusick maxrun = ndisks; 9841098Smckusick nextdisk = disks; 9941098Smckusick for (passno = 0; passno < maxrun; ++passno) { 100*68908Smckusick while ((ret = startdisk(nextdisk, chkit)) && nrun > 0) 10141098Smckusick sleep(10); 10241098Smckusick if (ret) 10341098Smckusick return (ret); 10441098Smckusick nextdisk = nextdisk->next; 10541098Smckusick } 10641098Smckusick while ((pid = wait(&status)) != -1) { 10741098Smckusick for (dk = disks; dk; dk = dk->next) 10841098Smckusick if (dk->pid == pid) 10941098Smckusick break; 11041098Smckusick if (dk == 0) { 11141098Smckusick printf("Unknown pid %d\n", pid); 11241098Smckusick continue; 11341098Smckusick } 11441098Smckusick if (WIFEXITED(status)) 11541098Smckusick retcode = WEXITSTATUS(status); 11641098Smckusick else 11741098Smckusick retcode = 0; 11841098Smckusick if (WIFSIGNALED(status)) { 11941098Smckusick printf("%s (%s): EXITED WITH SIGNAL %d\n", 12041098Smckusick dk->part->name, dk->part->fsname, 12141098Smckusick WTERMSIG(status)); 12241098Smckusick retcode = 8; 12341098Smckusick } 12441098Smckusick if (retcode != 0) { 12541098Smckusick sumstatus |= retcode; 12641098Smckusick *badnext = dk->part; 12741098Smckusick badnext = &dk->part->next; 12841098Smckusick dk->part = dk->part->next; 12941098Smckusick *badnext = NULL; 13041098Smckusick } else 13141098Smckusick dk->part = dk->part->next; 13241098Smckusick dk->pid = 0; 13341098Smckusick nrun--; 13441098Smckusick if (dk->part == NULL) 13541098Smckusick ndisks--; 13641098Smckusick 13741098Smckusick if (nextdisk == NULL) { 13841098Smckusick if (dk->part) { 139*68908Smckusick while ((ret = startdisk(dk, chkit)) && 14041098Smckusick nrun > 0) 14141098Smckusick sleep(10); 14241098Smckusick if (ret) 14341098Smckusick return (ret); 14441098Smckusick } 14541098Smckusick } else if (nrun < maxrun && nrun < ndisks) { 14641098Smckusick for ( ;; ) { 14741098Smckusick if ((nextdisk = nextdisk->next) == NULL) 14841098Smckusick nextdisk = disks; 14941098Smckusick if (nextdisk->part != NULL && 15041098Smckusick nextdisk->pid == 0) 15141098Smckusick break; 15241098Smckusick } 153*68908Smckusick while ((ret = startdisk(nextdisk, chkit)) && 15441098Smckusick nrun > 0) 15541098Smckusick sleep(10); 15641098Smckusick if (ret) 15741098Smckusick return (ret); 15841098Smckusick } 15941098Smckusick } 16041098Smckusick } 16141098Smckusick if (sumstatus) { 16241098Smckusick if (badlist == 0) 16341098Smckusick return (sumstatus); 16441098Smckusick fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 16541098Smckusick badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 16641098Smckusick for (pt = badlist; pt; pt = pt->next) 16741098Smckusick fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 16841098Smckusick pt->next ? ", " : "\n"); 16941098Smckusick return (sumstatus); 17041098Smckusick } 17141098Smckusick (void)endfsent(); 17241098Smckusick return (0); 17341098Smckusick } 17441098Smckusick 175*68908Smckusick static struct disk * 17641098Smckusick finddisk(name) 17741098Smckusick char *name; 17841098Smckusick { 17941098Smckusick register struct disk *dk, **dkp; 18041098Smckusick register char *p; 18144934Smckusick size_t len; 18241098Smckusick 183*68908Smckusick for (len = strlen(name), p = name + len - 1; p >= name; --p) 18441098Smckusick if (isdigit(*p)) { 18541098Smckusick len = p - name + 1; 18641098Smckusick break; 18741098Smckusick } 18841098Smckusick 18941098Smckusick for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 19041098Smckusick if (strncmp(dk->name, name, len) == 0 && 19141098Smckusick dk->name[len] == 0) 19241098Smckusick return (dk); 19341098Smckusick } 19441098Smckusick if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 19541098Smckusick fprintf(stderr, "out of memory"); 19641098Smckusick exit (8); 19741098Smckusick } 19841098Smckusick dk = *dkp; 19944934Smckusick if ((dk->name = malloc(len + 1)) == NULL) { 20041098Smckusick fprintf(stderr, "out of memory"); 20141098Smckusick exit (8); 20241098Smckusick } 20344934Smckusick (void)strncpy(dk->name, name, len); 20441098Smckusick dk->name[len] = '\0'; 20541098Smckusick dk->part = NULL; 20641098Smckusick dk->next = NULL; 20741098Smckusick dk->pid = 0; 20841098Smckusick ndisks++; 20941098Smckusick return (dk); 21041098Smckusick } 21141098Smckusick 212*68908Smckusick static void 21341098Smckusick addpart(name, fsname, auxdata) 21441098Smckusick char *name, *fsname; 21541098Smckusick long auxdata; 21641098Smckusick { 21741098Smckusick struct disk *dk = finddisk(name); 21841098Smckusick register struct part *pt, **ppt = &dk->part; 21941098Smckusick 22041098Smckusick for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 22141098Smckusick if (strcmp(pt->name, name) == 0) { 22241098Smckusick printf("%s in fstab more than once!\n", name); 22341098Smckusick return; 22441098Smckusick } 22541098Smckusick if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 22641098Smckusick fprintf(stderr, "out of memory"); 22741098Smckusick exit (8); 22841098Smckusick } 22941098Smckusick pt = *ppt; 23044934Smckusick if ((pt->name = malloc(strlen(name) + 1)) == NULL) { 23141098Smckusick fprintf(stderr, "out of memory"); 23241098Smckusick exit (8); 23341098Smckusick } 23444934Smckusick (void)strcpy(pt->name, name); 23544934Smckusick if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { 23641098Smckusick fprintf(stderr, "out of memory"); 23741098Smckusick exit (8); 23841098Smckusick } 23944934Smckusick (void)strcpy(pt->fsname, fsname); 24041098Smckusick pt->next = NULL; 24141098Smckusick pt->auxdata = auxdata; 24241098Smckusick } 24341098Smckusick 244*68908Smckusick static int 24541098Smckusick startdisk(dk, checkit) 24641098Smckusick register struct disk *dk; 247*68908Smckusick int (*checkit)(char *, char *, long, int); 24841098Smckusick { 24941098Smckusick register struct part *pt = dk->part; 25041098Smckusick 25141098Smckusick dk->pid = fork(); 25241098Smckusick if (dk->pid < 0) { 25341098Smckusick perror("fork"); 25441098Smckusick return (8); 25541098Smckusick } 25641098Smckusick if (dk->pid == 0) 25745027Skarels exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 25841098Smckusick nrun++; 25941098Smckusick return (0); 26041098Smckusick } 26141098Smckusick 26241098Smckusick char * 26368058Smckusick blockcheck(origname) 26468058Smckusick char *origname; 26541098Smckusick { 26641098Smckusick struct stat stslash, stblock, stchar; 26768058Smckusick char *newname, *raw; 26841098Smckusick int retried = 0; 26941098Smckusick 27041098Smckusick hotroot = 0; 27141098Smckusick if (stat("/", &stslash) < 0) { 27241098Smckusick perror("/"); 27341098Smckusick printf("Can't stat root\n"); 27468058Smckusick return (origname); 27541098Smckusick } 27668058Smckusick newname = origname; 27741098Smckusick retry: 27868058Smckusick if (stat(newname, &stblock) < 0) { 27968058Smckusick perror(newname); 28068058Smckusick printf("Can't stat %s\n", newname); 28168058Smckusick return (origname); 28241098Smckusick } 28341098Smckusick if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 28441098Smckusick if (stslash.st_dev == stblock.st_rdev) 28541098Smckusick hotroot++; 28668058Smckusick raw = rawname(newname); 28741098Smckusick if (stat(raw, &stchar) < 0) { 28841098Smckusick perror(raw); 28941098Smckusick printf("Can't stat %s\n", raw); 29068058Smckusick return (origname); 29141098Smckusick } 29241098Smckusick if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 29341098Smckusick return (raw); 29441098Smckusick } else { 29541098Smckusick printf("%s is not a character device\n", raw); 29668058Smckusick return (origname); 29741098Smckusick } 29841098Smckusick } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 29968058Smckusick newname = unrawname(newname); 30041098Smckusick retried++; 30141098Smckusick goto retry; 30241098Smckusick } 30368018Smckusick /* 30468018Smckusick * Not a block or character device, just return name and 30568018Smckusick * let the user decide whether to use it. 30668018Smckusick */ 30768058Smckusick return (origname); 30841098Smckusick } 30941098Smckusick 310*68908Smckusick static char * 31141098Smckusick unrawname(name) 31241098Smckusick char *name; 31341098Smckusick { 31441098Smckusick char *dp; 31541098Smckusick struct stat stb; 31641098Smckusick 31741098Smckusick if ((dp = rindex(name, '/')) == 0) 31841098Smckusick return (name); 31941098Smckusick if (stat(name, &stb) < 0) 32041098Smckusick return (name); 32141098Smckusick if ((stb.st_mode & S_IFMT) != S_IFCHR) 32241098Smckusick return (name); 32347578Smckusick if (dp[1] != 'r') 32441098Smckusick return (name); 32547578Smckusick (void)strcpy(&dp[1], &dp[2]); 32641098Smckusick return (name); 32741098Smckusick } 32841098Smckusick 329*68908Smckusick static char * 33041098Smckusick rawname(name) 33141098Smckusick char *name; 33241098Smckusick { 33341098Smckusick static char rawbuf[32]; 33441098Smckusick char *dp; 33541098Smckusick 33641098Smckusick if ((dp = rindex(name, '/')) == 0) 33741098Smckusick return (0); 33841098Smckusick *dp = 0; 33941098Smckusick (void)strcpy(rawbuf, name); 34041098Smckusick *dp = '/'; 34141098Smckusick (void)strcat(rawbuf, "/r"); 34247578Smckusick (void)strcat(rawbuf, &dp[1]); 34341098Smckusick return (rawbuf); 34441098Smckusick } 345