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