From mfm@whiterose.net  Mon Feb 11 07:36:39 2002
Return-Path: <mfm@whiterose.net>
Received: from whiterose.net (whiterose.net [64.65.220.94])
	by hub.freebsd.org (Postfix) with ESMTP id BCE9C37B405
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 11 Feb 2002 07:36:38 -0800 (PST)
Received: by whiterose.net (Postfix, from userid 1006)
	id 2C69E4B921; Mon, 11 Feb 2002 10:36:46 -0500 (EST)
Message-Id: <20020211153646.2C69E4B921@whiterose.net>
Date: Mon, 11 Feb 2002 10:36:46 -0500 (EST)
From: Tomas Svensson <tsn@gbdev.net>
Reply-To: Tomas Svensson <tsn@gbdev.net>
To: FreeBSD-gnats-submit@freebsd.org
Subject: "fix" of du(1) and -h
X-Send-Pr-Version: 3.2

>Number:         34834
>Category:       bin
>Synopsis:       "fix" of du(1) and -h
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pjd
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 11 07:40:03 PST 2002
>Closed-Date:    Sun Oct 24 17:46:03 GMT 2004
>Last-Modified:  Sun Oct 24 17:46:03 GMT 2004
>Originator:     Tomas Svensson
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
BSD Slackers Inc.
>Environment:
	FreeBSD 5.0-CURRENT i386
>Description:
	The manpages for df(1), du(1) and ls(1) claim that -h (print human-
	readable numbers) will reduce the number of digits to three or fewer,
	but this isn't true. It will print numbers such as 1000K or 1010K
	(since these are slightly less than a megabyte). Also, the 'K' for
	kilo should really be 'k'.

	Here is a fix for du(1) (I'll fix the others too if this patch is
	accepted). This version will display "1.0M" where the old version
	displayed "1012K", "32k" instead of "32K" etc.

	As a "side effect", df doesn't need the math library anymore (still
	does proper rounding) and the source is more than a kB smaller :)

	An alternative would be to add a more extensive humanize function
	to libc...

>How-To-Repeat:
>Fix:

Index: du.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/du/du.c,v
retrieving revision 1.23
diff -u -r1.23 du.c
--- du.c	8 Feb 2002 07:49:13 -0000	1.23
+++ du.c	11 Feb 2002 13:18:33 -0000
@@ -57,39 +57,12 @@
 #include <errno.h>
 #include <fnmatch.h>
 #include <fts.h>
-#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
 
-#define	KILO_SZ(n) (n)
-#define	MEGA_SZ(n) ((n) * (n))
-#define	GIGA_SZ(n) ((n) * (n) * (n))
-#define	TERA_SZ(n) ((n) * (n) * (n) * (n))
-#define	PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
-
-#define	KILO_2_SZ (KILO_SZ(1024ULL))
-#define	MEGA_2_SZ (MEGA_SZ(1024ULL))
-#define	GIGA_2_SZ (GIGA_SZ(1024ULL))
-#define	TERA_2_SZ (TERA_SZ(1024ULL))
-#define	PETA_2_SZ (PETA_SZ(1024ULL))
-
-#define	KILO_SI_SZ (KILO_SZ(1000ULL))
-#define	MEGA_SI_SZ (MEGA_SZ(1000ULL))
-#define	GIGA_SI_SZ (GIGA_SZ(1000ULL))
-#define	TERA_SI_SZ (TERA_SZ(1000ULL))
-#define	PETA_SI_SZ (PETA_SZ(1000ULL))
-
-unsigned long long vals_si [] = {1, KILO_SI_SZ, MEGA_SI_SZ, GIGA_SI_SZ, TERA_SI_SZ, PETA_SI_SZ};
-unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
-unsigned long long *valp;
-
-typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t;
-
-int unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
-
 SLIST_HEAD(ignhead, ignentry) ignores;
 struct ignentry {
 	char			*mask;
@@ -98,8 +71,7 @@
 
 int		linkchk __P((FTSENT *));
 static void	usage __P((void));
-void		prthumanval __P((double));
-unit_t		unit_adjust __P((double *));
+void		prthumanval __P((u_int64_t));
 void		ignoreadd __P((const char *));
 void		ignoreclean __P((void));
 int		ignorep __P((FTSENT *));
@@ -165,7 +137,6 @@
 			case 'h':
 				putenv("BLOCKSIZE=512");
 				hflag = 1;
-				valp = vals_base2;
 				break;
 			case 'k':
 				if (!hflag)
@@ -349,43 +320,29 @@
  * especially on huge disks.
  *
  */
-unit_t
-unit_adjust(val)
-	double *val;
-{
-	double abval;
-	unit_t unit;
-	unsigned int unit_sz;
-
-	abval = fabs(*val);
-
-	unit_sz = abval ? ilogb(abval) / 10 : 0;
-
-	if (unit_sz >= UNIT_MAX) {
-		unit = NONE;
-	} else {
-		unit = unitp[unit_sz];
-		*val /= (double)valp[unit_sz];
-	}
-
-	return (unit);
-}
-
 void
 prthumanval(bytes)
-	double bytes;
+	u_int64_t bytes;
 {
-	unit_t unit;
+	static const char prefixes[] = "BkMGTPE";
+	
+	int		i;
+	u_int64_t	s1, s2;
 
-	bytes *= 512;
-	unit = unit_adjust(&bytes);
+	bytes *= 51200;
 
-	if (bytes == 0)
-		(void)printf("  0B");
-	else if (bytes > 10)
-		(void)printf("%3.0f%c", bytes, "BKMGTPE"[unit]);
-	else
-		(void)printf("%3.1f%c", bytes, "BKMGTPE"[unit]);
+	for (i = 0; bytes >= 100000 && i < sizeof(prefixes); i++)
+		bytes /= 1024;
+
+	if (bytes < 1000 ) {
+		s1 = bytes / 100;
+		if (( s2 = (( (bytes % 100 ) + 5 ) /  10 ) ) == 10 ) {
+			s1++;
+			s2 = 0;
+		}
+		printf("%qd.%qd%c", s1, s2, prefixes[i]);
+	} else
+		printf("%3qd%c", (bytes + 50) / 100, prefixes[i]);
 }
 
 static void
Index: Makefile
===================================================================
RCS file: /home/ncvs/src/usr.bin/du/Makefile,v
retrieving revision 1.7
diff -u -r1.7 Makefile
--- Makefile	8 Feb 2002 22:31:38 -0000	1.7
+++ Makefile	11 Feb 2002 13:18:33 -0000
@@ -2,7 +2,5 @@
 # $FreeBSD: src/usr.bin/du/Makefile,v 1.7 2002/02/08 22:31:38 markm Exp $
 
 PROG=	du
-DPADD=	${LIBM}
-LDADD=	-lm
 
 .include <bsd.prog.mk>
>Release-Note:
>Audit-Trail:

From: "Crist J. Clark" <cjc@FreeBSD.ORG>
To: Tomas Svensson <tsn@gbdev.net>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/34834: "fix" of du(1) and -h
Date: Tue, 12 Feb 2002 03:50:37 -0800

 On Mon, Feb 11, 2002 at 10:36:46AM -0500, Tomas Svensson wrote:
 [snip]
 
 > >Description:
 > 	The manpages for df(1), du(1) and ls(1) claim that -h (print human-
 > 	readable numbers) will reduce the number of digits to three or fewer,
 > 	but this isn't true. It will print numbers such as 1000K or 1010K
 > 	(since these are slightly less than a megabyte). Also, the 'K' for
 > 	kilo should really be 'k'.
 
 'k' is generally used for multiples of 1000. 'K' is used for multiples
 of 1024. Sticking with 'K' is prefered except possibly for the '-H'
 option of df(1). But it seems like a lot of trouble to change that one
 case to 'k'.
 
 The current method does seem to be overkill. Why not just divide by
 1024 n-times until the result is < 1024 rather than ilogb(3)? We lose
 the math library, and we don't need that table of values.
 
 One comment about the patch,
 
 [snip]
 > +		printf("%qd.%qd%c", s1, s2, prefixes[i]);
 > +	} else
 > +		printf("%3qd%c", (bytes + 50) / 100, prefixes[i]);
 
 Quads? Ewwww...
 -- 
 Crist J. Clark                     |     cjclark@alum.mit.edu
                                    |     cjclark@jhu.edu
 http://people.freebsd.org/~cjc/    |     cjc@freebsd.org

From: Tomas Svensson <tsn@gbdev.net>
To: "Crist J. Clark" <cjc@FreeBSD.ORG>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/34834: "fix" of du(1) and -h
Date: Tue, 12 Feb 2002 14:52:46 +0100

 Tuesday, February 12, 2002, 12:50:37 PM, you wrote:
 
 CJC> On Mon, Feb 11, 2002 at 10:36:46AM -0500, Tomas Svensson wrote:
 CJC> [snip]
 
 >> >Description:
 >>       The manpages for df(1), du(1) and ls(1) claim that -h (print human-
 >>       readable numbers) will reduce the number of digits to three or fewer,
 >>       but this isn't true. It will print numbers such as 1000K or 1010K
 >>       (since these are slightly less than a megabyte). Also, the 'K' for
 >>       kilo should really be 'k'.
 
 CJC> 'k' is generally used for multiples of 1000. 'K' is used for multiples
 CJC> of 1024. Sticking with 'K' is prefered except possibly for the '-H'
 CJC> option of df(1). But it seems like a lot of trouble to change that one
 CJC> case to 'k'.
 
 Yes you're right, change the 'k' to 'K'. Just because 3-4 people told
 me that 'k' was right, I assumed that they were correct.
 
 CJC> The current method does seem to be overkill. Why not just divide by
 CJC> 1024 n-times until the result is < 1024 rather than ilogb(3)? We lose
 CJC> the math library, and we don't need that table of values.
 
 < 1024 will still give the irritating '1000K' result.
 
 CJC> One comment about the patch,
 
 CJC> [snip]
 >> +             printf("%qd.%qd%c", s1, s2, prefixes[i]);
 >> +     } else
 >> +             printf("%3qd%c", (bytes + 50) / 100, prefixes[i]);
 
 CJC> Quads? Ewwww...
 
 The smaller types won't do for the calculation, so no point in
 convertning before printing? (Ok, s1 and s2 doesn't need to be quads).
 
 -Tomas
 
 

From: Bob Bishop <rb@gid.co.uk>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/34834: "fix" of du(1) and -h
Date: Wed, 13 Feb 2002 14:57:10 +0000

 *ALL* the standard one-letter prefixes strictly denote powers of 10, so 
 being precious over k/K doesn't really help much. See
 http://physics.nist.gov/cuu/Units/prefixes.html
 and
 http://physics.nist.gov/cuu/Units/binary.html
 for the applicable standards.
 
 --
 Bob Bishop		    +44 (0)118 977 4017
 rb@gid.co.uk		fax +44 (0)118 989 4254
 
State-Changed-From-To: open->feedback 
State-Changed-By: pjd 
State-Changed-When: Sun Oct 24 17:23:39 GMT 2004 
State-Changed-Why:  
Could you check if this is fixed in FreeBSD 5.3 or 6-CURRENT? 


Responsible-Changed-From-To: freebsd-bugs->pjd 
Responsible-Changed-By: pjd 
Responsible-Changed-When: Sun Oct 24 17:23:39 GMT 2004 
Responsible-Changed-Why:  
Could you check if this is still a problem in 5.3 or 6-CURRENT? 

http://www.freebsd.org/cgi/query-pr.cgi?pr=34834 
State-Changed-From-To: feedback->closed 
State-Changed-By: pjd 
State-Changed-When: Sun Oct 24 17:45:00 GMT 2004 
State-Changed-Why:  
Submitter e-mail doesn't exist, so I can't get feedback. 
I think this bug was fixed when humanize_number(3) was introduced. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=34834 
>Unformatted:
