Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Feb 2002 10:36:46 -0500 (EST)
From:      Tomas Svensson <tsn@gbdev.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/34834: "fix" of du(1) and -h
Message-ID:  <20020211153646.2C69E4B921@whiterose.net>

next in thread | raw e-mail | index | archive | help

>Number:         34834
>Category:       bin
>Synopsis:       "fix" of du(1) and -h
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 11 07:40:03 PST 2002
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020211153646.2C69E4B921>