Subject: Progress meter for fsck, revisited
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@netbsd.org>
From: Jason Thorpe <thorpej@wasabisystems.com>
List: tech-userlevel
Date: 01/13/2004 13:20:41
--Apple-Mail-11--915122932
Content-Type: multipart/mixed; boundary=Apple-Mail-10--915122938


--Apple-Mail-10--915122938
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Folks...

I have a need for fsck progress meters in a couple of applications, so 
I decided to revisit the patches Chris Gilbert produced a while ago.

These patches are based on his, but have some changes:

	- -P is used to explicitly enable the progress meter.  The default
	  behavior of no progress meter is left intact.

	- If -P is specified, then the master fsck process disables 
parallelization
	  so that the meter output does not interfere with each other.

	- The progress meter is erased after reaching 100%, so that the
	  output when fsck is completed looks identical to if progress
	  meters were not used.

	- For preen, a single overall progress meter is used, rather than
	  one for each pass.

	- The code is sharable by fsck utilities other than fsck_ffs.

	- The code can be compiled out using -DSMALL.

If these patches look OK, I'll go ahead and check them in.

         -- Jason R. Thorpe <thorpej@wasabisystems.com>

--Apple-Mail-10--915122938
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name="progress-patch.txt"
Content-Disposition: attachment;
	filename=progress-patch.txt

Index: fsck/Makefile
===================================================================
RCS file: /cvsroot/src/sbin/fsck/Makefile,v
retrieving revision 1.15
diff -u -r1.15 Makefile
--- fsck/Makefile	23 Aug 2002 03:19:07 -0000	1.15
+++ fsck/Makefile	13 Jan 2004 21:18:53 -0000
@@ -4,6 +4,10 @@
 SRCS=	fsck.c fsutil.c preen.c
 MAN=	fsck.8
 
+# NOTE: progress.c is intentionally left out.  However, that file is not
+# file-system specific, so we place it here so that fsck programs for
+# all file systems may use the code.
+
 .if defined(RESCUEDIR)
 CPPFLAGS+= -D_PATH_RESCUE=\"${RESCUEDIR}\"
 .endif
Index: fsck/fsck.8
===================================================================
RCS file: /cvsroot/src/sbin/fsck/fsck.8,v
retrieving revision 1.29
diff -u -r1.29 fsck.8
--- fsck/fsck.8	20 Oct 2003 12:04:38 -0000	1.29
+++ fsck/fsck.8	13 Jan 2004 21:18:53 -0000
@@ -35,7 +35,7 @@
 .Nd file system consistency check and interactive repair
 .Sh SYNOPSIS
 .Nm
-.Op Fl dfnpqvy
+.Op Fl dfnpPqvy
 .Op Fl l Ar maxparallel
 .Op Fl t Ar fstype
 .Op Fl T Ar fstype:fsoptions
@@ -101,6 +101,10 @@
 .Xr exit 3
 code, so as to alert any invoking program or script that human
 intervention is required.
+.It Fl P
+Display a progress meter for each file system check.
+This option also disables parallel checking.
+Note that progress meters are not supported by all file system types.
 .It Fl q
 Quiet mode, do not output any messages for clean filesystems.
 .It Fl t Ar fstype
Index: fsck/fsck.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck/fsck.c,v
retrieving revision 1.32
diff -u -r1.32 fsck.c
--- fsck/fsck.c	5 Jan 2004 23:23:32 -0000	1.32
+++ fsck/fsck.c	13 Jan 2004 21:18:54 -0000
@@ -156,6 +156,10 @@
 			flags |= CHECK_PREEN;
 			break;
 
+		case 'P':
+			flags |= CHECK_PROGRESS;
+			break;
+
 		case 'q':
 			break;
 
@@ -194,6 +198,17 @@
 		catopt(&options, globopt);
 	}
 
+	/* Don't do progress meters if we're debugging. */
+	if (flags & CHECK_DEBUG)
+		flags &= ~CHECK_PROGRESS;
+
+	/*
+	 * If progress meters are being used, force max parallel to 1
+	 * so the progress meter outputs don't interfere with one another.
+	 */
+	if (flags & CHECK_PROGRESS)
+		maxrun = 1;
+
 	argc -= optind;
 	argv += optind;
 
Index: fsck/fsutil.h
===================================================================
RCS file: /cvsroot/src/sbin/fsck/fsutil.h,v
retrieving revision 1.8
diff -u -r1.8 fsutil.h
--- fsck/fsutil.h	28 Mar 2003 08:12:38 -0000	1.8
+++ fsck/fsutil.h	13 Jan 2004 21:18:54 -0000
@@ -55,6 +55,7 @@
 #define	CHECK_VERBOSE	2
 #define	CHECK_DEBUG	4
 #define	CHECK_FORCE	8
+#define	CHECK_PROGRESS	16
 
 struct fstab;
 int checkfstab(int, int, void *(*)(struct fstab *), 
Index: fsck/progress.c
===================================================================
RCS file: fsck/progress.c
diff -N fsck/progress.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fsck/progress.c	13 Jan 2004 21:18:54 -0000
@@ -0,0 +1,141 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn; by Chris Gilbert; and by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SMALL
+
+/*
+ * File system independent fsck progress bar routines.
+ */
+
+#include <sys/param.h>
+#include <sys/tty.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "progress.h"
+
+static int	ttywidth = 80;
+
+int	progress;
+long	progress_current;
+long	progress_total;
+
+#define	BUFLEFT		(sizeof(buf) - len)
+
+void
+progressbar(const char *dev, const char *label, long current, long total)
+{
+	static int lastpercentage = -1;
+	char buf[256];
+	int len, percentage;
+	int barlength;
+	int i;
+	int lengthextras;
+
+#define	BAROVERHEAD	10	/* non-* portion of progress bar */
+
+	/*
+	 * starts should contain at least sizeof(buf) - BAROVERHEAD
+	 * entries.
+	 */
+	static const char stars[] =
+"*****************************************************************************"
+"*****************************************************************************"
+"*****************************************************************************";
+
+	if (progress == 0)
+		return;
+
+	current += progress_current;
+	total += progress_total;
+
+	len = 0;
+	lengthextras = strlen(dev) + (label != NULL ? strlen(label) : 0);
+	percentage = (current * 100) / total;
+	percentage = MAX(percentage, 0);
+	percentage = MIN(percentage, 100);
+
+	if (percentage == lastpercentage)
+		return;
+	lastpercentage = percentage;
+
+	len += snprintf(buf + len, BUFLEFT, "%s: ", dev);
+	if (label != NULL)
+		len += snprintf(buf + len, BUFLEFT, "%s ", label);
+
+	barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD - lengthextras;
+	if (barlength > 0) {
+		i = barlength * percentage / 100;
+		len += snprintf(buf + len, BUFLEFT,
+		    "|%.*s%*s| ", i, stars, barlength - i, "");
+	}
+	len += snprintf(buf + len, BUFLEFT, "%3d%%\r", percentage);
+	write(fileno(stdout), buf, len);
+}
+
+void
+progressdone(void)
+{
+	char buf[256];
+	int len;
+
+	len = MIN(sizeof(buf) - 2, ttywidth);
+	memset(buf, ' ', len);
+	buf[len] = '\r';
+	buf[len + 1] = '\0';
+	write(fileno(stdout), buf, len + 1);
+}
+
+void
+setttywidth(int a)
+{
+	struct winsize winsize;
+	int oerrno = errno;
+
+	if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1 &&
+	    winsize.ws_col != 0)
+	    	ttywidth = winsize.ws_col;
+	else
+		ttywidth = 80;
+	errno = oerrno;
+}
+
+#endif /* ! SMALL */
Index: fsck/progress.h
===================================================================
RCS file: fsck/progress.h
diff -N fsck/progress.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fsck/progress.h	13 Jan 2004 21:18:54 -0000
@@ -0,0 +1,48 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn; by Chris Gilbert; and by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * File system independent fsck progress bar routines.
+ */
+
+int	progress;
+long	progress_current;
+long	progress_total;
+void	setttywidth(int);
+void	progressbar(const char *, const char *, long, long);
+void	progressdone(void);
Index: fsck_ext2fs/main.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ext2fs/main.c,v
retrieving revision 1.15
diff -u -r1.15 main.c
--- fsck_ext2fs/main.c	5 Jan 2004 23:23:33 -0000	1.15
+++ fsck_ext2fs/main.c	13 Jan 2004 21:18:54 -0000
@@ -109,7 +109,7 @@
 
 	sync();
 	skipclean = 1;
-	while ((ch = getopt(argc, argv, "b:c:dfm:npqy")) != -1) {
+	while ((ch = getopt(argc, argv, "b:c:dfm:npPqy")) != -1) {
 		switch (ch) {
 		case 'b':
 			skipclean = 0;
@@ -141,6 +141,10 @@
 			preen++;
 			break;
 
+		case 'P':
+			/* Progress meter not implemented. */
+			break;
+
 		case 'q':		/* Quiet not implemented */
 			break;
 
Index: fsck_ffs/Makefile
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/Makefile,v
retrieving revision 1.24
diff -u -r1.24 Makefile
--- fsck_ffs/Makefile	28 Sep 2002 20:11:05 -0000	1.24
+++ fsck_ffs/Makefile	13 Jan 2004 21:18:54 -0000
@@ -8,8 +8,12 @@
 SRCS=	dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
 	pass5.c fsutil.c setup.c utilities.c ffs_bswap.c ffs_subr.c \
 	ffs_tables.c ffs_appleufs.c
+
 FSCK=	${NETBSDSRCDIR}/sbin/fsck
 CPPFLAGS+=-I${FSCK}
+SRCS+=	progress.c
+.PATH:	${FSCK}
+
 .PATH:	${NETBSDSRCDIR}/sys/ufs/ffs ${FSCK}
 
 
Index: fsck_ffs/fsck.h
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/fsck.h,v
retrieving revision 1.37
diff -u -r1.37 fsck.h
--- fsck_ffs/fsck.h	9 Jan 2004 19:12:31 -0000	1.37
+++ fsck_ffs/fsck.h	13 Jan 2004 21:18:54 -0000
@@ -41,6 +41,10 @@
 #include <stdio.h>
 #include <machine/bswap.h>
 
+#ifndef SMALL
+#include "progress.h"
+#endif /* ! SMALL */
+
 #define	MAXDUP		10	/* limit on dup blks (per inode) */
 #define	MAXBAD		10	/* limit on bad blks (per inode) */
 #define	MAXBUFSPACE	40*1024	/* maximum space to allocate to buffers */
@@ -327,5 +331,3 @@
 		return bswap64(x);
 	else return x;
 }
-
-
Index: fsck_ffs/fsck_ffs.8
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/fsck_ffs.8,v
retrieving revision 1.36
diff -u -r1.36 fsck_ffs.8
--- fsck_ffs/fsck_ffs.8	9 Jan 2004 23:42:11 -0000	1.36
+++ fsck_ffs/fsck_ffs.8	13 Jan 2004 21:18:54 -0000
@@ -37,7 +37,7 @@
 .Nd Fast File System consistency check and interactive repair
 .Sh SYNOPSIS
 .Nm
-.Op Fl adFfpq
+.Op Fl adFfpPq
 .Op Fl B Ar byte order
 .Op Fl b Ar block#
 .Op Fl c Ar level
@@ -229,6 +229,14 @@
 do not open the file system for writing.
 .It Fl p
 Specify ``preen'' mode, described above.
+.It Fl P
+Display a progress meter for the file system check.
+A new meter is displayed for each of the 5 file system check passes, unless
+.Fl p
+is specified, in which case only one meter for overall progress is displayed.
+Progress meters are disabled if the
+.Fl -d
+option is specified.
 .It Fl q
 Quiet mode, do not output any messages for clean filesystems.
 .It Fl y
Index: fsck_ffs/main.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/main.c,v
retrieving revision 1.48
diff -u -r1.48 main.c
--- fsck_ffs/main.c	5 Jan 2004 23:23:33 -0000	1.48
+++ fsck_ffs/main.c	13 Jan 2004 21:18:54 -0000
@@ -94,7 +94,7 @@
 	forceimage = 0;
 	endian = 0;
 	isappleufs = 0;
-	while ((ch = getopt(argc, argv, "aB:b:c:dFfm:npqy")) != -1) {
+	while ((ch = getopt(argc, argv, "aB:b:c:dFfm:npPqy")) != -1) {
 		switch (ch) {
 		case 'a':
 			isappleufs = 1;
@@ -147,6 +147,10 @@
 			preen++;
 			break;
 
+		case 'P':
+			progress = 1;
+			break;
+
 		case 'q':
 			quiet++;
 			break;
@@ -167,10 +171,19 @@
 	if (!argc)
 		usage();
 
+	if (debug)
+		progress = 0;
+
 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 		(void)signal(SIGINT, catch);
 	if (preen)
 		(void)signal(SIGQUIT, catchquit);
+#ifndef SMALL
+	if (progress) {
+		setttywidth(0);
+		(void)signal(SIGWINCH, setttywidth);
+	}
+#endif /* ! SMALL */
 	signal(SIGINFO, infohandler);
 
 	while (argc-- > 0) {
@@ -241,6 +254,22 @@
 	 * the superblock should be marked clean.
 	 */
 	resolved = 1;
+
+#ifndef SMALL
+	/*
+	 * Pass 1, Pass 4, and Pass 5 all iterate over cylinder
+	 * groups.  Account for those now.  We'll never need to
+	 * add in Pass 1b, since that pass is never executed when
+	 * preening.
+	 *
+	 * Pass 2 and Pass 3 iterate over directory inodes, but we
+	 * don't know how many of those exist until after Pass 1.
+	 * We'll add those in after Pass 1 has completed.
+	 */
+	if (preen)
+		progress_total = sblock->fs_ncg * 3;
+#endif /* ! SMALL */
+
 	/*
 	 * 1: scan inodes tallying blocks used
 	 */
@@ -252,6 +281,12 @@
 	}
 	pass1();
 
+#ifndef SMALL
+	/* Account for number of directory inodes (used twice). */
+	if (preen)
+		progress_total += inplast * 2;
+#endif /* ! SMALL */
+
 	/*
 	 * 1b: locate first references to duplicates, if any
 	 */
Index: fsck_ffs/pass1.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass1.c,v
retrieving revision 1.31
diff -u -r1.31 pass1.c
--- fsck_ffs/pass1.c	3 Jan 2004 10:11:41 -0000	1.31
+++ fsck_ffs/pass1.c	13 Jan 2004 21:18:54 -0000
@@ -112,6 +112,10 @@
 			    c * 100 / sblock->fs_ncg);
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), preen ? NULL : "phase 1",
+			    c, sblock->fs_ncg);
+#endif /* ! SMALL */
 		/*
 		 * If we are using soft updates, then we can trust the
 		 * cylinder group inode allocation maps to tell us which
@@ -190,6 +194,12 @@
 		free(inostathead[c].il_stat);
 		inostathead[c].il_stat = info;
 	}
+#ifndef SMALL
+	if (preen)
+		progress_current += sblock->fs_ncg;
+	else
+		progressdone();
+#endif /* ! SMALL */
 	freeinodebuf();
 	do_blkswap = 0; /* has been done */
 }
Index: fsck_ffs/pass1b.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass1b.c,v
retrieving revision 1.17
diff -u -r1.17 pass1b.c
--- fsck_ffs/pass1b.c	7 Aug 2003 10:04:20 -0000	1.17
+++ fsck_ffs/pass1b.c	13 Jan 2004 21:18:54 -0000
@@ -74,6 +74,9 @@
 			    c * 100 / sblock->fs_ncg);
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), "phase 1b", c, sblock->fs_ncg);
+#endif /* ! SMALL */
 		for (i = 0; i < sblock->fs_ipg; i++, inumber++) {
 			if (inumber < ROOTINO)
 				continue;
@@ -86,6 +89,9 @@
 				return;
 		}
 	}
+#ifndef SMALL
+	progressdone();
+#endif /* ! SMALL */
 }
 
 static int
Index: fsck_ffs/pass2.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass2.c,v
retrieving revision 1.36
diff -u -r1.36 pass2.c
--- fsck_ffs/pass2.c	7 Aug 2003 10:04:21 -0000	1.36
+++ fsck_ffs/pass2.c	13 Jan 2004 21:18:55 -0000
@@ -150,6 +150,10 @@
 			    (int)((inpp - inpsort) * 100 / inplast));
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), preen ? NULL : "phase 2",
+			    (inpp - inpsort), inplast);
+#endif /* ! SMALL */
 		inp = *inpp;
 		if (inp->i_isize == 0)
 			continue;
@@ -302,6 +306,13 @@
 	 * Mark all the directories that can be found from the root.
 	 */
 	propagate(ROOTINO);
+
+#ifndef SMALL
+	if (preen)
+		progress_current += inplast;
+	else
+		progressdone();
+#endif /* ! SMALL */
 }
 
 static int
Index: fsck_ffs/pass3.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass3.c,v
retrieving revision 1.16
diff -u -r1.16 pass3.c
--- fsck_ffs/pass3.c	7 Aug 2003 10:04:21 -0000	1.16
+++ fsck_ffs/pass3.c	13 Jan 2004 21:18:55 -0000
@@ -61,14 +61,18 @@
 	char namebuf[MAXNAMLEN+1];
 
 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
+		int inpindex = inpp - inpsort;
 		if (got_siginfo) {
-			int inpindex = inpp - inpsort;
 			fprintf(stderr,
 			    "%s: phase 3: dir %d of %d (%d%%)\n", cdevname(),
 			    (int)(inplast - inpindex - 1), (int)inplast,
 			    (int)((inplast - inpindex - 1) * 100 / inplast));
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), preen ? NULL : "phase 3",
+			    inplast - inpindex - 1, inplast);
+#endif /* ! SMALL */
 		inp = *inpp;
 		state = inoinfo(inp->i_number)->ino_state;
 		if (inp->i_number == ROOTINO ||
@@ -120,4 +124,10 @@
 			inoinfo(lfdir)->ino_linkcnt--;
 		}
 	}
