Subject: bin/18402: fixed du(1), added -h option to display human-readable format
To: None <gnats-bugs@gnats.netbsd.org>
From: Benedikt Meurer <bmeurer@fwdn.de>
List: netbsd-bugs
Date: 09/24/2002 20:02:16
>Number:         18402
>Category:       bin
>Synopsis:       added -h option, as found on other plattforms
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 24 11:03:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Benedikt Meurer
>Release:        NetBSD 1.6
>Organization:
University Siegen
>Environment:
System: NetBSD endor.kosmos.all 1.6 NetBSD 1.6 (ENDOR) #1: Tue Sep 24 16:20:31 CEST 2002 benny@endor.kosmos.all:/usr/src/sys/arch/i386/compile/ENDOR i386
Architecture: i386
Machine: i386
>Description:
I've added the -h option to du, allowing it to display the numbers in
a "human-readable" format as found on other plattforms. I also make lint
happier about du.c and fixed the exit failure, since exit should return
"rval" not just 0, in case somethings went wrong. Also fixes a potential
bug with totalblocks too small (type long), and added l10n support.
>How-To-Repeat:
>Fix:
Patch follows.

Index: du.1
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/du/du.1,v
retrieving revision 1.12
diff -u -r1.12 du.1
--- du.1	2001/12/01 19:03:31	1.12
+++ du.1	2002/09/24 17:23:45
@@ -43,7 +43,7 @@
 .Nm
 .Op Fl H | Fl L | Fl P
 .Op Fl a | Fl s
-.Op Fl ckmrx
+.Op Fl chkmrx
 .Op Ar file ...
 .Sh DESCRIPTION
 The
@@ -80,6 +80,12 @@
 .Fl m
 flag is specified, the number displayed is the number of megabyte
 (1024*1024 bytes) blocks.
+.It Fl h
+If the
+.Fl h
+flag is specified, the numbers will be displayed in "human-readable"
+format. Use unit suffixes: B (Byte), K (Kilobyte), M (Megabyte),
+G (Gigabyte), T (Terabyte) and P (Petabyte).
 .It Fl c
 Display the grand total after all the arguments have been processed.
 .It Fl r
Index: du.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/du/du.c,v
retrieving revision 1.17
diff -u -r1.17 du.c
--- du.c	2001/01/04 23:05:54	1.17
+++ du.c	2002/09/24 17:23:46
@@ -57,6 +57,7 @@
 #include <err.h>
 #include <errno.h>
 #include <fts.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -64,8 +65,13 @@
 
 int	linkchk __P((FTSENT *));
 int	main __P((int, char **));
+void	prstat __P((const char *, int64_t));
 void	usage __P((void));
 
+/* used by prstat */
+long blocksize;
+int hflag;
+
 int
 main(argc, argv)
 	int argc;
@@ -73,27 +79,26 @@
 {
 	FTS *fts;
 	FTSENT *p;
-	long blocksize, totalblocks;
+	int64_t totalblocks;
 	int ftsoptions, listdirs, listfiles;
-	int Hflag, Lflag, Pflag, aflag, ch, cflag, kmflag, notused, rval, sflag;
+	int Hflag, Lflag, aflag, ch, cflag, kmflag, notused, rval, sflag;
 	char **save;
 
 	save = argv;
-	Hflag = Lflag = Pflag = aflag = cflag = kmflag = sflag = 0;
+	Hflag = Lflag = aflag = cflag = kmflag = sflag = 0;
 	totalblocks = 0;
 	ftsoptions = FTS_PHYSICAL;
-	while ((ch = getopt(argc, argv, "HLPackmrsx")) != -1)
+	while ((ch = getopt(argc, argv, "HLPachkmrsx")) != -1)
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
-			Lflag = Pflag = 0;
+			Lflag = 0;
 			break;
 		case 'L':
 			Lflag = 1;
-			Hflag = Pflag = 0;
+			Hflag = 0;
 			break;
 		case 'P':
-			Pflag = 1;
 			Hflag = Lflag = 0;
 			break;
 		case 'a':
@@ -102,6 +107,9 @@
 		case 'c':
 			cflag = 1;
 			break;
+		case 'h':
+			hflag = 1;
+			break;
 		case 'k':
 			blocksize = 1024;
 			kmflag = 1;
@@ -183,9 +191,7 @@
 			 * root of a traversal, display the total.
 			 */
 			if (listdirs || (!listfiles && !p->fts_level))
-				(void)printf("%ld\t%s\n",
-				    howmany(p->fts_number, blocksize),
-				    p->fts_path);
+				prstat(p->fts_path, (int64_t)p->fts_number);
 			break;
 		case FTS_DC:			/* Ignore. */
 			break;
@@ -203,9 +209,7 @@
 			 * the root of a traversal, display the total.
 			 */
 			if (listfiles || !p->fts_level)
-				(void)printf("%lld\t%s\n", (long long)
-				    howmany(p->fts_statp->st_blocks, blocksize),
-				    p->fts_path);
+				prstat(p->fts_path, p->fts_statp->st_blocks);
 			p->fts_parent->fts_number += p->fts_statp->st_blocks;
 			if (cflag)
 				totalblocks += p->fts_statp->st_blocks;
@@ -213,9 +217,28 @@
 	if (errno)
 		err(1, "fts_read");
 	if (cflag)
-		(void)printf("%ld\ttotal\n",
-		    howmany(totalblocks, blocksize));
-	exit(0);
+		prstat("total", totalblocks);
+	exit(rval);
+}
+
+void
+prstat (fname, blocks)
+	const char *fname;
+	int64_t blocks;
+{
+	static char sznam[] = {'B', 'K', 'M', 'G', 'T', 'P'};
+
+	if (hflag) {
+		double sz = blocks * 512;
+		int n = 0;
+
+		for ( ; sz >= 1024; n++, sz /= 1024)
+			;
+		(void)printf("%.1f%c\t%s\n", sz, sznam[n], fname);
+	}
+	else
+		(void)printf("%lld\t%s\n", howmany(blocks, (int64_t)blocksize),
+			fname);
 }
 
 typedef struct _ID {
@@ -254,6 +277,6 @@
 {
 
 	(void)fprintf(stderr,
-		"usage: du [-H | -L | -P] [-a | -s] [-ckmrx] [file ...]\n");
+		"usage: du [-H | -L | -P] [-a | -s] [-chkmrx] [file ...]\n");
 	exit(1);
 }
>Release-Note:
>Audit-Trail:
>Unformatted: