fred@umcp-cs.UUCP (06/23/83)
This program runs under 4.1BSD. It reads your /etc/fstab file and starts an ``fsck -p'' on each file system which is normally mounted read-writable. This is the same thing which fsck would do anyway, except that it would do them each in sequence. Preen forks separate processes, so the fsck's are running in parallel. This can speed up reboots & such, since fsck spends most of its time thrashing the disk head around, it's not really tying down the CPU, so you might as well run other fsck's at the same time and let them thrash their assigned disk heads around. The reason I didn't hack it directly into fsck is that: 1) I don't understand fsck, and 2) There's no headache of re-implementing it in future releases of fsck. : Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH /bin/echo 'Extracting preen.8l' sed 's/^X//' <<'//go.sysin dd *' >preen.8l X.TH PREEN 8l "11-Jan-83 (U of Maryland)" X.UC 4 X.SH NAME Xpreen \- automatic file system consistency check using fsck X.SH SYNOPSIS X.B /etc/preen X.SH DESCRIPTION X.I Preen Xis intended to be invoked from X.I /etc/rc. XIt invokes X.I /etc/fsck -p Xon all normally read-write mounted file systems, as defined in the file X.I /etc/fstab. X.I Fsck X``preens'' the file system, cleaning up trivial inconsistencies. X.I Preen Xdoes the root file system first, then the raw versions of all the others, Xin parallel. XThis speeds up automatic reboots, since it keeps more than one disk head Xmoving at a time, which X.I fsck Xdoesn't normally do. XEach individual invocation of X.I fsck Xspends most of its time waiting for disk seeks, so having multiple Xinvocations on separate drives makes more efficient use of the processor. X.sp XIf any of the X.I fsck\c Xs exit with an abnormal return status, X.I preen Xwill also, causing an automatic reboot to fail. X.PP X.SH FILES X.br X.ns X.TP 21 X/etc/fstab Xcontains default list of file systems to check. X.TP 21 X/etc/fsck Xexecutable disk patcher program. X.SH DIAGNOSTICS XThe diagnostics produced by X.I preen Xare intended to be self-explanatory. X.SH "SEE ALSO" Xfsck(8), fstab(5), fs(5), crash(8), reboot(8) X.SH BUGS //go.sysin dd * /bin/chmod 644 preen.8l /bin/echo -n ' '; /bin/ls -ld preen.8l /bin/echo 'Extracting preen.c' sed 's/^X//' <<'//go.sysin dd *' >preen.c X#ifndef lint Xstatic char *sccsid = "@(#)preen.c (U of Maryland - FLB) $Header: /usr/fred/sys/preen.c,v 1.2 83/06/22 17:58:46 fred Exp $"; X#endif lint X X/* X * preen - Run ``fsck -p'' on disks. Root file system first, then others in X * parallel. Device names, other than root, are converted to the raw X * device name by converting ``/dev/'' to ``/dev/r''. Error status X * from any instance of ``fsck'' is returned as the exit status of X * this program. Preen is intended to be invoked from ``/etc/rc''. X * X * To compile: X * cc -s -O preen.c -o preen X * or: X * cc -s -O -DDEBUG preen.c -o preen X * for debugging. X * X * Fred Blonder, University of Maryland, College Park, Md. <fred@umcp-cs> X * X * $Log: preen.c,v $ X * Revision 1.2 83/06/22 17:58:46 fred X * Bug causing short lines in fstab to cause the remainder of the file X * to be ignored, fixed by Chris Torek. X * X * X */ X X#include <stdio.h> X#include <fstab.h> X#include <sys/types.h> X#include <sys/dir.h> X X#ifdef DEBUG X#undef FSTAB X#define FSTAB "fstab" X#define FSCK "/bin/echo" X#else X#define FSCK "/etc/fsck" X#endif X X#define MODE_LENGTH 3 X Xmain() X{ XFILE *fstab; Xchar device[FSNMLG], file[FSNMLG], mode[MODE_LENGTH], *sbrk(); Xchar linebuf[BUFSIZ]; Xstruct fs_buf { X char fs_device[FSNMLG]; X char fs_file[FSNMLG]; X char fs_mode[MODE_LENGTH]; X struct fs_buf *fs_next; X } *fs_list = (struct fs_buf *)0, *fs_tmp; Xint status, pid, value = 0; X Xif ((fstab = fopen(FSTAB, "r")) == NULL) { X fprintf(stderr, "Can't read ``%s''\n", FSTAB); X exit(1); X } X Xwhile (fgets(linebuf, sizeof(linebuf), fstab)) { X if (sscanf(linebuf, "%[^:]:%[^:]:%[^:]:%*[^\n]\n", X device, file, mode) == 3) { X fs_tmp = (struct fs_buf *) sbrk(sizeof(struct fs_buf)); X strncpy(fs_tmp->fs_device, device, sizeof(device)); X strncpy(fs_tmp->fs_file, file, sizeof(file)); X strncpy(fs_tmp->fs_mode, mode, sizeof(mode)); X fs_tmp->fs_next = fs_list; X fs_list = fs_tmp; X } X } X Xfor (fs_tmp = fs_list; fs_tmp && strcmp(fs_tmp->fs_file, "/"); X fs_tmp = fs_tmp->fs_next); X Xif (!fs_tmp) { X fprintf(stderr, "Can't find root file system\n"); X exit(1); X } X Xif (!(pid = fork())) { X printf("Checking root file system (%s):\n", fs_tmp->fs_device); X execl(FSCK, "fsck", "-p", fs_tmp->fs_device, 0); X fprintf(stderr, "Can't exec fsck\n"); X exit(1); X } X Xif (pid < 0) { X perror("fork error"); X exit(1); X } X Xwhile (wait(&status) != pid); X Xif (status) X exit(status >> 8); X Xprintf("Root ok. Checking other disks"); Xfor (fs_tmp = fs_list; fs_tmp; fs_tmp = fs_tmp->fs_next) X if (strcmp(fs_tmp->fs_file, "/") X && !strcmp(fs_tmp->fs_mode, FSTAB_RW)) { X make_raw(fs_tmp->fs_device); X printf(" (%s)", fs_tmp->fs_device); X (void) fflush(stdout); X } Xprintf(":\n"); X Xfor (fs_tmp = fs_list; fs_tmp; fs_tmp = fs_tmp->fs_next) X if (strcmp(fs_tmp->fs_file, "/") X && !strcmp(fs_tmp->fs_mode, FSTAB_RW)) { X if ((pid = fork()) == 0) { X execl(FSCK, "fsck", "-p", fs_tmp->fs_device, 0); X fprintf(stderr, "Can't exec fsck\n"); X exit(1); X } X else if (pid < 0) { X fprintf(stderr, "Can't fork\n"); X exit(1); X } X } X Xwhile (wait(&status) >= 0) X if (status) X value = status >> 8; X Xif (!value) X printf("Other disks ok.\n"); X Xexit(value); X} X Xmake_raw(dev_name) /* Make raw device name by inserting an ``r'' after */ Xchar dev_name[]; /* the last ``/'' in the device name. */ X{ Xregister char *cp, *cp1; Xchar *rindex(); X X/* find the last slash */ Xif (!(cp = rindex(dev_name, '/'))) { X fprintf(stderr, "\nWierd device name ``%s'' in %s\n", dev_name, FSTAB); X exit(1); X } X Xfor (cp1 = dev_name; *cp1; cp1++); /* find the trailing null */ X Xif (cp1 > &cp[DIRSIZ]) /* if file name already max length */ X return; /* . . . don't do anything */ X Xfor (;cp1 > cp; cp1--) /* bump everything to the right of */ X cp1[1] = *cp1; /* the slash right by one char */ X Xcp[1] = 'r'; /* insert the ``r'' */ X} //go.sysin dd * /bin/chmod 644 preen.c /bin/echo -n ' '; /bin/ls -ld preen.c