]> git.saurik.com Git - apple/libutil.git/commitdiff
libutil-43.tar.gz os-x-1011 os-x-10111 os-x-10112 os-x-10113 os-x-10114 os-x-10115 os-x-10116 v43
authorApple <opensource@apple.com>
Tue, 10 Mar 2015 20:17:47 +0000 (20:17 +0000)
committerApple <opensource@apple.com>
Tue, 10 Mar 2015 20:17:47 +0000 (20:17 +0000)
humanize_number.3
humanize_number.c
libutil.h
libutil.xcodeproj/project.pbxproj
tests/humanize_number_test.c [new file with mode: 0644]
wipefs.cpp
xcconfigs/base.xcconfig
xcconfigs/test.xcconfig [new file with mode: 0644]
xcconfigs/tzlinkd.xcconfig

index aa712a7f7f09b4dae4ed4c16e797cc13613a8302..57251a9c881ebbfc913bc4ab2f44b6deb084bb6c 100644 (file)
@@ -1,5 +1,5 @@
 .\"    $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $
-.\" $FreeBSD: src/lib/libutil/humanize_number.3,v 1.8 2005/04/10 12:15:25 delphij Exp $
+.\" $FreeBSD$
 .\"
 .\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
 .\" 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
@@ -35,7 +28,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 25, 2004
+.Dd October 7, 2013
 .Dt HUMANIZE_NUMBER 3
 .Os
 .Sh NAME
@@ -56,12 +49,12 @@ The
 function formats the signed 64-bit quantity given in
 .Fa number
 into
-.Fa buffer .
+.Fa buf .
 A space and then
 .Fa suffix
 is appended to the end.
 The buffer pointed to by
-.Fa buffer
+.Fa buf
 must be at least
 .Fa len
 bytes long.
@@ -69,23 +62,49 @@ bytes long.
 If the formatted number (including
 .Fa suffix )
 would be too long to fit into
-.Fa buffer ,
+.Fa buf ,
 then divide
 .Fa number
 by 1024 until it will.
 In this case, prefix
 .Fa suffix
-with the appropriate SI designator.
+with the appropriate designator.
+The
+.Fn humanize_number
+function follows the traditional computer science conventions by
+default, rather than the IEE/IEC (and now also SI) power of two
+convention or the power of ten notion.
+This behaviour however can be altered by specifying the
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags.
+.Pp
+The traditional
+.Pq default
+prefixes are:
+.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" Ta Sy "Multiplier 1000x"
+.It Li (note) Ta No kilo Ta 1024 Ta 1000
+.It Li M Ta No mega Ta 1048576 Ta 1000000
+.It Li G Ta No giga Ta 1073741824 Ta 1000000000
+.It Li T Ta No tera Ta 1099511627776 Ta 1000000000000
+.It Li P Ta No peta Ta 1125899906842624 Ta 1000000000000000
+.It Li E Ta No exa Ta 1152921504606846976 Ta 1000000000000000000
+.El
+.Pp
+Note:
+An uppercase K indicates a power of two, a lowercase k a power of ten.
 .Pp
-The prefixes are:
-.Bl -column "Prefix" "Description" "Multiplier" -offset indent
+The IEE/IEC (and now also SI) power of two prefixes are:
+.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
 .It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
-.It Li k Ta No kilo Ta 1024
-.It Li M Ta No mega Ta 1048576
-.It Li G Ta No giga Ta 1073741824
-.It Li T Ta No tera Ta 1099511627776
-.It Li P Ta No peta Ta 1125899906842624
-.It Li E Ta No exa Ta 1152921504606846976
+.It Li Ki Ta No kibi Ta 1024
+.It Li Mi Ta No mebi Ta 1048576
+.It Li Gi Ta No gibi Ta 1073741824
+.It Li Ti Ta No tebi Ta 1099511627776
+.It Li Pi Ta No pebi Ta 1125899906842624
+.It Li Ei Ta No exbi Ta 1152921504606846976
 .El
 .Pp
 The
@@ -93,10 +112,15 @@ The
 argument must be at least 4 plus the length of
 .Fa suffix ,
 in order to ensure a useful result is generated into
-.Fa buffer .
+.Fa buf .
 To use a specific prefix, specify this as
 .Fa scale
-(multiplier = 1024 ^ scale).
+.Po multiplier = 1024 ^ scale;
+when
+.Dv HN_DIVISOR_1000
+is specified,
+multiplier = 1000 ^ scale
+.Pc .
 This cannot be combined with any of the
 .Fa scale
 flags below.
@@ -116,7 +140,7 @@ The following flags may be passed in
 .Fa flags :
 .Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
 .It Dv HN_DECIMAL
-If the final result is less than 10, display it using one digit.
+If the final result is less than 10, display it using one decimal place.
 .It Dv HN_NOSPACE
 Do not put a space between
 .Fa number
@@ -129,20 +153,50 @@ Use
 Divide
 .Fa number
 with 1000 instead of 1024.
+.It Dv HN_IEC_PREFIXES
+Use the IEE/IEC notion of prefixes (Ki, Mi, Gi...).
+This flag has no effect when
+.Dv HN_DIVISOR_1000
+is also specified.
 .El
 .Sh RETURN VALUES
-The
-.Fn humanize_number
-function returns the number of characters stored in
-.Fa buffer
+Upon success, the
+.Nm
+function returns the number of characters that would have been stored in
+.Fa buf
 (excluding the terminating
 .Dv NUL )
-upon success, or \-1 upon failure.
+if
+.Fa buf
+was large enough, or \-1 upon failure.
+Even upon failure, the contents of
+.Fa buf
+may be modified.
 If
 .Dv HN_GETSCALE
 is specified, the prefix index number will be returned instead.
+.\" .Sh SEE ALSO
+.\" .Xr expand_number 3
+.Sh STANDARDS
+The
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags
+conform to
+.Tn ISO/IEC
+Std\~80000-13:2008
+and
+.Tn IEEE
+Std\~1541-2002.
 .Sh HISTORY
 The
 .Fn humanize_number
 function first appeared in
-.Nx 2.0 .
+.Nx 2.0
+and then in
+.Fx 5.3 .
+The
+.Dv HN_IEC_PREFIXES
+flag was introduced in
+.Fx 9.0 .
index 5f801cfe73217cdc506f9659e82b7a089211e8bf..b773422475b39b67530bdeca11f8ab645df28bf5 100644 (file)
@@ -1,7 +1,8 @@
-/*     $NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $        */
+/*     $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $      */
 
 /*
  * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * Copyright 2013 John-Mark Gurney <jmg@FreeBSD.org>
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * 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
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
 #include <assert.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <locale.h>
 #include <libutil.h>
-#include <stdint.h>
-#include <limits.h>
+
+static const int maxscale = 7;
 
 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;
-       int64_t divisor, max;
-       // We multiply bytes by 100 to deal with rounding, so we need something
-       // big enough to hold LLONG_MAX * 100. On 64-bit we can use 128-bit wide
-       // integers with __int128_t, but on 32-bit we have to use long double.
-#ifdef __LP64__
-       __int128_t scalable = (__int128_t)bytes;
-#else
-       long double scalable = (long double)bytes;
-#endif
+       int     i, r, remainder, s1, s2, sign;
+       int     divisordeccut;
+       int64_t divisor, max;
        size_t  baselen;
 
-       assert(buf != NULL);
-       assert(suffix != NULL);
-       assert(scale >= 0);
+       /* Since so many callers don't check -1, NUL terminate the buffer */
+       if (len > 0)
+               buf[0] = '\0';
 
-       if (flags & HN_DIVISOR_1000) {
-               /* SI for decimal multiplies */
-               divisor = 1000;
-               if (flags & HN_B)
-                       prefixes = "B\0k\0M\0G\0T\0P\0E";
-               else
-                       prefixes = "\0\0k\0M\0G\0T\0P\0E";
-       } else {
+       /* validate args */
+       if (buf == NULL || suffix == NULL)
+               return (-1);
+       if (scale < 0)
+               return (-1);
+       else if (scale >= maxscale &&
+           ((scale & ~(HN_AUTOSCALE|HN_GETSCALE)) != 0))
+               return (-1);
+       if ((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))
+               return (-1);
+
+       /* setup parameters */
+       remainder = 0;
+
+       if (flags & HN_IEC_PREFIXES) {
+               baselen = 2;
                /*
-                * binary multiplies
-                * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+                * Use the prefixes for power of two recommended by
+                * the International Electrotechnical Commission
+                * (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
+                *
+                * HN_IEC_PREFIXES implies a divisor of 1024 here
+                * (use of HN_DIVISOR_1000 would have triggered
+                * an assertion earlier).
                 */
                divisor = 1024;
+               divisordeccut = 973;    /* ceil(.95 * 1024) */
                if (flags & HN_B)
-                       prefixes = "B\0K\0M\0G\0T\0P\0E";
+                       prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
                else
-                       prefixes = "\0\0K\0M\0G\0T\0P\0E";
+                       prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+       } else {
+               baselen = 1;
+               if (flags & HN_DIVISOR_1000) {
+                       divisor = 1000;
+                       divisordeccut = 950;
+                       if (flags & HN_B)
+                               prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
+                       else
+                               prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
+               } else {
+                       divisor = 1024;
+                       divisordeccut = 973;    /* ceil(.95 * 1024) */
+                       if (flags & HN_B)
+                               prefixes = "B\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
+                       else
+                               prefixes = "\0\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
+               }
        }
 
-#define        SCALE2PREFIX(scale)     (&prefixes[(scale) << 1])
-       maxscale = 7;
-
-       if (scale >= maxscale &&
-           (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
-               return (-1);
+#define        SCALE2PREFIX(scale)     (&prefixes[(scale) * 3])
 
-       if (buf == NULL || suffix == NULL)
-               return (-1);
-
-       if (len > 0)
-               buf[0] = '\0';
-       if (bytes < 0) {
+       if (quotient < 0) {
                sign = -1;
-               scalable *= -100;
-               baselen = 3;            /* sign, digit, prefix */
+               quotient = -quotient;
+               baselen += 2;           /* sign, digit */
        } else {
                sign = 1;
-               scalable *= 100;
-               baselen = 2;            /* digit, prefix */
+               baselen += 1;           /* digit */
        }
        if (flags & HN_NOSPACE)
                sep = "";
@@ -124,35 +133,46 @@ humanize_number(char *buf, size_t len, int64_t bytes,
 
        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;
 
-               for (i = 0; scalable >= max && i < maxscale; i++)
-                       scalable /= divisor;
+               /*
+                * Divide the number until it fits the given column.
+                * If there will be an overflow by the rounding below,
+                * divide once more.
+                */
+               for (i = 0;
+                   (quotient >= max || (quotient == max - 1 &&
+                   remainder >= divisordeccut)) && i < maxscale; i++) {
+                       remainder = quotient % divisor;
+                       quotient /= divisor;
+               }
 
                if (scale & HN_GETSCALE)
                        return (i);
-       } else
-               for (i = 0; i < scale && i < maxscale; i++)
-                       scalable /= divisor;
+       } else {
+               for (i = 0; i < scale && i < maxscale; i++) {
+                       remainder = quotient % divisor;
+                       quotient /= divisor;
+               }
+       }
 
        /* If a value <= 9.9 after rounding and ... */
-       if (scalable < 995 && i > 0 && flags & HN_DECIMAL) {
-               /* baselen + \0 + .N */
-               if (len < baselen + 1 + 2)
-                       return (-1);
-               b = ((int)scalable + 5) / 10;
-               s1 = b / 10;
-               s2 = b % 10;
-               r = snprintf(buf, len, "%s%d%s%d%s%s%s",
-                       ((sign == -1) ? "-" : ""),
-                   s1, localeconv()->decimal_point, s2,
+       /*
+        * XXX - should we make sure there is enough space for the decimal
+        * place and if not, don't do HN_DECIMAL?
+        */
+       if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) &&
+           i > 0 && flags & HN_DECIMAL) {
+               s1 = (int)quotient + ((remainder * 10 + divisor / 2) /
+                   divisor / 10);
+               s2 = ((remainder * 10 + divisor / 2) / divisor) % 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, "%s%lld%s%s%s",
-                   /* LONGLONG */
-                       ((sign == -1) ? "-" : ""),
-                   (long long)((scalable + 50) / 100),
+               r = snprintf(buf, len, "%" PRId64 "%s%s%s",
+                   sign * (quotient + (remainder + divisor / 2) / divisor),
                    sep, SCALE2PREFIX(i), suffix);
 
        return (r);
index 16a935ffd085a589370d8a2f8a4b6dff1f1a0b9c..4b5ed047ceac0005d8b1138541378eb3cbdeaea9 100644 (file)
--- a/libutil.h
+++ b/libutil.h
@@ -81,13 +81,15 @@ __END_DECLS
 #define HOSTNAME_INVALIDADDR   (2)
 #define HOSTNAME_INVALIDNAME   (3)
 
-/* humanize_number(3) */
-#define HN_DECIMAL             0x01
-#define HN_NOSPACE             0x02
-#define HN_B                   0x04
-#define HN_DIVISOR_1000                0x08
+/* Values for humanize_number(3)'s flags parameter. */
+#define        HN_DECIMAL              0x01
+#define        HN_NOSPACE              0x02
+#define        HN_B                    0x04
+#define        HN_DIVISOR_1000         0x08
+#define        HN_IEC_PREFIXES         0x10
 
-#define HN_GETSCALE            0x10
-#define HN_AUTOSCALE           0x20
+/* Values for humanize_number(3)'s scale parameter. */
+#define        HN_GETSCALE             0x10
+#define        HN_AUTOSCALE            0x20
 
 #endif /* !_LIBUTIL_H_ */
index 965c679a4fad78102f39cfc6ade6e3627bc0d57e..a8b631ac4663768e8d5f4aad7f4ea665df21eba0 100644 (file)
@@ -7,6 +7,17 @@
        objects = {
 
 /* Begin PBXAggregateTarget section */
+               FDA4990F199D69B800A32E83 /* tests */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = FDA49910199D69B800A32E83 /* Build configuration list for PBXAggregateTarget "tests" */;
+                       buildPhases = (
+                       );
+                       dependencies = (
+                               FDA49918199D69C800A32E83 /* PBXTargetDependency */,
+                       );
+                       name = tests;
+                       productName = tests;
+               };
                FDBC26E41741B09300CA4B2B /* osx */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = FDBC26E71741B09300CA4B2B /* Build configuration list for PBXAggregateTarget "osx" */;
@@ -14,6 +25,7 @@
                        );
                        dependencies = (
                                FDBC27001741B1B300CA4B2B /* PBXTargetDependency */,
+                               FDA49916199D69C600A32E83 /* PBXTargetDependency */,
                        );
                        name = osx;
                        productName = OSX;
@@ -25,6 +37,7 @@
                        );
                        dependencies = (
                                FDBC27021741B1B500CA4B2B /* PBXTargetDependency */,
+                               FDA49914199D69C100A32E83 /* PBXTargetDependency */,
                                FDBC27041741B1B700CA4B2B /* PBXTargetDependency */,
                        );
                        name = ios;
@@ -55,6 +68,8 @@
                BA79F9E613BB76B0006A292D /* wipefs.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9BC13BB70FF006A292D /* wipefs.3 */; };
                BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9AB13BB70FF006A292D /* libutil.plist */; };
                BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9AC13BB70FF006A292D /* libutil.txt */; };
+               FDA4991B199D6A0400A32E83 /* humanize_number_test.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA4991A199D6A0400A32E83 /* humanize_number_test.c */; };
+               FDA4991C199D6B9300A32E83 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA79F9C513BB718B006A292D /* libutil.dylib */; };
                FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */; };
                FDBC27061741B1CF00CA4B2B /* tzlinkd.c in Sources */ = {isa = PBXBuildFile; fileRef = FDBC26FE1741B19000CA4B2B /* tzlinkd.c */; };
                FDBC27071741B1D600CA4B2B /* tzlink.c in Sources */ = {isa = PBXBuildFile; fileRef = FDBC26F91741B18500CA4B2B /* tzlink.c */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+               FDA49913199D69C100A32E83 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = BA79F99713BB70D7006A292D /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = FDA4990F199D69B800A32E83;
+                       remoteInfo = tests;
+               };
+               FDA49915199D69C600A32E83 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = BA79F99713BB70D7006A292D /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = FDA4990F199D69B800A32E83;
+                       remoteInfo = tests;
+               };
+               FDA49917199D69C800A32E83 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = BA79F99713BB70D7006A292D /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = FDA49902199D69B000A32E83;
+                       remoteInfo = humanize_number_test;
+               };
                FDBC26FF1741B1B300CA4B2B /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = BA79F99713BB70D7006A292D /* Project object */;
                BA79F9DB13BB7698006A292D /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "$(INSTALL_PATH_PREFIX)/usr/local/share/man/man3";
+                       dstPath = "/usr/local/share/man/man3";
                        dstSubfolderSpec = 0;
                        files = (
                                BA79F9DD13BB76B0006A292D /* getmntopts.3 in CopyFiles */,
                BA79F9E713BB77BB006A292D /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "$(INSTALL_PATH_PREFIX)/usr/local/OpenSourceVersions";
+                       dstPath = "/usr/local/OpenSourceVersions";
                        dstSubfolderSpec = 0;
                        files = (
                                BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */,
                BA79F9E813BB77D6006A292D /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "$(INSTALL_PATH_PREFIX)/usr/local/OpenSourceLicenses";
+                       dstPath = "/usr/local/OpenSourceLicenses";
                        dstSubfolderSpec = 0;
                        files = (
                                BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */,
                FDBC26EE1741B13400CA4B2B /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 2147483647;
-                       dstPath = "$(INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons";
+                       dstPath = "/System/Library/LaunchDaemons";
                        dstSubfolderSpec = 0;
                        files = (
                                FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */,
                BA79F9BD13BB70FF006A292D /* wipefs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wipefs.cpp; sourceTree = "<group>"; };
                BA79F9BE13BB70FF006A292D /* wipefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wipefs.h; sourceTree = "<group>"; };
                BA79F9C513BB718B006A292D /* libutil.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libutil.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+               FDA49903199D69B000A32E83 /* humanize_number_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = humanize_number_test; sourceTree = BUILT_PRODUCTS_DIR; };
+               FDA4991A199D6A0400A32E83 /* humanize_number_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = humanize_number_test.c; sourceTree = "<group>"; };
+               FDA4991D199D6CB800A32E83 /* test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = test.xcconfig; sourceTree = "<group>"; };
                FDBC26F01741B13400CA4B2B /* tzlinkd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tzlinkd; sourceTree = BUILT_PRODUCTS_DIR; };
                FDBC26F91741B18500CA4B2B /* tzlink.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tzlink.c; sourceTree = "<group>"; };
                FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.tzlinkd.plist; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               FDA49900199D69B000A32E83 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               FDA4991C199D6B9300A32E83 /* libutil.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FDBC26ED1741B13400CA4B2B /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                BA79F9B513BB70FF006A292D /* realhostname.c */,
                                BA79F9B613BB70FF006A292D /* reexec_to_match_kernel.3 */,
                                BA79F9B713BB70FF006A292D /* reexec_to_match_kernel.c */,
+                               FDA49919199D6A0400A32E83 /* tests */,
                                BA79F9B813BB70FF006A292D /* trimdomain.3 */,
                                BA79F9B913BB70FF006A292D /* trimdomain.c */,
                                FDBC26F91741B18500CA4B2B /* tzlink.c */,
                        children = (
                                BA79F9C513BB718B006A292D /* libutil.dylib */,
                                FDBC26F01741B13400CA4B2B /* tzlinkd */,
+                               FDA49903199D69B000A32E83 /* humanize_number_test */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                };
+               FDA49919199D6A0400A32E83 /* tests */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FDA4991A199D6A0400A32E83 /* humanize_number_test.c */,
+                       );
+                       path = tests;
+                       sourceTree = "<group>";
+               };
                FDBC26F11741B13400CA4B2B /* tzlinkd */ = {
                        isa = PBXGroup;
                        children = (
                FDBC270C1741B66500CA4B2B /* xcconfigs */ = {
                        isa = PBXGroup;
                        children = (
+                               FDA4991D199D6CB800A32E83 /* test.xcconfig */,
                                FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */,
                        );
                        path = xcconfigs;
                        productReference = BA79F9C513BB718B006A292D /* libutil.dylib */;
                        productType = "com.apple.product-type.library.dynamic";
                };
+               FDA49902199D69B000A32E83 /* humanize_number_test */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = FDA4990E199D69B000A32E83 /* Build configuration list for PBXNativeTarget "humanize_number_test" */;
+                       buildPhases = (
+                               FDA498FF199D69B000A32E83 /* Sources */,
+                               FDA49900199D69B000A32E83 /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = humanize_number_test;
+                       productName = humanize_number_test;
+                       productReference = FDA49903199D69B000A32E83 /* humanize_number_test */;
+                       productType = "com.apple.product-type.tool";
+               };
                FDBC26EF1741B13400CA4B2B /* tzlinkd */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = FDBC26F81741B13400CA4B2B /* Build configuration list for PBXNativeTarget "tzlinkd" */;
                                FDBC26E41741B09300CA4B2B /* osx */,
                                BA79F9C413BB718B006A292D /* util */,
                                FDBC26EF1741B13400CA4B2B /* tzlinkd */,
+                               FDA4990F199D69B800A32E83 /* tests */,
+                               FDA49902199D69B000A32E83 /* humanize_number_test */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               FDA498FF199D69B000A32E83 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               FDA4991B199D6A0400A32E83 /* humanize_number_test.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FDBC26EC1741B13400CA4B2B /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+               FDA49914199D69C100A32E83 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = FDA4990F199D69B800A32E83 /* tests */;
+                       targetProxy = FDA49913199D69C100A32E83 /* PBXContainerItemProxy */;
+               };
+               FDA49916199D69C600A32E83 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = FDA4990F199D69B800A32E83 /* tests */;
+                       targetProxy = FDA49915199D69C600A32E83 /* PBXContainerItemProxy */;
+               };
+               FDA49918199D69C800A32E83 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = FDA49902199D69B000A32E83 /* humanize_number_test */;
+                       targetProxy = FDA49917199D69C800A32E83 /* PBXContainerItemProxy */;
+               };
                FDBC27001741B1B300CA4B2B /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = BA79F9C413BB718B006A292D /* util */;
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               INSTALL_PATH_ACTUAL = /usr/lib;
+                               HEADER_SEARCH_PATHS = "$(SRCROOT)";
+                               INSTALL_PATH = /usr/lib;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                WARNING_CFLAGS = "-Wall";
                        };
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               INSTALL_PATH_ACTUAL = /usr/lib;
+                               HEADER_SEARCH_PATHS = "$(SRCROOT)";
+                               INSTALL_PATH = /usr/lib;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                WARNING_CFLAGS = "-Wall";
                        };
                        name = Release;
                };
+               FDA4990C199D69B000A32E83 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = FDA4991D199D6CB800A32E83 /* test.xcconfig */;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               FDA4990D199D69B000A32E83 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = FDA4991D199D6CB800A32E83 /* test.xcconfig */;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               FDA49911199D69B800A32E83 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               FDA49912199D69B800A32E83 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                FDBC26E51741B09300CA4B2B /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               FDA4990E199D69B000A32E83 /* Build configuration list for PBXNativeTarget "humanize_number_test" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               FDA4990C199D69B000A32E83 /* Debug */,
+                               FDA4990D199D69B000A32E83 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               FDA49910199D69B800A32E83 /* Build configuration list for PBXAggregateTarget "tests" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               FDA49911199D69B800A32E83 /* Debug */,
+                               FDA49912199D69B800A32E83 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                FDBC26E71741B09300CA4B2B /* Build configuration list for PBXAggregateTarget "osx" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/tests/humanize_number_test.c b/tests/humanize_number_test.c
new file mode 100644 (file)
index 0000000..8aed540
--- /dev/null
@@ -0,0 +1,602 @@
+/*-
+ * Copyright 2012 Clifton Royston
+ * Copyright 2013 John-Mark Gurney
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#include <sys/param.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define        MAX_STR_FLAGS_RESULT    80
+#define MAX_INT_STR_DIGITS     12
+#ifdef __APPLE__
+#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
+#define __INT_MAX INT_MAX
+#endif /* __APPLE__ */
+
+static const int64_t halfExabyte = (int64_t)500*1000*1000*1000*1000*1000L;
+
+static struct {
+       int retval;
+       const char *res;
+       int64_t num;
+       int flags;
+       int scale;
+} test_args[] = {
+       /* tests 0-13 test 1000 suffixes */
+       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+
+       /* tests 14-27 test 1024 suffixes */
+       { 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE },
+       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
+       { 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE },
+       { 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE },
+       { 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE },
+       { 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+
+       /* tests 28-37 test rounding */
+       { 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE },
+       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
+       { 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
+       { 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE },
+       { 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE },
+
+       /* tests 38-61 test specific scale factors with 1000 divisor */
+       { 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1 },
+       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1 },
+       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2 },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2 },
+       { 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3 },
+       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3 },
+       { 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4 },
+       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
+       { 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
+       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
+       { 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1 },
+       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1 },
+       { 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2 },
+       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2 },
+       { 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3 },
+       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3 },
+       { 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4 },
+       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
+       { 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
+       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
+       { 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+
+       /* tests 62-85 test specific scale factors with 1024 divisor */
+       { 3, "0 K", (int64_t)0L, 0, 1 },
+       { 3, "1 K", (int64_t)512L, 0, 1 },
+       { 3, "0 M", (int64_t)512L, 0, 2 },
+       { 3, "1 M", (int64_t)512*1024L, 0, 2 },
+       { 3, "0 G", (int64_t)512*1024L, 0, 3 },
+       { 3, "1 G", (int64_t)512*1024*1024L, 0, 3 },
+       { 3, "0 T", (int64_t)512*1024*1024L, 0, 4 },
+       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4 },
+       { 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5 },
+       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5 },
+       { 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6 },
+       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 K", (int64_t)1L, 0, 1 },
+       { 3, "2 K", (int64_t)1536L, 0, 1 },
+       { 3, "0 M", (int64_t)1536L, 0, 2 },
+       { 3, "2 M", (int64_t)1536*1024L, 0, 2 },
+       { 3, "0 G", (int64_t)1536*1024L, 0, 3 },
+       { 3, "2 G", (int64_t)1536*1024*1024L, 0, 3 },
+       { 3, "0 T", (int64_t)1536*1024*1024L, 0, 4 },
+       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4 },
+       { 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5 },
+       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5 },
+       { 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6 },
+       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6 },
+
+       /* tests 86-99 test invalid specific scale values of < 0 or >= 7 with
+       and without HN_DIVISOR_1000 set */
+       /*  all should return errors with new code; with old, the latter 3
+       are instead processed as if having AUTOSCALE and/or GETSCALE set */
+       { -1, "", (int64_t)1L, 0, 7 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 7 },
+       { -1, "", (int64_t)1L, 0, 1000 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000 },
+       { -1, "", (int64_t)0L, 0, 1000*1000 },
+       { -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000 },
+       { -1, "", (int64_t)0L, 0, INT_MAX },
+       { -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX },
+
+       /* Negative scale values are not handled well
+        by the existing library routine - should report as error */
+       /*  all should return errors with new code, fail assertion with old */
+
+       { -1, "", (int64_t)1L, 0, -1 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1 },
+       { -1, "", (int64_t)1L, 0, -1000 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000 },
+
+       /* __INT_MIN doesn't print properly, skipped. */
+
+       { -1, "", (int64_t)1L, 0, -__INT_MAX },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX },
+
+
+       /* tests for scale == 0, without autoscale */
+       /* tests 100-114 test scale 0 with 1000 divisor - print first N digits */
+       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0 },
+       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0 },
+       { 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0 },
+       { 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE },
+       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE },
+       { 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE },
+       { 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0 },
+       { 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0 },
+       { 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0 },
+       { 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0 },
+       { 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0 },
+       { 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0 },
+       { 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0 },
+       { 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0 },
+       { 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0 },
+
+       /* tests 115-126 test scale 0 with 1024 divisor - print first N digits */
+       { 2, "0 ", (int64_t)0L, 0, 0 },
+       { 2, "1 ", (int64_t)1L, 0, 0 },
+       { 3, "10 ", (int64_t)10L, 0, 0 },
+       { 4, "150", (int64_t)150L, 0, 0 },
+       { 4, "500", (int64_t)500L, 0, 0 },
+       { 4, "999", (int64_t)999L, 0, 0 },
+       { 5, "100", (int64_t)1000L, 0, 0 },
+       { 5, "150", (int64_t)1500L, 0, 0 },
+       { 7, "500", (int64_t)500*1000L, 0, 0 },
+       { 8, "150", (int64_t)1500*1000L, 0, 0 },
+       { 10, "500", (int64_t)500*1000*1000L, 0, 0 },
+       { 11, "150", (int64_t)1500*1000*1000L, 0, 0 },
+
+       /* Test boundary cases for very large positive/negative number formatting */
+       /* Explicit scale, divisor 1024 */
+
+       /* XXX = requires length 5 (buflen 6) for some cases*/
+       /* KLUDGE - test loop below will bump length 5 up to 5 */
+       { 3, "8 E",   INT64_MAX, 0, 6 },
+       { 4, "-8 E", -INT64_MAX, 0, 6 },
+       { 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
+       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
+       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
+       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
+       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
+       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
+       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
+
+       /* Explicit scale, divisor 1000 */
+       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, 6 },
+       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000,  6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
+       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
+       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
+       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
+       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
+
+       /* Autoscale, divisor 1024 */
+       { 3, "8 E",   INT64_MAX, 0, HN_AUTOSCALE },
+       { 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE },
+       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       /* Autoscale, divisor 1000 */
+       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
+
+       /* 0 scale, divisor 1024 */
+       { 12, "skdj",  INT64_MAX, 0, 0 },
+       { 21, "-9223", -INT64_MAX, 0, 0 },
+       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
+       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
+       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
+       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
+       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
+       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
+
+       /* 0 scale, divisor 1000 */
+       /* XXX - why does this fail? */
+       { -1, "", INT64_MAX, HN_DIVISOR_1000, 0 },
+       { 21, "-9223", -INT64_MAX, HN_DIVISOR_1000,  0 },
+       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+       /* Expected to pass */
+       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
+
+
+
+       /* Need to implement tests for GETSCALE */
+/*     { ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE },
+       ...
+*/
+        /* Tests for HN_DECIMAL */
+        /* Positive, Autoscale */
+       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+
+       { 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       /* XXX - shouldn't the following two be "10. M"? */
+       { 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+
+        /* Negative, Autoscale - should pass */
+       { 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+
+       { 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE },
+
+       /* Positive/negative, at maximum scale */
+       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+        /* Negatives work with latest rev only: */
+       { 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+
+       { 5, "8.0 E",   INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "7.9 E",   INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE },
+       { 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
+       { 6, "-7.9 ",   -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE },
+
+       /* Positive, Fixed scales */
+       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
+       { 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
+       { 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
+       { 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
+       { 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
+       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
+       { 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
+       /* Positive/negative, at maximum scale */
+       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
+       { 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
+       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6 },
+
+       /* HN_DECIMAL + binary + fixed scale cases not completed */
+       { 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1 },
+       { 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2 },
+
+       /* Negative, Fixed scales */
+        /* Not yet added, but should work with latest rev */
+
+};
+
+
+/* Command line options usage */
+static void
+usage(char * progname) {
+       printf("%s: tests libutil humanize_number function\n", progname);
+       printf("Usage: %s [-nE] [-l num] [-v]\n\n", progname);
+       printf("Options:\n");
+       printf("\t-l num\tSet max length for result; buflen = num + 1\n");
+       printf("\t\t  (NOTE: does not change expected result strings.)\n");
+       printf("\t-n\tInclude negative scale tests, which cause older libutil\n");
+       printf("\t\t  version of function to coredump with assertion failure\n");
+       printf("\t-E\tInclude numbers > 1/2 Exa[byte] which currently fail\n");
+       printf("\t-v\tVerbose - always print summary results\n");
+       printf("\t-h, -?\tShow options\n");
+}
+
+/* Parse command line options */
+static void
+read_options(int argc, char * const argv[], size_t *bufLength,
+    int *includeNegativeScale, int *includeExabytes, int *verbose) {
+       int ch;
+       size_t temp;
+
+       while ((ch = getopt(argc, argv, "nEh?vl:")) != -1) {
+               switch (ch) {
+                       default:
+                               usage(argv[0]);
+                               exit(1);
+                               break;  /* UNREACHABLE */
+                       case 'h' :
+                       case '?' :
+                               usage(argv[0]);
+                               exit(0);
+                               break;  /* UNREACHABLE */
+                       case 'l' :
+                               sscanf(optarg, "%zu", &temp);
+                               *bufLength = temp + 1;
+                               break;
+                       case 'n' :
+                               *includeNegativeScale = 1;
+                               break;
+                       case 'E' :
+                               *includeExabytes = 1;
+                               break;
+                       case 'v' :
+                               *verbose = 1;
+                               break;
+               }
+       }
+}
+
+static struct {
+       int value;
+       const char *name;
+ } flags[] = {
+       { HN_AUTOSCALE, "HN_AUTOSCALE" },
+       { HN_GETSCALE, "HN_GETSCALE" },
+       { HN_DIVISOR_1000, "HN_DIVISOR_1000"},
+       { HN_B, "HN_B"},
+       { HN_DECIMAL, "HN_DECIMAL"},
+};
+
+static const char *separator = "|";
+
+/* Format flags parameter for meaningful display */
+static char *
+str_flags(int hn_flags, char *noFlags) {
+       size_t i;
+       char * result;
+
+       result = malloc(MAX_STR_FLAGS_RESULT);
+       result[0] = '\0';
+
+       for (i = 0; i < sizeof flags / sizeof *flags; i++) {
+               if (hn_flags & flags[i].value) {
+                       if (*result != 0)
+                               strlcat(result, separator,
+                                   MAX_STR_FLAGS_RESULT);
+                       strlcat(result, flags[i].name, MAX_STR_FLAGS_RESULT);
+               }
+       }
+
+       if (strlen(result) == 0)
+               strlcat(result, noFlags, MAX_STR_FLAGS_RESULT);
+       return result;
+}
+
+
+/* Format scale parameter for meaningful display */
+static char *
+str_scale(int scale) {
+       char *result;
+
+       if (scale == HN_AUTOSCALE || scale == HN_GETSCALE)
+               return str_flags(scale, "");
+
+       result = malloc(MAX_INT_STR_DIGITS);
+       result[0] = '\0';
+       snprintf(result, MAX_INT_STR_DIGITS, "%d", scale);
+       return result;
+}
+
+static void
+testskipped(size_t i)
+{
+
+       printf("ok %zu # skip - not turned on\n", i);
+}
+
+int
+main(int argc, char * const argv[])
+{
+       char *buf;
+       char *flag_str, *scale_str;
+       size_t buflen, errcnt, i, skipped, tested;
+       int r;
+       int includeNegScale;
+       int includeExabyteTests;
+       int verbose;
+
+       buflen = 4;
+       includeNegScale = 0;
+       includeExabyteTests = 0;
+       verbose = 0;
+
+       read_options(argc, argv, &buflen, &includeNegScale,
+           &includeExabyteTests, &verbose);
+
+       buf = malloc(buflen);
+       errcnt = 0;
+       tested = 0;
+       skipped = 0;
+
+       if (buflen != 4)
+               printf("Warning: buffer size %zu != 4, expect some results to differ.\n", buflen);
+
+       printf("1..%zu\n", nitems(test_args));
+       for (i = 0; i < nitems(test_args); i++) {
+               /* KLUDGE */
+               if (test_args[i].num == INT64_MAX && buflen == 4) {
+                       /* Start final tests which require buffer of 6 */
+                       free(buf);
+                       buflen = 6;
+                        buf = malloc(buflen);
+                        if (verbose)
+                                printf("Buffer length increased to %zu\n",
+                                   buflen);
+               }
+
+               if (test_args[i].scale < 0 && ! includeNegScale) {
+                       skipped++;
+                       testskipped(i + 1);
+                       continue;
+               }
+               if (test_args[i].num >= halfExabyte && ! includeExabyteTests) {
+                       skipped++;
+                       testskipped(i + 1);
+                       continue;
+               }
+
+               r = humanize_number(buf, buflen, test_args[i].num, "",
+                   test_args[i].scale, test_args[i].flags);
+               flag_str = str_flags(test_args[i].flags, "[no flags]");
+               scale_str = str_scale(test_args[i].scale);
+
+               if (r != test_args[i].retval) {
+                       if (verbose)
+                               printf("wrong return value on index %zu, "
+                                   "buflen: %zu, got: %d + \"%s\", "
+                                   "expected %d + \"%s\"; num = %jd, "
+                                   "scale = %s, flags= %s.\n",
+                                   i, buflen, r, buf, test_args[i].retval,
+                                   test_args[i].res,
+                                   (intmax_t)test_args[i].num,
+                                   scale_str, flag_str);
+                       else
+                               printf("not ok %zu # return %d != %d\n",
+                                   i + 1, r, test_args[i].retval);
+                       errcnt++;
+               } else if (strcmp(buf, test_args[i].res) != 0) {
+                       if (verbose)
+                               printf("result mismatch on index %zu, got: "
+                                   "\"%s\", expected \"%s\"; num = %jd, "
+                                   "scale = %s, flags= %s.\n",
+                                   i, buf, test_args[i].res,
+                                   (intmax_t)test_args[i].num,
+                                   scale_str, flag_str);
+                       else
+                               printf("not ok %zu # buf \"%s\" != \"%s\"\n",
+                                   i + 1, buf, test_args[i].res);
+                       errcnt++;
+               } else {
+                       if (verbose)
+                               printf("successful result on index %zu, "
+                                   "returned %d, got: \"%s\"; num = %jd, "
+                                   "scale = %s, flags= %s.\n",
+                                   i, r, buf,
+                                   (intmax_t)test_args[i].num,
+                                   scale_str, flag_str);
+                       else
+                               printf("ok %zu\n", i + 1);
+               }
+               tested++;
+       }
+
+       if (verbose)
+               printf("total errors: %zu/%zu tests, %zu skipped\n", errcnt,
+                   tested, skipped);
+
+       if (errcnt)
+               return 1;
+
+       return 0;
+}
index d9d1d653304d730e389fbcc3fa998cc57916b3cc..3be8ae1e2419d9d8cca103f27b2c5916a8ab2217 100644 (file)
@@ -127,6 +127,14 @@ AddExtentsForPartitions(class ExtentManager *extMan)
        extMan->AddByteRangeExtent(extMan->totalBytes - 512 * 33, 512 * 33);
 }
 
+static void
+AddExtentsForCoreStorage(class ExtentManager *extMan)
+{
+       // the CoreStorage VolumeHeader structures reside in the first/last 512 bytes of each PV
+       extMan->AddByteRangeExtent(0, 512);
+       extMan->AddByteRangeExtent(extMan->totalBytes - 512, 512);
+}
+
 extern "C" int
 wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle)
 {
@@ -188,6 +196,7 @@ wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle)
                AddExtentsForUFS(extMan);
                AddExtentsForZFS(extMan);
                AddExtentsForPartitions(extMan);
+               AddExtentsForCoreStorage(extMan);
        }
        catch (bad_alloc &e) {
                err = ENOMEM;
@@ -300,6 +309,8 @@ wipefs_wipe(wipefs_ctx handle)
        }       
 
   labelExit:
+
+       (void)ioctl(handle->fd, DKIOCSYNCHRONIZECACHE);
        if (bufZero != NULL)
                delete[] bufZero;
        return err;
index c51588b92f4a11e14c9653848c26f6e321f09e32..64031d0ca924f19cd14d85c7adf534b9d4ff0121 100644 (file)
@@ -1,11 +1,3 @@
 #include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
-#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
-
-// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable
-INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL)
-
-// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as a prefix for other
-// variables as appropriate
-PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include
-PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include
-
+PUBLIC_HEADERS_FOLDER_PATH = /usr/include
+PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include
diff --git a/xcconfigs/test.xcconfig b/xcconfigs/test.xcconfig
new file mode 100644 (file)
index 0000000..bce8946
--- /dev/null
@@ -0,0 +1 @@
+INSTALL_PATH = /AppleInternal/CoreOS/libutil
index 8c330db4554fb246d6c7d2d048e3f8b073ee94cb..185eb5c5c4e567215830fdb93707ed899684e834 100644 (file)
@@ -1,9 +1,4 @@
-#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
-
-// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be
-INSTALL_PATH_ACTUAL = /usr/sbin
-
-INSTALL_PATH_ACTUAL = /usr/libexec
+INSTALL_PATH = /usr/libexec
 PRODUCT_NAME = tzlinkd
 
 CODE_SIGN_IDENTITY = -