From nobody@FreeBSD.org  Fri Apr 30 23:57:41 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 96C5F10656A3
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 30 Apr 2010 23:57:41 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id 86B4E8FC1C
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 30 Apr 2010 23:57:41 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o3UNvfE8002381
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 30 Apr 2010 23:57:41 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o3UNvfON002380;
	Fri, 30 Apr 2010 23:57:41 GMT
	(envelope-from nobody)
Message-Id: <201004302357.o3UNvfON002380@www.freebsd.org>
Date: Fri, 30 Apr 2010 23:57:41 GMT
From: Bruce Cran <bruce@cran.org.uk>
To: freebsd-gnats-submit@FreeBSD.org
Subject: df(1) fails to display total space on a 100PB filesystem correctly
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         146205
>Category:       bin
>Synopsis:       [patch] humanize_number(3): df fails to display total space on a 100PB filesystem correctly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    delphij
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat May 01 00:00:20 UTC 2010
>Closed-Date:    Fri Apr 22 00:32:44 UTC 2011
>Last-Modified:  Fri Apr 22 00:40:09 UTC 2011
>Originator:     Bruce Cran
>Release:        9.0-CURRENT
>Organization:
>Environment:
FreeBSD core.draftnet 9.0-CURRENT FreeBSD 9.0-CURRENT #0 r207449: Fri Apr 30 22:16:52 BST 2010     brucec@core.draftnet:/usr/obj/usr/src/head/sys/CORE  amd64
>Description:
df(1) correctly displays the number of 1K blocks in a 100PB filesystem, but displays wrong results when run with the "-h" flag:

> df tank
Filesystem 1K-blocks       Used           Avail Capacity  Mounted on
tank   107692009979824   19 107692009979805     0%    /tank

> df -h tank
Filesystem    Size    Used   Avail Capacity  Mounted on
tank      -741     19K    -741     0%    /tank

I suspect this is due to bugs in humanize_number from libdisk.
>How-To-Repeat:
On a ZFS filesystem, run "truncate -s100P mdfile && mdconfig -a -f mdfile" then create a pool on the md device.
>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-fs 
Responsible-Changed-By: arundel 
Responsible-Changed-When: Sun Mar 20 21:42:44 UTC 2011 
Responsible-Changed-Why:  


http://www.freebsd.org/cgi/query-pr.cgi?pr=146205 
Responsible-Changed-From-To: freebsd-fs->freebsd-bugs 
Responsible-Changed-By: arundel 
Responsible-Changed-When: Sun Mar 20 21:53:03 UTC 2011 
Responsible-Changed-Why:  
Sorry my bad. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=146205 

From: Alexander Best <arundel@freebsd.org>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/146205: df(1) fails to display total space on a 100PB filesystem correctly
Date: Sun, 20 Mar 2011 22:07:22 +0000

 --LZvS9be/3tNcYl/X
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 verified!
 
 defenately a problem with humanize_number(3). here's a testcase.
 
 cheers.
 alex
 
 -- 
 a13x
 
 --LZvS9be/3tNcYl/X
 Content-Type: text/x-csrc; charset=us-ascii
 Content-Disposition: attachment; filename="humanize_number.c"
 
 #include <libutil.h>
 #include <stdio.h>      
 
 int
 main(int argc, char** argv)
 {
 char buf[6];
 int flags;
 int64_t bytes = 107692009979824 * 1024;
 
 flags = HN_B | HN_NOSPACE | HN_DECIMAL;
 
 humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), bytes, "", HN_AUTOSCALE, flags);
 
 (void)printf("  %6s\n", buf);
 
 return 0;
 }
 
 --LZvS9be/3tNcYl/X--

From: Mark Linimon <linimon@lonesome.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: [delphij@delphij.net: Re: bin/146205: df(1) fails to display total
 space on a 100PB?filesystem correctly]
