Index: stable/8/lib/libutil/humanize_number.3 =================================================================== --- stable/8/lib/libutil/humanize_number.3 (revision 221192) +++ stable/8/lib/libutil/humanize_number.3 (revision 221193) @@ -1,157 +1,204 @@ .\" $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $ .\" $FreeBSD$ .\" .\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation .\" by Luke Mewburn and by Tomas Svensson. .\" .\" 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. .\" 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 .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 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. .\" -.Dd May 25, 2004 +.Dd Apr 12, 2011 .Dt HUMANIZE_NUMBER 3 .Os .Sh NAME .Nm humanize_number .Nd format a number into a human readable form .Sh LIBRARY .Lb libutil .Sh SYNOPSIS .In libutil.h .Ft int .Fo humanize_number .Fa "char *buf" "size_t len" "int64_t number" "const char *suffix" .Fa "int scale" "int flags" .Fc .Sh DESCRIPTION The .Fn humanize_number function formats the signed 64-bit quantity given in .Fa number into .Fa buf . A space and then .Fa suffix is appended to the end. The buffer pointed to by .Fa buf must be at least .Fa len bytes long. .Pp If the formatted number (including .Fa suffix ) would be too long to fit into .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 rather than the proposed -SI power of two convention. +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 prefixes are: +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 k Ta No kilo Ta 1024 Ta 1000 +.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 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 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 .Fa len argument must be at least 4 plus the length of .Fa suffix , in order to ensure a useful result is generated into .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. .Pp The following flags may be passed in .Fa scale : .Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent .It Dv HN_AUTOSCALE Format the buffer using the lowest multiplier possible. .It Dv HN_GETSCALE Return the prefix index number (the number of times .Fa number must be divided to fit) instead of formatting it to the buffer. .El .Pp 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. .It Dv HN_NOSPACE Do not put a space between .Fa number and the prefix. .It Dv HN_B Use .Ql B (bytes) as prefix if the original result does not have a prefix. .It Dv HN_DIVISOR_1000 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 buf (excluding the terminating .Dv NUL ) upon success, or \-1 upon failure. 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 and then in .Fx 5.3 . +The +.Dv HN_IEC_PREFIXES +flag was introduced in +.Fx 9.0 . Index: stable/8/lib/libutil/humanize_number.c =================================================================== --- stable/8/lib/libutil/humanize_number.c (revision 221192) +++ stable/8/lib/libutil/humanize_number.c (revision 221193) @@ -1,154 +1,167 @@ /* $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. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson. * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include +static const int maxscale = 7; + int humanize_number(char *buf, size_t len, int64_t quotient, const char *suffix, int scale, int flags) { const char *prefixes, *sep; - int i, r, remainder, maxscale, s1, s2, sign; + int i, r, remainder, s1, s2, sign; int64_t divisor, max; size_t baselen; assert(buf != NULL); assert(suffix != NULL); assert(scale >= 0); + assert(scale < maxscale || (((scale & (HN_AUTOSCALE | HN_GETSCALE)) != 0))); + assert(!((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))); remainder = 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 { + 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; 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\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei"; + } else { + baselen = 1; + if (flags & HN_DIVISOR_1000) + divisor = 1000; + else + divisor = 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; +#define SCALE2PREFIX(scale) (&prefixes[(scale) * 3]) - if (scale >= maxscale && - (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0) + if (scale < 0 || (scale >= maxscale && + (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)) return (-1); if (buf == NULL || suffix == NULL) return (-1); if (len > 0) buf[0] = '\0'; if (quotient < 0) { sign = -1; quotient = -quotient; - baselen = 3; /* sign, digit, prefix */ + baselen += 2; /* sign, digit */ } else { sign = 1; - baselen = 2; /* digit, prefix */ + baselen += 1; /* digit */ } if (flags & HN_NOSPACE) sep = ""; else { sep = " "; baselen++; } baselen += strlen(suffix); /* Check if enough room for `x y' + suffix + `\0' */ if (len < baselen + 1) return (-1); if (scale & (HN_AUTOSCALE | HN_GETSCALE)) { /* See if there is additional columns can be used. */ for (max = 1, i = len - baselen; i-- > 0;) max *= 10; /* * 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 >= 950)) && i < maxscale; i++) { remainder = quotient % divisor; quotient /= divisor; } if (scale & HN_GETSCALE) return (i); } else { for (i = 0; i < scale && i < maxscale; i++) { remainder = quotient % divisor; quotient /= divisor; } } /* If a value <= 9.9 after rounding and ... */ if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) { /* baselen + \0 + .N */ if (len < baselen + 1 + 2) return (-1); 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 * (quotient + (remainder + 50) / 1000), sep, SCALE2PREFIX(i), suffix); return (r); } Index: stable/8/lib/libutil/libutil.h =================================================================== --- stable/8/lib/libutil/libutil.h (revision 221192) +++ stable/8/lib/libutil/libutil.h (revision 221193) @@ -1,221 +1,223 @@ /* * Copyright (c) 1996 Peter Wemm . * All rights reserved. * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, is 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. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * 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$ */ #ifndef _LIBUTIL_H_ #define _LIBUTIL_H_ #include #include #ifndef _GID_T_DECLARED typedef __gid_t gid_t; #define _GID_T_DECLARED #endif #ifndef _INT64_T_DECLARED typedef __int64_t int64_t; #define _INT64_T_DECLARED #endif #ifndef _UINT64_T_DECLARED typedef __uint64_t uint64_t; #define _UINT64_T_DECLARED #endif #ifndef _PID_T_DECLARED typedef __pid_t pid_t; #define _PID_T_DECLARED #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _UID_T_DECLARED typedef __uid_t uid_t; #define _UID_T_DECLARED #endif #define PROPERTY_MAX_NAME 64 #define PROPERTY_MAX_VALUE 512 /* for properties.c */ typedef struct _property { struct _property *next; char *name; char *value; } *properties; #ifdef _SYS_PARAM_H_ /* for pidfile.c */ struct pidfh { int pf_fd; char pf_path[MAXPATHLEN + 1]; __dev_t pf_dev; ino_t pf_ino; }; #endif /* Avoid pulling in all the include files for no need */ struct termios; struct winsize; struct utmp; struct in_addr; struct kinfo_file; struct kinfo_vmentry; __BEGIN_DECLS void clean_environment(const char * const *_white, const char * const *_more_white); int extattr_namespace_to_string(int _attrnamespace, char **_string); int extattr_string_to_namespace(const char *_string, int *_attrnamespace); int flopen(const char *_path, int _flags, ...); void hexdump(const void *ptr, int length, const char *hdr, int flags); void login(struct utmp *_ut); int login_tty(int _fd); int logout(const char *_line); void logwtmp(const char *_line, const char *_name, const char *_host); void trimdomain(char *_fullhost, int _hostsize); int openpty(int *_amaster, int *_aslave, char *_name, struct termios *_termp, struct winsize *_winp); int forkpty(int *_amaster, char *_name, struct termios *_termp, struct winsize *_winp); int humanize_number(char *_buf, size_t _len, int64_t _number, const char *_suffix, int _scale, int _flags); int expand_number(const char *_buf, int64_t *_num); const char *uu_lockerr(int _uu_lockresult); int uu_lock(const char *_ttyname); int uu_unlock(const char *_ttyname); int uu_lock_txfr(const char *_ttyname, pid_t _pid); int _secure_path(const char *_path, uid_t _uid, gid_t _gid); properties properties_read(int fd); void properties_free(properties list); char *property_find(properties list, const char *name); char *auth_getval(const char *name); int realhostname(char *host, size_t hsize, const struct in_addr *ip); struct sockaddr; int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen); int kld_isloaded(const char *name); int kld_load(const char *name); struct kinfo_file * kinfo_getfile(pid_t _pid, int *_cntp); struct kinfo_vmentry * kinfo_getvmmap(pid_t _pid, int *_cntp); #ifdef _STDIO_H_ /* avoid adding new includes */ char *fparseln(FILE *, size_t *, size_t *, const char[3], int); #endif #ifdef _PWD_H_ int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw); struct passwd *pw_dup(const struct passwd *_pw); int pw_edit(int _notsetuid); int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2); void pw_fini(void); int pw_init(const char *_dir, const char *_master); char *pw_make(const struct passwd *_pw); int pw_mkdb(const char *_user); int pw_lock(void); struct passwd *pw_scan(const char *_line, int _flags); const char *pw_tempname(void); int pw_tmp(int _mfd); #endif #ifdef _GRP_H_ int gr_equal(const struct group *gr1, const struct group *gr2); char *gr_make(const struct group *gr); struct group *gr_dup(const struct group *gr); struct group *gr_scan(const char *line); #endif #ifdef _SYS_PARAM_H_ struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr); int pidfile_write(struct pidfh *pfh); int pidfile_close(struct pidfh *pfh); int pidfile_remove(struct pidfh *pfh); #endif __END_DECLS #define UU_LOCK_INUSE (1) #define UU_LOCK_OK (0) #define UU_LOCK_OPEN_ERR (-1) #define UU_LOCK_READ_ERR (-2) #define UU_LOCK_CREAT_ERR (-3) #define UU_LOCK_WRITE_ERR (-4) #define UU_LOCK_LINK_ERR (-5) #define UU_LOCK_TRY_ERR (-6) #define UU_LOCK_OWNER_ERR (-7) /* return values from realhostname() */ #define HOSTNAME_FOUND (0) #define HOSTNAME_INCORRECTNAME (1) #define HOSTNAME_INVALIDADDR (2) #define HOSTNAME_INVALIDNAME (3) /* fparseln(3) */ #define FPARSELN_UNESCESC 0x01 #define FPARSELN_UNESCCONT 0x02 #define FPARSELN_UNESCCOMM 0x04 #define FPARSELN_UNESCREST 0x08 #define FPARSELN_UNESCALL 0x0f /* pw_scan() */ #define PWSCAN_MASTER 0x01 #define PWSCAN_WARN 0x02 /* humanize_number(3) */ #define HN_DECIMAL 0x01 #define HN_NOSPACE 0x02 #define HN_B 0x04 #define HN_DIVISOR_1000 0x08 +#define HN_IEC_PREFIXES 0x10 +/* maxscale = 0x07 */ #define HN_GETSCALE 0x10 #define HN_AUTOSCALE 0x20 /* hexdump(3) */ #define HD_COLUMN_MASK 0xff #define HD_DELIM_MASK 0xff00 #define HD_OMIT_COUNT (1 << 16) #define HD_OMIT_HEX (1 << 17) #define HD_OMIT_CHARS (1 << 18) #endif /* !_LIBUTIL_H_ */ Index: stable/8/lib/libutil =================================================================== --- stable/8/lib/libutil (revision 221192) +++ stable/8/lib/libutil (revision 221193) Property changes on: stable/8/lib/libutil ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/lib/libutil:r220582