141098Smckusick /* 241098Smckusick * Copyright (c) 1990 The Regents of the University of California. 341098Smckusick * All rights reserved. 441098Smckusick * 5*42702Sbostic * %sccs.include.redist.c% 641098Smckusick */ 741098Smckusick 841098Smckusick #ifndef lint 9*42702Sbostic static char sccsid[] = "@(#)preen.c 5.4 (Berkeley) 06/01/90"; 1041098Smckusick #endif /* not lint */ 1141098Smckusick 1241098Smckusick #include <sys/param.h> 1341098Smckusick #include <sys/stat.h> 1441098Smckusick #include <sys/wait.h> 1541098Smckusick #include <fstab.h> 1642041Sbostic #include <string.h> 1741098Smckusick #include <stdio.h> 1841098Smckusick #include <ctype.h> 1941098Smckusick 2041098Smckusick char *rawname(), *unrawname(), *blockcheck(), *malloc(); 2141098Smckusick 2241098Smckusick struct part { 2341098Smckusick struct part *next; /* forward link of partitions on disk */ 2441098Smckusick char *name; /* device name */ 2541098Smckusick char *fsname; /* mounted filesystem name */ 2641098Smckusick long auxdata; /* auxillary data for application */ 2741098Smckusick } *badlist, **badnext = &badlist; 2841098Smckusick 2941098Smckusick struct disk { 3041098Smckusick char *name; /* disk base name */ 3141098Smckusick struct disk *next; /* forward link for list of disks */ 3241098Smckusick struct part *part; /* head of list of partitions on disk */ 3341098Smckusick int pid; /* If != 0, pid of proc working on */ 3441098Smckusick } *disks; 3541098Smckusick 3641416Smckusick int nrun, ndisks; 3741416Smckusick char hotroot; 3841098Smckusick 3941098Smckusick checkfstab(preen, maxrun, docheck, chkit) 4041098Smckusick int preen, maxrun; 4141098Smckusick int (*docheck)(), (*chkit)(); 4241098Smckusick { 4341098Smckusick register struct fstab *fsp; 4441098Smckusick register struct disk *dk, *nextdisk; 4541098Smckusick register struct part *pt; 4641098Smckusick int ret, pid, retcode, passno, sumstatus, status; 4741098Smckusick long auxdata; 4841098Smckusick char *name; 4941098Smckusick 5041098Smckusick sumstatus = 0; 5141098Smckusick for (passno = 1; passno <= 2; passno++) { 5241098Smckusick if (setfsent() == 0) { 5341098Smckusick fprintf(stderr, "Can't open checklist file: %s\n", 5441098Smckusick _PATH_FSTAB); 5541098Smckusick return (8); 5641098Smckusick } 5741098Smckusick while ((fsp = getfsent()) != 0) { 5841098Smckusick if ((auxdata = (*docheck)(fsp)) == 0) 5941098Smckusick continue; 6041098Smckusick if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { 6141098Smckusick if (name = blockcheck(fsp->fs_spec)) { 6241098Smckusick if (sumstatus = (*chkit)(name, 6341098Smckusick fsp->fs_file, auxdata)) 6441098Smckusick return (sumstatus); 6541098Smckusick } else if (preen) 6641098Smckusick return (8); 6741098Smckusick } else if (passno == 2 && fsp->fs_passno > 1) { 6841098Smckusick if ((name = blockcheck(fsp->fs_spec)) == NULL) { 6941098Smckusick fprintf(stderr, "BAD DISK NAME %s\n", 7041098Smckusick fsp->fs_spec); 7141098Smckusick sumstatus |= 8; 7241098Smckusick continue; 7341098Smckusick } 7441098Smckusick addpart(name, fsp->fs_file, auxdata); 7541098Smckusick } 7641098Smckusick } 7741098Smckusick if (preen == 0) 7841098Smckusick return (0); 7941098Smckusick } 8041098Smckusick if (preen) { 8141098Smckusick if (maxrun == 0) 8241098Smckusick maxrun = ndisks; 8341098Smckusick if (maxrun > ndisks) 8441098Smckusick maxrun = ndisks; 8541098Smckusick nextdisk = disks; 8641098Smckusick for (passno = 0; passno < maxrun; ++passno) { 8741098Smckusick while (ret = startdisk(nextdisk, chkit) && nrun > 0) 8841098Smckusick sleep(10); 8941098Smckusick if (ret) 9041098Smckusick return (ret); 9141098Smckusick nextdisk = nextdisk->next; 9241098Smckusick } 9341098Smckusick while ((pid = wait(&status)) != -1) { 9441098Smckusick for (dk = disks; dk; dk = dk->next) 9541098Smckusick if (dk->pid == pid) 9641098Smckusick break; 9741098Smckusick if (dk == 0) { 9841098Smckusick printf("Unknown pid %d\n", pid); 9941098Smckusick continue; 10041098Smckusick } 10141098Smckusick if (WIFEXITED(status)) 10241098Smckusick retcode = WEXITSTATUS(status); 10341098Smckusick else 10441098Smckusick retcode = 0; 10541098Smckusick if (WIFSIGNALED(status)) { 10641098Smckusick printf("%s (%s): EXITED WITH SIGNAL %d\n", 10741098Smckusick dk->part->name, dk->part->fsname, 10841098Smckusick WTERMSIG(status)); 10941098Smckusick retcode = 8; 11041098Smckusick } 11141098Smckusick if (retcode != 0) { 11241098Smckusick sumstatus |= retcode; 11341098Smckusick *badnext = dk->part; 11441098Smckusick badnext = &dk->part->next; 11541098Smckusick dk->part = dk->part->next; 11641098Smckusick *badnext = NULL; 11741098Smckusick } else 11841098Smckusick dk->part = dk->part->next; 11941098Smckusick dk->pid = 0; 12041098Smckusick nrun--; 12141098Smckusick if (dk->part == NULL) 12241098Smckusick ndisks--; 12341098Smckusick 12441098Smckusick if (nextdisk == NULL) { 12541098Smckusick if (dk->part) { 12641098Smckusick while (ret = startdisk(dk, chkit) && 12741098Smckusick nrun > 0) 12841098Smckusick sleep(10); 12941098Smckusick if (ret) 13041098Smckusick return (ret); 13141098Smckusick } 13241098Smckusick } else if (nrun < maxrun && nrun < ndisks) { 13341098Smckusick for ( ;; ) { 13441098Smckusick if ((nextdisk = nextdisk->next) == NULL) 13541098Smckusick nextdisk = disks; 13641098Smckusick if (nextdisk->part != NULL && 13741098Smckusick nextdisk->pid == 0) 13841098Smckusick break; 13941098Smckusick } 14041098Smckusick while (ret = startdisk(nextdisk, chkit) && 14141098Smckusick nrun > 0) 14241098Smckusick sleep(10); 14341098Smckusick if (ret) 14441098Smckusick return (ret); 14541098Smckusick } 14641098Smckusick } 14741098Smckusick } 14841098Smckusick if (sumstatus) { 14941098Smckusick if (badlist == 0) 15041098Smckusick return (sumstatus); 15141098Smckusick fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 15241098Smckusick badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 15341098Smckusick for (pt = badlist; pt; pt = pt->next) 15441098Smckusick fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 15541098Smckusick pt->next ? ", " : "\n"); 15641098Smckusick return (sumstatus); 15741098Smckusick } 15841098Smckusick (void)endfsent(); 15941098Smckusick return (0); 16041098Smckusick } 16141098Smckusick 16241098Smckusick struct disk * 16341098Smckusick finddisk(name) 16441098Smckusick char *name; 16541098Smckusick { 16641098Smckusick register struct disk *dk, **dkp; 16741098Smckusick register char *p; 16841098Smckusick int len; 16941098Smckusick 17041098Smckusick for (p = name + strlen(name) - 1; p >= name; --p) 17141098Smckusick if (isdigit(*p)) { 17241098Smckusick len = p - name + 1; 17341098Smckusick break; 17441098Smckusick } 17541098Smckusick if (p < name) 17641098Smckusick len = strlen(name); 17741098Smckusick 17841098Smckusick for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 17941098Smckusick if (strncmp(dk->name, name, len) == 0 && 18041098Smckusick dk->name[len] == 0) 18141098Smckusick return (dk); 18241098Smckusick } 18341098Smckusick if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 18441098Smckusick fprintf(stderr, "out of memory"); 18541098Smckusick exit (8); 18641098Smckusick } 18741098Smckusick dk = *dkp; 18841098Smckusick if ((dk->name = malloc((unsigned int)len + 1)) == NULL) { 18941098Smckusick fprintf(stderr, "out of memory"); 19041098Smckusick exit (8); 19141098Smckusick } 19241098Smckusick strncpy(dk->name, name, len); 19341098Smckusick dk->name[len] = '\0'; 19441098Smckusick dk->part = NULL; 19541098Smckusick dk->next = NULL; 19641098Smckusick dk->pid = 0; 19741098Smckusick ndisks++; 19841098Smckusick return (dk); 19941098Smckusick } 20041098Smckusick 20141098Smckusick addpart(name, fsname, auxdata) 20241098Smckusick char *name, *fsname; 20341098Smckusick long auxdata; 20441098Smckusick { 20541098Smckusick struct disk *dk = finddisk(name); 20641098Smckusick register struct part *pt, **ppt = &dk->part; 20741098Smckusick 20841098Smckusick for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 20941098Smckusick if (strcmp(pt->name, name) == 0) { 21041098Smckusick printf("%s in fstab more than once!\n", name); 21141098Smckusick return; 21241098Smckusick } 21341098Smckusick if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 21441098Smckusick fprintf(stderr, "out of memory"); 21541098Smckusick exit (8); 21641098Smckusick } 21741098Smckusick pt = *ppt; 21841098Smckusick if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL) { 21941098Smckusick fprintf(stderr, "out of memory"); 22041098Smckusick exit (8); 22141098Smckusick } 22241098Smckusick strcpy(pt->name, name); 22341098Smckusick if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL) { 22441098Smckusick fprintf(stderr, "out of memory"); 22541098Smckusick exit (8); 22641098Smckusick } 22741098Smckusick strcpy(pt->fsname, fsname); 22841098Smckusick pt->next = NULL; 22941098Smckusick pt->auxdata = auxdata; 23041098Smckusick } 23141098Smckusick 23241098Smckusick startdisk(dk, checkit) 23341098Smckusick register struct disk *dk; 23441098Smckusick int (*checkit)(); 23541098Smckusick { 23641098Smckusick register struct part *pt = dk->part; 23741098Smckusick 23841098Smckusick dk->pid = fork(); 23941098Smckusick if (dk->pid < 0) { 24041098Smckusick perror("fork"); 24141098Smckusick return (8); 24241098Smckusick } 24341098Smckusick if (dk->pid == 0) 24441098Smckusick exit((*checkit)(pt->name, pt->fsname, pt->auxdata)); 24541098Smckusick nrun++; 24641098Smckusick return (0); 24741098Smckusick } 24841098Smckusick 24941098Smckusick char * 25041098Smckusick blockcheck(name) 25141098Smckusick char *name; 25241098Smckusick { 25341098Smckusick struct stat stslash, stblock, stchar; 25441098Smckusick char *raw; 25541098Smckusick int retried = 0; 25641098Smckusick 25741098Smckusick hotroot = 0; 25841098Smckusick if (stat("/", &stslash) < 0) { 25941098Smckusick perror("/"); 26041098Smckusick printf("Can't stat root\n"); 26141098Smckusick return (0); 26241098Smckusick } 26341098Smckusick retry: 26441098Smckusick if (stat(name, &stblock) < 0) { 26541098Smckusick perror(name); 26641098Smckusick printf("Can't stat %s\n", name); 26741098Smckusick return (0); 26841098Smckusick } 26941098Smckusick if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 27041098Smckusick if (stslash.st_dev == stblock.st_rdev) 27141098Smckusick hotroot++; 27241098Smckusick raw = rawname(name); 27341098Smckusick if (stat(raw, &stchar) < 0) { 27441098Smckusick perror(raw); 27541098Smckusick printf("Can't stat %s\n", raw); 27641098Smckusick return (name); 27741098Smckusick } 27841098Smckusick if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 27941098Smckusick return (raw); 28041098Smckusick } else { 28141098Smckusick printf("%s is not a character device\n", raw); 28241098Smckusick return (name); 28341098Smckusick } 28441098Smckusick } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 28541098Smckusick name = unrawname(name); 28641098Smckusick retried++; 28741098Smckusick goto retry; 28841098Smckusick } 28941098Smckusick printf("Can't make sense out of name %s\n", name); 29041098Smckusick return (0); 29141098Smckusick } 29241098Smckusick 29341098Smckusick char * 29441098Smckusick unrawname(name) 29541098Smckusick char *name; 29641098Smckusick { 29741098Smckusick char *dp; 29841098Smckusick struct stat stb; 29941098Smckusick 30041098Smckusick if ((dp = rindex(name, '/')) == 0) 30141098Smckusick return (name); 30241098Smckusick if (stat(name, &stb) < 0) 30341098Smckusick return (name); 30441098Smckusick if ((stb.st_mode & S_IFMT) != S_IFCHR) 30541098Smckusick return (name); 30641098Smckusick if (*(dp + 1) != 'r') 30741098Smckusick return (name); 30841098Smckusick (void)strcpy(dp + 1, dp + 2); 30941098Smckusick return (name); 31041098Smckusick } 31141098Smckusick 31241098Smckusick char * 31341098Smckusick rawname(name) 31441098Smckusick char *name; 31541098Smckusick { 31641098Smckusick static char rawbuf[32]; 31741098Smckusick char *dp; 31841098Smckusick 31941098Smckusick if ((dp = rindex(name, '/')) == 0) 32041098Smckusick return (0); 32141098Smckusick *dp = 0; 32241098Smckusick (void)strcpy(rawbuf, name); 32341098Smckusick *dp = '/'; 32441098Smckusick (void)strcat(rawbuf, "/r"); 32541098Smckusick (void)strcat(rawbuf, dp + 1); 32641098Smckusick return (rawbuf); 32741098Smckusick } 328