Date: Mon, 21 Mar 2011 20:35:17 -0500

 ----- Forwarded message from Xin LI <delphij@delphij.net> -----
 
 Date: Mon, 21 Mar 2011 17:44:43 -0700
 From: Xin LI <delphij@delphij.net>
 To: d@delphij.net
 Cc: Alexander Best <arundel@freebsd.org>, freebsd-bugs@FreeBSD.org
 Subject: Re: bin/146205: df(1) fails to display total space on a
 	100PB	filesystem correctly
 
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA256
 
 Revised version, I have mistakenly understood the old code, which only
 keeps one digit after the dot.
 
 Cheers,
 - -- 
 Xin LI <delphij@delphij.net>	http://www.delphij.net/
 FreeBSD - The Power to Serve!	       Live free or die
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.17 (FreeBSD)
 
 iQEcBAEBCAAGBQJNh/D6AAoJEATO+BI/yjfBbDoH/25nmc7rQ914Rgfp2iVTBTCo
 0J6D29V1tRfqFnzg62zYH23tsoQfcYI/gesx5TyegdCOpR1nOAEUl7T/UA4CmUuh
 CN54KNQ631WUT/V5Rndf5ikIcAnu7L5IP14RNGUWH5CJhi70OmrbWt3d2XKvLMvO
 Uhtq+Uhl/NyoGaq2tE9/WyGyeb70Ribzd4zE6hMVSSY9rPKASpCj3oSpAn7ioSms
 X9MvcUCM/eOQxLMYtq1PN6Dz5GPqewiBfmoOWNGssbYnhqotYpIKNUAkDeKUuFop
 P940nVkhhiSmsZPGD4W67fgKwXhxzj7Ukw7ru+XOp0z3afK6xxkkUQAvAfGop4g=
 =mx5z
 -----END PGP SIGNATURE-----
 
 Index: humanize_number.c
 ===================================================================
 --- humanize_number.c	(revision 219842)
 +++ humanize_number.c	(working copy)
 @@ -47,8 +47,9 @@
      const char *suffix, int scale, int flags)
  {
  	const char *prefixes, *sep;
 -	int	b, i, r, maxscale, s1, s2, sign;
 +	int	i, r, maxscale, s1, s2, sign;
  	int64_t	divisor, max;
 +	int64_t quotient = bytes, reminder = 0;
  	size_t	baselen;
  
  	assert(buf != NULL);
 @@ -88,11 +89,10 @@
  		buf[0] = '\0';
  	if (bytes < 0) {
  		sign = -1;
 -		bytes *= -100;
 +		quotient = -quotient;
  		baselen = 3;		/* sign, digit, prefix */
  	} else {
  		sign = 1;
 -		bytes *= 100;
  		baselen = 2;		/* digit, prefix */
  	}
  	if (flags & HN_NOSPACE)
 @@ -109,7 +109,7 @@
  
  	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
  		/* See if there is additional columns can be used. */
 -		for (max = 100, i = len - baselen; i-- > 0;)
 +		for (max = 1, i = len - baselen; i-- > 0;)
  			max *= 10;
  
  		/*
 @@ -117,29 +117,33 @@
  		 * If there will be an overflow by the rounding below,
  		 * divide once more.
  		 */
 -		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
 -			bytes /= divisor;
 +		for (i = 0; quotient > max && i < maxscale; i++) {
 +			reminder = quotient % divisor;
 +			quotient /= divisor;
 +		}
  
  		if (scale & HN_GETSCALE)
  			return (i);
 -	} else
 -		for (i = 0; i < scale && i < maxscale; i++)
 -			bytes /= divisor;
 +	} else {
 +		for (i = 0; i < scale && i < maxscale; i++) {
 +			reminder = quotient % divisor;
 +			quotient /= divisor;
 +		}
 +	}
  
  	/* If a value <= 9.9 after rounding and ... */
 -	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
 +	if (quotient == 9 && reminder < 950 && i > 0 && flags & HN_DECIMAL) {
  		/* baselen + \0 + .N */
  		if (len < baselen + 1 + 2)
  			return (-1);
 -		b = ((int)bytes + 5) / 10;
 -		s1 = b / 10;
 -		s2 = b % 10;
 +		s1 = (int)quotient + (((int)reminder + 50) / 100);
 +		s2 = (((int)reminder + 50) / 10) % 10;
  		r = snprintf(buf, len, "%d%s%d%s%s%s",
  		    sign * s1, localeconv()->decimal_point, s2,
  		    sep, SCALE2PREFIX(i), suffix);
  	} else
  		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
 -		    sign * ((bytes + 50) / 100),
 +		    sign * (quotient + (reminder + 50) / 100),
  		    sep, SCALE2PREFIX(i), suffix);
  
  	return (r);
 
 _______________________________________________
 freebsd-bugs@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
 To unsubscribe, send any mail to "freebsd-bugs-unsubscribe@freebsd.org"
 
 
 ----- End forwarded message -----
State-Changed-From-To: open->analyzed 
State-Changed-By: delphij 
State-Changed-When: Wed Mar 23 21:13:16 UTC 2011 
State-Changed-Why:  
Bump to analyzed, have a pending patch and some test cases and 
this is likely to be fixed really soon. 


Responsible-Changed-From-To: freebsd-bugs->delphij 
Responsible-Changed-By: delphij 
Responsible-Changed-When: Wed Mar 23 21:13:16 UTC 2011 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=146205 
State-Changed-From-To: analyzed->patched 
State-Changed-By: delphij 
State-Changed-When: Wed Mar 23 22:08:12 UTC 2011 
State-Changed-Why:  
Patched in -HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=146205 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/146205: commit references a PR
Date: Wed, 23 Mar 2011 22:08:15 +0000 (UTC)

 Author: delphij
 Date: Wed Mar 23 22:08:01 2011
 New Revision: 219939
 URL: http://svn.freebsd.org/changeset/base/219939
 
 Log:
   humanize_number(3) multiply the input number by 100, which could cause an
   integer overflow when the input is very large (for example, 100 Pi would
   become about 10 Ei which exceeded signed int64_t).
   
   Solve this issue by splitting the division into two parts and avoid the
   multiplication.
   
   PR:		bin/146205
   Reviewed by:	arundel
   MFC after:	1 month
 
 Modified:
   head/lib/libutil/humanize_number.c
 
 Modified: head/lib/libutil/humanize_number.c
 ==============================================================================
 --- head/lib/libutil/humanize_number.c	Wed Mar 23 22:06:09 2011	(r219938)
 +++ head/lib/libutil/humanize_number.c	Wed Mar 23 22:08:01 2011	(r219939)
 @@ -43,11 +43,11 @@ __FBSDID("$FreeBSD$");
  #include <libutil.h>
  
  int
 -humanize_number(char *buf, size_t len, int64_t bytes,
 +humanize_number(char *buf, size_t len, int64_t quotient,
      const char *suffix, int scale, int flags)
  {
  	const char *prefixes, *sep;
 -	int	b, i, r, maxscale, s1, s2, sign;
 +	int	i, r, remainder, maxscale, s1, s2, sign;
  	int64_t	divisor, max;
  	size_t	baselen;
  
 @@ -55,6 +55,8 @@ humanize_number(char *buf, size_t len, i
  	assert(suffix != NULL);
  	assert(scale >= 0);
  
 +	remainder = 0;
 +
  	if (flags & HN_DIVISOR_1000) {
  		/* SI for decimal multiplies */
  		divisor = 1000;
 @@ -86,13 +88,12 @@ humanize_number(char *buf, size_t len, i
  
  	if (len > 0)
  		buf[0] = '\0';
 -	if (bytes < 0) {
 +	if (quotient < 0) {
  		sign = -1;
 -		bytes *= -100;
 +		quotient = -quotient;
  		baselen = 3;		/* sign, digit, prefix */
  	} else {
  		sign = 1;
 -		bytes *= 100;
  		baselen = 2;		/* digit, prefix */
  	}
  	if (flags & HN_NOSPACE)
 @@ -109,7 +110,7 @@ humanize_number(char *buf, size_t len, i
  
  	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
  		/* See if there is additional columns can be used. */
 -		for (max = 100, i = len - baselen; i-- > 0;)
 +		for (max = 1, i = len - baselen; i-- > 0;)
  			max *= 10;
  
  		/*
 @@ -117,30 +118,37 @@ humanize_number(char *buf, size_t len, i
  		 * If there will be an overflow by the rounding below,
  		 * divide once more.
  		 */
 -		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
 -			bytes /= divisor;
 +		for (i = 0;
 +		    (quotient >= max || (quotient == max - 1 && remainder >= 950)) &&
 +		    i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
  
  		if (scale & HN_GETSCALE)
  			return (i);
 -	} else
 -		for (i = 0; i < scale && i < maxscale; i++)
 -			bytes /= divisor;
 +	} else {
 +		for (i = 0; i < scale && i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
 +	}
  
  	/* If a value <= 9.9 after rounding and ... */
 -	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
 +	if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) {
  		/* baselen + \0 + .N */
  		if (len < baselen + 1 + 2)
  			return (-1);
 -		b = ((int)bytes + 5) / 10;
 -		s1 = b / 10;
 -		s2 = b % 10;
 +		s1 = (int)quotient + ((remainder + 50) / 1000);
 +		s2 = ((remainder + 50) / 100) % 10;
  		r = snprintf(buf, len, "%d%s%d%s%s%s",
  		    sign * s1, localeconv()->decimal_point, s2,
  		    sep, SCALE2PREFIX(i), suffix);
  	} else
  		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
 -		    sign * ((bytes + 50) / 100),
 +		    sign * (quotient + (remainder + 50) / 1000),
  		    sep, SCALE2PREFIX(i), suffix);
  
  	return (r);
  }
 +
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: delphij 
State-Changed-When: Fri Apr 22 00:32:25 UTC 2011 
State-Changed-Why:  
Fix merged to 7 and 8-STABLE. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=146205 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/146205: commit references a PR
Date: Fri, 22 Apr 2011 00:31:22 +0000 (UTC)

 Author: delphij
 Date: Fri Apr 22 00:31:07 2011
 New Revision: 220933
 URL: http://svn.freebsd.org/changeset/base/220933
 
 Log:
   MFC r219939:
   
   humanize_number(3) multiply the input number by 100, which could cause an
   integer overflow when the input is very large (for example, 100 Pi would
   become about 10 Ei which exceeded signed int64_t).
   
   Solve this issue by splitting the division into two parts and avoid the
   multiplication.
   
   PR:		bin/146205
   Reviewed by:	arundel
 
 Modified:
   stable/8/lib/libutil/humanize_number.c
 Directory Properties:
   stable/8/lib/libutil/   (props changed)
 
 Modified: stable/8/lib/libutil/humanize_number.c
 ==============================================================================
 --- stable/8/lib/libutil/humanize_number.c	Thu Apr 21 23:06:00 2011	(r220932)
 +++ stable/8/lib/libutil/humanize_number.c	Fri Apr 22 00:31:07 2011	(r220933)
 @@ -43,11 +43,11 @@ __FBSDID("$FreeBSD$");
  #include <libutil.h>
  
  int
 -humanize_number(char *buf, size_t len, int64_t bytes,
 +humanize_number(char *buf, size_t len, int64_t quotient,
      const char *suffix, int scale, int flags)
  {
  	const char *prefixes, *sep;
 -	int	b, i, r, maxscale, s1, s2, sign;
 +	int	i, r, remainder, maxscale, s1, s2, sign;
  	int64_t	divisor, max;
  	size_t	baselen;
  
 @@ -55,6 +55,8 @@ humanize_number(char *buf, size_t len, i
  	assert(suffix != NULL);
  	assert(scale >= 0);
  
 +	remainder = 0;
 +
  	if (flags & HN_DIVISOR_1000) {
  		/* SI for decimal multiplies */
  		divisor = 1000;
 @@ -86,13 +88,12 @@ humanize_number(char *buf, size_t len, i
  
  	if (len > 0)
  		buf[0] = '\0';
 -	if (bytes < 0) {
 +	if (quotient < 0) {
  		sign = -1;
 -		bytes *= -100;
 +		quotient = -quotient;
  		baselen = 3;		/* sign, digit, prefix */
  	} else {
  		sign = 1;
 -		bytes *= 100;
  		baselen = 2;		/* digit, prefix */
  	}
  	if (flags & HN_NOSPACE)
 @@ -109,7 +110,7 @@ humanize_number(char *buf, size_t len, i
  
  	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
  		/* See if there is additional columns can be used. */
 -		for (max = 100, i = len - baselen; i-- > 0;)
 +		for (max = 1, i = len - baselen; i-- > 0;)
  			max *= 10;
  
  		/*
 @@ -117,30 +118,37 @@ humanize_number(char *buf, size_t len, i
  		 * If there will be an overflow by the rounding below,
  		 * divide once more.
  		 */
 -		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
 -			bytes /= divisor;
 +		for (i = 0;
 +		    (quotient >= max || (quotient == max - 1 && remainder >= 950)) &&
 +		    i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
  
  		if (scale & HN_GETSCALE)
  			return (i);
 -	} else
 -		for (i = 0; i < scale && i < maxscale; i++)
 -			bytes /= divisor;
 +	} else {
 +		for (i = 0; i < scale && i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
 +	}
  
  	/* If a value <= 9.9 after rounding and ... */
 -	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
 +	if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) {
  		/* baselen + \0 + .N */
  		if (len < baselen + 1 + 2)
  			return (-1);
 -		b = ((int)bytes + 5) / 10;
 -		s1 = b / 10;
 -		s2 = b % 10;
 +		s1 = (int)quotient + ((remainder + 50) / 1000);
 +		s2 = ((remainder + 50) / 100) % 10;
  		r = snprintf(buf, len, "%d%s%d%s%s%s",
  		    sign * s1, localeconv()->decimal_point, s2,
  		    sep, SCALE2PREFIX(i), suffix);
  	} else
  		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
 -		    sign * ((bytes + 50) / 100),
 +		    sign * (quotient + (remainder + 50) / 1000),
  		    sep, SCALE2PREFIX(i), suffix);
  
  	return (r);
  }
 +
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/146205: commit references a PR
Date: Fri, 22 Apr 2011 00:32:25 +0000 (UTC)

 Author: delphij
 Date: Fri Apr 22 00:32:16 2011
 New Revision: 220934
 URL: http://svn.freebsd.org/changeset/base/220934
 
 Log:
   MFC r219939:
   
   humanize_number(3) multiply the input number by 100, which could cause an
   integer overflow when the input is very large (for example, 100 Pi would
   become about 10 Ei which exceeded signed int64_t).
   
   Solve this issue by splitting the division into two parts and avoid the
   multiplication.
   
   PR:		bin/146205
   Reviewed by:	arundel
 
 Modified:
   stable/7/lib/libutil/humanize_number.c
 Directory Properties:
   stable/7/lib/libutil/   (props changed)
 
 Modified: stable/7/lib/libutil/humanize_number.c
 ==============================================================================
 --- stable/7/lib/libutil/humanize_number.c	Fri Apr 22 00:31:07 2011	(r220933)
 +++ stable/7/lib/libutil/humanize_number.c	Fri Apr 22 00:32:16 2011	(r220934)
 @@ -50,11 +50,11 @@ __FBSDID("$FreeBSD$");
  #include <libutil.h>
  
  int
 -humanize_number(char *buf, size_t len, int64_t bytes,
 +humanize_number(char *buf, size_t len, int64_t quotient,
      const char *suffix, int scale, int flags)
  {
  	const char *prefixes, *sep;
 -	int	b, i, r, maxscale, s1, s2, sign;
 +	int	i, r, remainder, maxscale, s1, s2, sign;
  	int64_t	divisor, max;
  	size_t	baselen;
  
 @@ -62,6 +62,8 @@ humanize_number(char *buf, size_t len, i
  	assert(suffix != NULL);
  	assert(scale >= 0);
  
 +	remainder = 0;
 +
  	if (flags & HN_DIVISOR_1000) {
  		/* SI for decimal multiplies */
  		divisor = 1000;
 @@ -93,13 +95,12 @@ humanize_number(char *buf, size_t len, i
  
  	if (len > 0)
  		buf[0] = '\0';
 -	if (bytes < 0) {
 +	if (quotient < 0) {
  		sign = -1;
 -		bytes *= -100;
 +		quotient = -quotient;
  		baselen = 3;		/* sign, digit, prefix */
  	} else {
  		sign = 1;
 -		bytes *= 100;
  		baselen = 2;		/* digit, prefix */
  	}
  	if (flags & HN_NOSPACE)
 @@ -116,7 +117,7 @@ humanize_number(char *buf, size_t len, i
  
  	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
  		/* See if there is additional columns can be used. */
 -		for (max = 100, i = len - baselen; i-- > 0;)
 +		for (max = 1, i = len - baselen; i-- > 0;)
  			max *= 10;
  
  		/*
 @@ -124,30 +125,37 @@ humanize_number(char *buf, size_t len, i
  		 * If there will be an overflow by the rounding below,
  		 * divide once more.
  		 */
 -		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
 -			bytes /= divisor;
 +		for (i = 0;
 +		    (quotient >= max || (quotient == max - 1 && remainder >= 950)) &&
 +		    i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
  
  		if (scale & HN_GETSCALE)
  			return (i);
 -	} else
 -		for (i = 0; i < scale && i < maxscale; i++)
 -			bytes /= divisor;
 +	} else {
 +		for (i = 0; i < scale && i < maxscale; i++) {
 +			remainder = quotient % divisor;
 +			quotient /= divisor;
 +		}
 +	}
  
  	/* If a value <= 9.9 after rounding and ... */
 -	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
 +	if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) {
  		/* baselen + \0 + .N */
  		if (len < baselen + 1 + 2)
  			return (-1);
 -		b = ((int)bytes + 5) / 10;
 -		s1 = b / 10;
 -		s2 = b % 10;
 +		s1 = (int)quotient + ((remainder + 50) / 1000);
 +		s2 = ((remainder + 50) / 100) % 10;
  		r = snprintf(buf, len, "%d%s%d%s%s%s",
  		    sign * s1, localeconv()->decimal_point, s2,
  		    sep, SCALE2PREFIX(i), suffix);
  	} else
  		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
 -		    sign * ((bytes + 50) / 100),
 +		    sign * (quotient + (remainder + 50) / 1000),
  		    sep, SCALE2PREFIX(i), suffix);
  
  	return (r);
  }
 +
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
