diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index e13663ceafb..7157c51994b 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -6,9 +6,9 @@ SHLIB_MAJOR= 4 SHLIBDIR?= /lib CFLAGS+=-DLIBC_SCCS -I${.CURDIR} -I${.CURDIR}/../libc/gen/ CFLAGS+=-DINET6 -SRCS= _secure_path.c auth.c fparseln.c login.c login_auth.c \ - login_cap.c login_class.c login_crypt.c login_ok.c login_times.c \ - login_tty.c logout.c logwtmp.c property.c pty.c \ +SRCS= _secure_path.c auth.c fparseln.c humanize_number.c login.c \ + login_auth.c login_cap.c login_class.c login_crypt.c login_ok.c \ + login_times.c login_tty.c logout.c logwtmp.c property.c pty.c \ pw_util.c realhostname.c stub.c \ trimdomain.c uucplock.c INCS= libutil.h login_cap.h @@ -16,7 +16,7 @@ INCS= libutil.h login_cap.h MAN+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \ login_cap.3 login_class.3 login_times.3 login_ok.3 \ _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \ - realhostname_sa.3 trimdomain.3 fparseln.3 + realhostname_sa.3 trimdomain.3 fparseln.3 humanize_number.3 MAN+= login.conf.5 auth.conf.5 MLINKS+= property.3 properties_read.3 property.3 properties_free.3 MLINKS+= property.3 property_find.3 diff --git a/lib/libutil/humanize_number.3 b/lib/libutil/humanize_number.3 new file mode 100644 index 00000000000..edcc7c00e53 --- /dev/null +++ b/lib/libutil/humanize_number.3 @@ -0,0 +1,137 @@ +.\" $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 +.Dt HUMANIZE_NUMBER 3 +.Os +.Sh NAME +.Nm humanize_number +.Nd format a number into a human readable form +.Sh SYNOPSIS +.In util.h +.Ft int +.Fn humanize_number "char *buf" "size_t len" "int64_t number" "const char *suffix" "int scale" "int flags" +.Sh DESCRIPTION +The +.Fn humanize_number +function formats the signed 64 bit quantity given in +.Fa number +into +.Fa buffer . +A space and then +.Fa suffix +is appended to the end. +.Fa buffer +must be at least +.Fa len +bytes bytes long. +.Pp +If the formatted number (including +.Fa suffix ) +would be too long to fit into +.Fa buffer , +then divide +.Fa number +by 1024 until it will. +In this case, prefix +.Fa suffix +with the appropriate SI designator. +.Pp +The prefixes are: +.Bl -column "Prefix" "Description" "Multiplier" -offset indent +.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" +.It k kilo 1024 +.It M mega 1048576 +.It G giga 1073741824 +.It T tera 1099511627776 +.It P peta 1125899906842624 +.It E exa 1152921504606846976 +.El +.Pp +.Fa len +must be at least 4 plus the length of +.Fa suffix , +in order to ensure a useful result is generated into +.Fa buffer . +To use a specific prefix, specify this as +.Fa scale +(Multiplier = 1024 ^ scale). +This can not be combined with any of the +.Fa scale +flags below. +.Pp +The following flags may be passed in +.Pa scale : +.Bl -tag -width Dv -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 +.Pa flags : +.Bl -tag -width Dv -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 '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. +.El +.Sh RETURN VALUES +.Fn humanize_number +returns the number of characters stored in +.Fa buffer +(excluding the terminating 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 humanize_number 9 +.Sh HISTORY +.Fn humanize_number +first appeared in +.Nx 2.0 . diff --git a/lib/libutil/humanize_number.c b/lib/libutil/humanize_number.c new file mode 100644 index 00000000000..51bd24bb20d --- /dev/null +++ b/lib/libutil/humanize_number.c @@ -0,0 +1,160 @@ +/* $NetBSD: humanize_number.c,v 1.5 2003/12/26 11:30:36 simonb 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. + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +int +humanize_number(char *buf, size_t len, int64_t bytes, + const char *suffix, int scale, int flags) +{ + const char *prefixes; + int i, r; + int64_t divisor, max, s1, s2, sign; + size_t baselen, suffixlen; + + assert(buf != NULL); + assert(suffix != NULL); + assert(scale >= 0); + + if (flags & HN_DIVISOR_1000) { + /* SI for decimal multiplies */ + divisor = 1000; + prefixes = " kMGTPE"; + } else { + /* + * binary multiplies + * XXX IEC 60027-2 recommends Ki, Mi, Gi... + */ + divisor = 1024; + prefixes = " KMGTPE"; + } + + if ((size_t) scale >= strlen(prefixes) && scale != HN_AUTOSCALE && + scale != HN_GETSCALE) + return (-1); + + if (buf == NULL || suffix == NULL) + return (-1); + + if (len > 0) + buf[0] = '\0'; + if (bytes < 0) { + sign = -1; + bytes *= -100; + baselen = 4; + } else { + sign = 1; + bytes *= 100; + baselen = 3; + } + + suffixlen = strlen(suffix); + + /* check if enough room for `x y' + suffix + `\0' */ + if (len < baselen + suffixlen + 1) + return (-1); + + if (flags & HN_DIVISOR_1000) + divisor = 1000; + else + divisor = 1024; + + max = 100; + for (i = 0; + (size_t) i < len - suffixlen - baselen + ((flags & HN_NOSPACE) ? + 1 : 0); i++) + max *= 10; + + if ((scale & HN_AUTOSCALE) || (scale & HN_GETSCALE)) { + for (i = 0; bytes >= max && prefixes[i + 1]; i++) + bytes /= divisor; + } else { + for (i = 0; i < scale && prefixes[i + 1]; i++) + bytes /= divisor; + } + + if (scale & HN_GETSCALE) + return (i); + + if (bytes < 1000 && flags & HN_DECIMAL) { + if (len < (baselen + 2 + ((flags & HN_NOSPACE) || (i == 0 && + !(flags & HN_B)) ? 0 : 1))) + return (-1); + s1 = bytes / 100; + if ((s2 = (((bytes % 100) + 5) / 10)) == 10) { + s1++; + s2 = 0; + } + if (s1 < 10 && i == 0) + /* Don't ever use .0 for a number less than 10. */ + r = snprintf(buf, len, "%lld%s%c%s", + /* LONGLONG */ + (long long)(sign * s1), + (i == 0 && !(flags & HN_B)) || flags & HN_NOSPACE ? + "" : " ", (i == 0 && (flags & HN_B)) ? 'B' : + prefixes[i], suffix); + else + r = snprintf(buf, len, "%lld%s%lld%s%c%s", + /* LONGLONG */ + (long long)(sign * s1), + localeconv()->decimal_point, + /* LONGLONG */ + (long long)s2, + (i == 0 && !(flags & HN_B)) || flags & HN_NOSPACE ? + "" : " ", (i == 0 && (flags & HN_B)) ? 'B' : + prefixes[i], suffix); + + } else + r = snprintf(buf, len, "%lld%s%c%s", + /* LONGLONG */ + (long long)(sign * ((bytes + 50) / 100)), + i == 0 || flags & HN_NOSPACE ? "" : " ", (i == 0 && + (flags & HN_B)) ? 'B' : prefixes[i], suffix); + + return (r); +} diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index fbc68c07fb6..3042d0fddb3 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -69,6 +69,8 @@ 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); const char *uu_lockerr(int _uu_lockresult); int uu_lock(const char *_ttyname); int uu_unlock(const char *_ttyname); @@ -129,4 +131,13 @@ __END_DECLS #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_GETSCALE 0x10 +#define HN_AUTOSCALE 0x20 + #endif /* !_LIBUTIL_H_ */