From 5211717fe967b84be3cf1852cd60a0a19a21bf50 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Fri, 27 Apr 1990 06:41:39 -0800 Subject: [PATCH] date and time created 90/04/26 23:41:39 by mckusick SCCS-vsn: sbin/fsck/preen.c 5.1 --- usr/src/sbin/fsck/preen.c | 336 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 usr/src/sbin/fsck/preen.c diff --git a/usr/src/sbin/fsck/preen.c b/usr/src/sbin/fsck/preen.c new file mode 100644 index 0000000000..77aa72d0f4 --- /dev/null +++ b/usr/src/sbin/fsck/preen.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)preen.c 5.1 (Berkeley) %G%"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +char *rawname(), *unrawname(), *blockcheck(), *malloc(); + +struct part { + struct part *next; /* forward link of partitions on disk */ + char *name; /* device name */ + char *fsname; /* mounted filesystem name */ + long auxdata; /* auxillary data for application */ +} *badlist, **badnext = &badlist; + +struct disk { + char *name; /* disk base name */ + struct disk *next; /* forward link for list of disks */ + struct part *part; /* head of list of partitions on disk */ + int pid; /* If != 0, pid of proc working on */ +} *disks; + +int nrun, ndisks, hotroot; + +checkfstab(preen, maxrun, docheck, chkit) + int preen, maxrun; + int (*docheck)(), (*chkit)(); +{ + register struct fstab *fsp; + register struct disk *dk, *nextdisk; + register struct part *pt; + int ret, pid, retcode, passno, sumstatus, status; + long auxdata; + char *name; + + sumstatus = 0; + for (passno = 1; passno <= 2; passno++) { + if (setfsent() == 0) { + fprintf(stderr, "Can't open checklist file: %s\n", + _PATH_FSTAB); + return (8); + } + while ((fsp = getfsent()) != 0) { + if ((auxdata = (*docheck)(fsp)) == 0) + continue; + if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { + if (name = blockcheck(fsp->fs_spec)) { + if (sumstatus = (*chkit)(name, + fsp->fs_file, auxdata)) + return (sumstatus); + } else if (preen) + return (8); + } else if (passno == 2 && fsp->fs_passno > 1) { + if ((name = blockcheck(fsp->fs_spec)) == NULL) { + fprintf(stderr, "BAD DISK NAME %s\n", + fsp->fs_spec); + sumstatus |= 8; + continue; + } + addpart(name, fsp->fs_file, auxdata); + } + } + if (preen == 0) + return (0); + } + if (preen) { + if (maxrun == 0) + maxrun = ndisks; + if (maxrun > ndisks) + maxrun = ndisks; + nextdisk = disks; + for (passno = 0; passno < maxrun; ++passno) { + while (ret = startdisk(nextdisk, chkit) && nrun > 0) + sleep(10); + if (ret) + return (ret); + nextdisk = nextdisk->next; + } + while ((pid = wait(&status)) != -1) { + for (dk = disks; dk; dk = dk->next) + if (dk->pid == pid) + break; + if (dk == 0) { + printf("Unknown pid %d\n", pid); + continue; + } + if (WIFEXITED(status)) + retcode = WEXITSTATUS(status); + else + retcode = 0; + if (WIFSIGNALED(status)) { + printf("%s (%s): EXITED WITH SIGNAL %d\n", + dk->part->name, dk->part->fsname, + WTERMSIG(status)); + retcode = 8; + } + if (retcode != 0) { + sumstatus |= retcode; + *badnext = dk->part; + badnext = &dk->part->next; + dk->part = dk->part->next; + *badnext = NULL; + } else + dk->part = dk->part->next; + dk->pid = 0; + nrun--; + if (dk->part == NULL) + ndisks--; + + if (nextdisk == NULL) { + if (dk->part) { + while (ret = startdisk(dk, chkit) && + nrun > 0) + sleep(10); + if (ret) + return (ret); + } + } else if (nrun < maxrun && nrun < ndisks) { + for ( ;; ) { + if ((nextdisk = nextdisk->next) == NULL) + nextdisk = disks; + if (nextdisk->part != NULL && + nextdisk->pid == 0) + break; + } + while (ret = startdisk(nextdisk, chkit) && + nrun > 0) + sleep(10); + if (ret) + return (ret); + } + } + } + if (sumstatus) { + if (badlist == 0) + return (sumstatus); + fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", + badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); + for (pt = badlist; pt; pt = pt->next) + fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, + pt->next ? ", " : "\n"); + return (sumstatus); + } + (void)endfsent(); + return (0); +} + +struct disk * +finddisk(name) + char *name; +{ + register struct disk *dk, **dkp; + register char *p; + int len; + + for (p = name + strlen(name) - 1; p >= name; --p) + if (isdigit(*p)) { + len = p - name + 1; + break; + } + if (p < name) + len = strlen(name); + + for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { + if (strncmp(dk->name, name, len) == 0 && + dk->name[len] == 0) + return (dk); + } + if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + dk = *dkp; + if ((dk->name = malloc((unsigned int)len + 1)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + strncpy(dk->name, name, len); + dk->name[len] = '\0'; + dk->part = NULL; + dk->next = NULL; + dk->pid = 0; + ndisks++; + return (dk); +} + +addpart(name, fsname, auxdata) + char *name, *fsname; + long auxdata; +{ + struct disk *dk = finddisk(name); + register struct part *pt, **ppt = &dk->part; + + for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) + if (strcmp(pt->name, name) == 0) { + printf("%s in fstab more than once!\n", name); + return; + } + if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + pt = *ppt; + if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + strcpy(pt->name, name); + if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL) { + fprintf(stderr, "out of memory"); + exit (8); + } + strcpy(pt->fsname, fsname); + pt->next = NULL; + pt->auxdata = auxdata; +} + +startdisk(dk, checkit) + register struct disk *dk; + int (*checkit)(); +{ + register struct part *pt = dk->part; + + dk->pid = fork(); + if (dk->pid < 0) { + perror("fork"); + return (8); + } + if (dk->pid == 0) + exit((*checkit)(pt->name, pt->fsname, pt->auxdata)); + nrun++; + return (0); +} + +char * +blockcheck(name) + char *name; +{ + struct stat stslash, stblock, stchar; + char *raw; + int retried = 0; + + hotroot = 0; + if (stat("/", &stslash) < 0) { + perror("/"); + printf("Can't stat root\n"); + return (0); + } +retry: + if (stat(name, &stblock) < 0) { + perror(name); + printf("Can't stat %s\n", name); + return (0); + } + if ((stblock.st_mode & S_IFMT) == S_IFBLK) { + if (stslash.st_dev == stblock.st_rdev) + hotroot++; + raw = rawname(name); + if (stat(raw, &stchar) < 0) { + perror(raw); + printf("Can't stat %s\n", raw); + return (name); + } + if ((stchar.st_mode & S_IFMT) == S_IFCHR) { + return (raw); + } else { + printf("%s is not a character device\n", raw); + return (name); + } + } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { + name = unrawname(name); + retried++; + goto retry; + } + printf("Can't make sense out of name %s\n", name); + return (0); +} + +char * +unrawname(name) + char *name; +{ + char *dp; + struct stat stb; + + if ((dp = rindex(name, '/')) == 0) + return (name); + if (stat(name, &stb) < 0) + return (name); + if ((stb.st_mode & S_IFMT) != S_IFCHR) + return (name); + if (*(dp + 1) != 'r') + return (name); + (void)strcpy(dp + 1, dp + 2); + return (name); +} + +char * +rawname(name) + char *name; +{ + static char rawbuf[32]; + char *dp; + + if ((dp = rindex(name, '/')) == 0) + return (0); + *dp = 0; + (void)strcpy(rawbuf, name); + *dp = '/'; + (void)strcat(rawbuf, "/r"); + (void)strcat(rawbuf, dp + 1); + return (rawbuf); +} -- 2.20.1