+#ifndef SMALL
+	if (preen)
+		progress_current += inplast;
+	else
+		progressdone();
+#endif /* ! SMALL */
 }
Index: fsck_ffs/pass4.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass4.c,v
retrieving revision 1.18
diff -u -r1.18 pass4.c
--- fsck_ffs/pass4.c	7 Aug 2003 10:04:21 -0000	1.18
+++ fsck_ffs/pass4.c	13 Jan 2004 21:18:55 -0000
@@ -74,6 +74,10 @@
 			    cg * 100 / sblock->fs_ncg);
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), preen ? NULL : "phase 4",
+			    cg, sblock->fs_ncg);
+#endif /* ! SMALL */
 		inumber = cg * sblock->fs_ipg;
 		for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) {
 			if (inumber < ROOTINO)
@@ -123,6 +127,12 @@
 			}
 		}
 	}
+#ifndef SMALL
+	if (preen)
+		progress_current += sblock->fs_ncg;
+	else
+		progressdone();
+#endif /* ! SMALL */
 }
 
 int
Index: fsck_ffs/pass5.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass5.c,v
retrieving revision 1.39
diff -u -r1.39 pass5.c
--- fsck_ffs/pass5.c	9 Jan 2004 19:12:31 -0000	1.39
+++ fsck_ffs/pass5.c	13 Jan 2004 21:18:55 -0000
@@ -206,6 +206,10 @@
 			    c * 100 / fs->fs_ncg);
 			got_siginfo = 0;
 		}
+#ifndef SMALL
+		progressbar(cdevname(), preen ? NULL : "phase 5",
+			    c, fs->fs_ncg);
+#endif /* ! SMALL */
 		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
 		memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize);
 		if((doswap && !needswap) || (!doswap && needswap))
@@ -466,6 +470,12 @@
 		} else
 			markclean = 0;
 	}
+#ifndef SMALL
+	if (preen)
+		progress_current += fs->fs_ncg;
+	else
+		progressdone();
+#endif /* ! SMALL */
 }
 
 void 
Index: fsck_lfs/main.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_lfs/main.c,v
retrieving revision 1.17
diff -u -r1.17 main.c
--- fsck_lfs/main.c	5 Jan 2004 23:23:33 -0000	1.17
+++ fsck_lfs/main.c	13 Jan 2004 21:18:55 -0000
@@ -64,7 +64,7 @@
 {
 	int ch;
 	int ret = 0;
-	char *optstring = "b:dfi:m:npqy";
+	char *optstring = "b:dfi:m:npPqy";
 
 	sync();
 	skipclean = 1;
@@ -106,6 +106,9 @@
 			preen++;
 			break;
 
+		case 'P':		/* Progress meter not implemented. */
+			break;
+
 		case 'q':		/* Quiet not implemented */
 			break;
 
Index: fsck_msdos/main.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_msdos/main.c,v
retrieving revision 1.15
diff -u -r1.15 main.c
--- fsck_msdos/main.c	5 Jan 2004 23:23:33 -0000	1.15
+++ fsck_msdos/main.c	13 Jan 2004 21:18:55 -0000
@@ -71,7 +71,7 @@
 	int ret = 0, erg;
 	int ch;
 
-	while ((ch = getopt(argc, argv, "pqynf")) != -1) {
+	while ((ch = getopt(argc, argv, "pPqynf")) != -1) {
 		switch (ch) {
 		case 'f':
 			/*
@@ -93,7 +93,10 @@
 			alwaysyes = alwaysno = 0;
 			break;
 
-		case 'q':		/* quite not implemented */
+		case 'P':		/* Progress meter not implemented. */
+			break;
+
+		case 'q':		/* Quiet not implemented. */
 			break;
 
 		default:

--Apple-Mail-10--915122938--

--Apple-Mail-11--915122932
content-type: application/pgp-signature; x-mac-type=70674453;
	name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (Darwin)

iD8DBQFABGEpOpVKkaBm8XkRAgLkAKCd7Wj7E4tcLOKgTGotZBbbi+/dRACbBXoq
WZiDURZ+1vEv7ilaz/F64Ng=
=JtgE
-----END PGP SIGNATURE-----

--Apple-Mail-11--915122932--