198038Sache/* human.c -- print human readable file size 298038Sache 3133543Stjr Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 4133543Stjr Free Software Foundation, Inc. 598038Sache 698038Sache This program is free software; you can redistribute it and/or modify 798038Sache it under the terms of the GNU General Public License as published by 898038Sache the Free Software Foundation; either version 2, or (at your option) 998038Sache any later version. 1098038Sache 1198038Sache This program is distributed in the hope that it will be useful, 1298038Sache but WITHOUT ANY WARRANTY; without even the implied warranty of 1398038Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1498038Sache GNU General Public License for more details. 1598038Sache 1698038Sache You should have received a copy of the GNU General Public License 1798038Sache along with this program; if not, write to the Free Software Foundation, 1898038Sache Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1998038Sache 20131447Stjr/* Written by Paul Eggert and Larry McVoy. */ 2198038Sache 2298038Sache#if HAVE_CONFIG_H 2398038Sache# include <config.h> 2498038Sache#endif 2598038Sache 26131447Stjr#include "human.h" 2798038Sache 28131447Stjr#ifndef SIZE_MAX 29131447Stjr# define SIZE_MAX ((size_t) -1) 3098038Sache#endif 31131447Stjr#ifndef UINTMAX_MAX 32131447Stjr# define UINTMAX_MAX ((uintmax_t) -1) 3398038Sache#endif 3498038Sache 35131447Stjr#if HAVE_LOCALE_H && HAVE_LOCALECONV 36131447Stjr# include <locale.h> 3798038Sache#endif 3898038Sache 39131447Stjr#include <stdio.h> 40131447Stjr#include <stdlib.h> 41131447Stjr#include <string.h> 4298038Sache 43131447Stjr#include "gettext.h" 44131447Stjr#define _(msgid) gettext (msgid) 4598038Sache 4698038Sache#include <argmatch.h> 4798038Sache#include <error.h> 4898038Sache#include <xstrtol.h> 4998038Sache 50131447Stjr/* The maximum length of a suffix like "KiB". */ 51131447Stjr#define HUMAN_READABLE_SUFFIX_LENGTH_MAX 3 5298038Sache 53131447Stjrstatic const char power_letter[] = 5498038Sache{ 5598038Sache 0, /* not used */ 5698038Sache 'K', /* kibi ('k' for kilo is a special case) */ 5798038Sache 'M', /* mega or mebi */ 5898038Sache 'G', /* giga or gibi */ 5998038Sache 'T', /* tera or tebi */ 6098038Sache 'P', /* peta or pebi */ 6198038Sache 'E', /* exa or exbi */ 6298038Sache 'Z', /* zetta or 2**70 */ 6398038Sache 'Y' /* yotta or 2**80 */ 6498038Sache}; 6598038Sache 6698038Sache 67131447Stjr/* If INEXACT_STYLE is not human_round_to_nearest, and if easily 68131447Stjr possible, adjust VALUE according to the style. */ 6998038Sache 70131447Stjrstatic long double 71131447Stjradjust_value (int inexact_style, long double value) 7298038Sache{ 73131447Stjr /* Do not use the floorl or ceill functions, as that would mean 74131447Stjr checking for their presence and possibly linking with the 75131447Stjr standard math library, which is a porting pain. So leave the 76131447Stjr value alone if it is too large to easily round. */ 77131447Stjr if (inexact_style != human_round_to_nearest && value < UINTMAX_MAX) 7898038Sache { 7998038Sache uintmax_t u = value; 8098038Sache value = u + (inexact_style == human_ceiling && u != value); 8198038Sache } 8298038Sache 8398038Sache return value; 8498038Sache} 8598038Sache 86131447Stjr/* Group the digits of NUMBER according to the grouping rules of the 87131447Stjr current locale. NUMBER contains NUMBERLEN digits. Modify the 88131447Stjr bytes pointed to by NUMBER in place, subtracting 1 from NUMBER for 89131447Stjr each byte inserted. Return the starting address of the modified 90131447Stjr number. 91131447Stjr 92131447Stjr To group the digits, use GROUPING and THOUSANDS_SEP as in `struct 93131447Stjr lconv' from <locale.h>. */ 94131447Stjr 95131447Stjrstatic char * 96131447Stjrgroup_number (char *number, size_t numberlen, 97131447Stjr char const *grouping, char const *thousands_sep) 9898038Sache{ 99131447Stjr register char *d; 100131447Stjr size_t grouplen = SIZE_MAX; 101131447Stjr size_t thousands_seplen = strlen (thousands_sep); 102131447Stjr size_t i = numberlen; 103131447Stjr 104131447Stjr /* The maximum possible value for NUMBERLEN is the number of digits 105131447Stjr in the square of the largest uintmax_t, so double the size of 106131447Stjr uintmax_t before converting to a bound. 302 / 1000 is ceil 107131447Stjr (log10 (2.0)). Add 1 for integer division truncation. */ 108131447Stjr char buf[2 * sizeof (uintmax_t) * CHAR_BIT * 302 / 1000 + 1]; 109131447Stjr 110131447Stjr memcpy (buf, number, numberlen); 111131447Stjr d = number + numberlen; 112131447Stjr 113131447Stjr for (;;) 114131447Stjr { 115131447Stjr unsigned char g = *grouping; 116131447Stjr 117131447Stjr if (g) 118131447Stjr { 119131447Stjr grouplen = g < CHAR_MAX ? g : i; 120131447Stjr grouping++; 121131447Stjr } 122131447Stjr 123131447Stjr if (i < grouplen) 124131447Stjr grouplen = i; 125131447Stjr 126131447Stjr d -= grouplen; 127131447Stjr i -= grouplen; 128131447Stjr memcpy (d, buf + i, grouplen); 129131447Stjr if (i == 0) 130131447Stjr return d; 131131447Stjr 132131447Stjr d -= thousands_seplen; 133131447Stjr memcpy (d, thousands_sep, thousands_seplen); 134131447Stjr } 13598038Sache} 13698038Sache 137131447Stjr/* Convert N to a human readable format in BUF, using the options OPTS. 13898038Sache 13998038Sache N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must 14098038Sache be nonnegative. 14198038Sache 142131447Stjr Use units of TO_BLOCK_SIZE in the output number. TO_BLOCK_SIZE 143131447Stjr must be positive. 14498038Sache 145131447Stjr Use (OPTS & (human_round_to_nearest | human_floor | human_ceiling)) 146131447Stjr to determine whether to take the ceiling or floor of any result 147131447Stjr that cannot be expressed exactly. 14898038Sache 149131447Stjr If (OPTS & human_group_digits), group the thousands digits 150131447Stjr according to the locale, e.g., `1,000,000' in an American English 151131447Stjr locale. 15298038Sache 153131447Stjr If (OPTS & human_autoscale), deduce the output block size 154131447Stjr automatically; TO_BLOCK_SIZE must be 1 but it has no effect on the 155131447Stjr output. Use powers of 1024 if (OPTS & human_base_1024), and powers 156131447Stjr of 1000 otherwise. For example, assuming powers of 1024, 8500 157131447Stjr would be converted to 8.3, 133456345 to 127, 56990456345 to 53, and 158131447Stjr so on. Numbers smaller than the power aren't modified. 159131447Stjr human_autoscale is normally used together with human_SI. 160131447Stjr 161131447Stjr If (OPTS & human_SI), append an SI prefix indicating which power is 162131447Stjr being used. If in addition (OPTS & human_B), append "B" (if base 163131447Stjr 1000) or "iB" (if base 1024) to the SI prefix. When ((OPTS & 164131447Stjr human_SI) && ! (OPTS & human_autoscale)), TO_BLOCK_SIZE must be a 165131447Stjr power of 1024 or of 1000, depending on (OPTS & 166131447Stjr human_base_1024). */ 167131447Stjr 16898038Sachechar * 169131447Stjrhuman_readable (uintmax_t n, char *buf, int opts, 170131447Stjr uintmax_t from_block_size, uintmax_t to_block_size) 17198038Sache{ 172131447Stjr int inexact_style = 173131447Stjr opts & (human_round_to_nearest | human_floor | human_ceiling); 174131447Stjr unsigned int base = opts & human_base_1024 ? 1024 : 1000; 17598038Sache uintmax_t amt; 176131447Stjr int tenths; 177131447Stjr int exponent = -1; 178131447Stjr int exponent_max = sizeof power_letter - 1; 17998038Sache char *p; 180131447Stjr char *psuffix; 181131447Stjr char const *integerlim; 18298038Sache 18398038Sache /* 0 means adjusted N == AMT.TENTHS; 18498038Sache 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05; 18598038Sache 2 means adjusted N == AMT.TENTHS + 0.05; 18698038Sache 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */ 187131447Stjr int rounding; 18898038Sache 189131447Stjr char const *decimal_point = "."; 190131447Stjr size_t decimal_pointlen = 1; 191131447Stjr char const *grouping = ""; 192131447Stjr char const *thousands_sep = ""; 193131447Stjr#if HAVE_LOCALE_H && HAVE_LOCALECONV 194131447Stjr struct lconv const *l = localeconv (); 195131447Stjr size_t pointlen = strlen (l->decimal_point); 196131447Stjr if (0 < pointlen && pointlen <= MB_LEN_MAX) 19798038Sache { 198131447Stjr decimal_point = l->decimal_point; 199131447Stjr decimal_pointlen = pointlen; 20098038Sache } 201131447Stjr grouping = l->grouping; 202131447Stjr if (strlen (l->thousands_sep) <= MB_LEN_MAX) 203131447Stjr thousands_sep = l->thousands_sep; 204131447Stjr#endif 205131447Stjr 206131447Stjr psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX; 207131447Stjr p = psuffix; 208131447Stjr 209131447Stjr /* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE 210131447Stjr units. If this can be done exactly with integer arithmetic, do 211131447Stjr not use floating point operations. */ 212131447Stjr if (to_block_size <= from_block_size) 21398038Sache { 214131447Stjr if (from_block_size % to_block_size == 0) 215131447Stjr { 216131447Stjr uintmax_t multiplier = from_block_size / to_block_size; 217131447Stjr amt = n * multiplier; 218131447Stjr if (amt / multiplier == n) 219131447Stjr { 220131447Stjr tenths = 0; 221131447Stjr rounding = 0; 222131447Stjr goto use_integer_arithmetic; 223131447Stjr } 224131447Stjr } 22598038Sache } 226131447Stjr else if (from_block_size != 0 && to_block_size % from_block_size == 0) 227131447Stjr { 228131447Stjr uintmax_t divisor = to_block_size / from_block_size; 229131447Stjr uintmax_t r10 = (n % divisor) * 10; 230131447Stjr uintmax_t r2 = (r10 % divisor) * 2; 231131447Stjr amt = n / divisor; 232131447Stjr tenths = r10 / divisor; 233131447Stjr rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2); 234131447Stjr goto use_integer_arithmetic; 235131447Stjr } 23698038Sache 237131447Stjr { 238131447Stjr /* Either the result cannot be computed easily using uintmax_t, 239131447Stjr or from_block_size is zero. Fall back on floating point. 240131447Stjr FIXME: This can yield answers that are slightly off. */ 24198038Sache 242131447Stjr long double dto_block_size = to_block_size; 243131447Stjr long double damt = n * (from_block_size / dto_block_size); 244131447Stjr size_t buflen; 245131447Stjr size_t nonintegerlen; 24698038Sache 247131447Stjr if (! (opts & human_autoscale)) 248131447Stjr { 249131447Stjr sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt)); 250131447Stjr buflen = strlen (buf); 251131447Stjr nonintegerlen = 0; 252131447Stjr } 253131447Stjr else 254131447Stjr { 255131447Stjr long double e = 1; 256131447Stjr exponent = 0; 25798038Sache 258131447Stjr do 259131447Stjr { 260131447Stjr e *= base; 261131447Stjr exponent++; 262131447Stjr } 263131447Stjr while (e * base <= damt && exponent < exponent_max); 264131447Stjr 265131447Stjr damt /= e; 266131447Stjr 267131447Stjr sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt)); 268131447Stjr buflen = strlen (buf); 269131447Stjr nonintegerlen = decimal_pointlen + 1; 270131447Stjr 271131447Stjr if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen 272131447Stjr || ((opts & human_suppress_point_zero) 273131447Stjr && buf[buflen - 1] == '0')) 274131447Stjr { 275131447Stjr sprintf (buf, "%.0Lf", 276131447Stjr adjust_value (inexact_style, damt * 10) / 10); 277131447Stjr buflen = strlen (buf); 278131447Stjr nonintegerlen = 0; 279131447Stjr } 280131447Stjr } 281131447Stjr 282131447Stjr p = psuffix - buflen; 283131447Stjr memmove (p, buf, buflen); 284131447Stjr integerlim = p + buflen - nonintegerlen; 285131447Stjr } 286131447Stjr goto do_grouping; 287131447Stjr 288131447Stjr use_integer_arithmetic: 28998038Sache { 290131447Stjr /* The computation can be done exactly, with integer arithmetic. 291131447Stjr 292131447Stjr Use power of BASE notation if requested and if adjusted AMT is 293131447Stjr large enough. */ 294131447Stjr 295131447Stjr if (opts & human_autoscale) 29698038Sache { 297131447Stjr exponent = 0; 29898038Sache 299131447Stjr if (base <= amt) 30098038Sache { 30198038Sache do 30298038Sache { 303133543Stjr unsigned int r10 = (amt % base) * 10 + tenths; 304133543Stjr unsigned int r2 = (r10 % base) * 2 + (rounding >> 1); 305131447Stjr amt /= base; 306131447Stjr tenths = r10 / base; 307131447Stjr rounding = (r2 < base 308131447Stjr ? (r2 + rounding) != 0 309131447Stjr : 2 + (base < r2 + rounding)); 310131447Stjr exponent++; 31198038Sache } 312131447Stjr while (base <= amt && exponent < exponent_max); 31398038Sache 314131447Stjr if (amt < 10) 315131447Stjr { 316131447Stjr if (inexact_style == human_round_to_nearest 317131447Stjr ? 2 < rounding + (tenths & 1) 318131447Stjr : inexact_style == human_ceiling && 0 < rounding) 319131447Stjr { 320131447Stjr tenths++; 321131447Stjr rounding = 0; 32298038Sache 323131447Stjr if (tenths == 10) 324131447Stjr { 325131447Stjr amt++; 326131447Stjr tenths = 0; 327131447Stjr } 328131447Stjr } 329131447Stjr 330131447Stjr if (amt < 10 331131447Stjr && (tenths || ! (opts & human_suppress_point_zero))) 332131447Stjr { 333131447Stjr *--p = '0' + tenths; 334131447Stjr p -= decimal_pointlen; 335131447Stjr memcpy (p, decimal_point, decimal_pointlen); 336131447Stjr tenths = rounding = 0; 337131447Stjr } 338131447Stjr } 33998038Sache } 340131447Stjr } 34198038Sache 342131447Stjr if (inexact_style == human_round_to_nearest 343131447Stjr ? 5 < tenths + (0 < rounding + (amt & 1)) 344131447Stjr : inexact_style == human_ceiling && 0 < tenths + rounding) 345131447Stjr { 346131447Stjr amt++; 347131447Stjr 348131447Stjr if ((opts & human_autoscale) 349131447Stjr && amt == base && exponent < exponent_max) 350131447Stjr { 351131447Stjr exponent++; 352131447Stjr if (! (opts & human_suppress_point_zero)) 353131447Stjr { 354131447Stjr *--p = '0'; 355131447Stjr p -= decimal_pointlen; 356131447Stjr memcpy (p, decimal_point, decimal_pointlen); 357131447Stjr } 358131447Stjr amt = 1; 359131447Stjr } 36098038Sache } 361131447Stjr 362131447Stjr integerlim = p; 363131447Stjr 364131447Stjr do 365131447Stjr { 366131447Stjr int digit = amt % 10; 367131447Stjr *--p = digit + '0'; 368131447Stjr } 369131447Stjr while ((amt /= 10) != 0); 37098038Sache } 37198038Sache 372131447Stjr do_grouping: 373131447Stjr if (opts & human_group_digits) 374131447Stjr p = group_number (p, integerlim - p, grouping, thousands_sep); 37598038Sache 376131447Stjr if (opts & human_SI) 37798038Sache { 378131447Stjr if (exponent < 0) 37998038Sache { 380131447Stjr uintmax_t power; 381131447Stjr exponent = 0; 382131447Stjr for (power = 1; power < to_block_size; power *= base) 383131447Stjr if (++exponent == exponent_max) 384131447Stjr break; 38598038Sache } 38698038Sache 387131447Stjr if (exponent) 388131447Stjr *psuffix++ = (! (opts & human_base_1024) && exponent == 1 389131447Stjr ? 'k' 390131447Stjr : power_letter[exponent]); 39198038Sache 392131447Stjr if (opts & human_B) 39398038Sache { 394131447Stjr if ((opts & human_base_1024) && exponent) 395131447Stjr *psuffix++ = 'i'; 396131447Stjr *psuffix++ = 'B'; 39798038Sache } 39898038Sache } 39998038Sache 400131447Stjr *psuffix = '\0'; 40198038Sache 40298038Sache return p; 40398038Sache} 40498038Sache 40598038Sache 40698038Sache/* The default block size used for output. This number may change in 40798038Sache the future as disks get larger. */ 40898038Sache#ifndef DEFAULT_BLOCK_SIZE 40998038Sache# define DEFAULT_BLOCK_SIZE 1024 41098038Sache#endif 41198038Sache 41298038Sachestatic char const *const block_size_args[] = { "human-readable", "si", 0 }; 413131447Stjrstatic int const block_size_opts[] = 414131447Stjr { 415131447Stjr human_autoscale + human_SI + human_base_1024, 416131447Stjr human_autoscale + human_SI 417131447Stjr }; 41898038Sache 419131447Stjrstatic uintmax_t 42098038Sachedefault_block_size (void) 42198038Sache{ 42298038Sache return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE; 42398038Sache} 42498038Sache 42598038Sachestatic strtol_error 426131447Stjrhumblock (char const *spec, uintmax_t *block_size, int *options) 42798038Sache{ 42898038Sache int i; 429131447Stjr int opts = 0; 43098038Sache 431133543Stjr if (! spec 432133543Stjr && ! (spec = getenv ("BLOCK_SIZE")) 433133543Stjr && ! (spec = getenv ("BLOCKSIZE"))) 43498038Sache *block_size = default_block_size (); 43598038Sache else 43698038Sache { 437131447Stjr if (*spec == '\'') 438131447Stjr { 439131447Stjr opts |= human_group_digits; 440131447Stjr spec++; 441131447Stjr } 442131447Stjr 443131447Stjr if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_opts))) 444131447Stjr { 445131447Stjr opts |= block_size_opts[i]; 446131447Stjr *block_size = 1; 447131447Stjr } 448131447Stjr else 449131447Stjr { 450131447Stjr char *ptr; 451131447Stjr strtol_error e = xstrtoumax (spec, &ptr, 0, block_size, 452131447Stjr "eEgGkKmMpPtTyYzZ0"); 453131447Stjr if (e != LONGINT_OK) 454131447Stjr return e; 455131447Stjr for (; ! ('0' <= *spec && *spec <= '9'); spec++) 456131447Stjr if (spec == ptr) 457131447Stjr { 458131447Stjr opts |= human_SI; 459131447Stjr if (ptr[-1] == 'B') 460131447Stjr opts |= human_B; 461131447Stjr if (ptr[-1] != 'B' || ptr[-2] == 'i') 462131447Stjr opts |= human_base_1024; 463131447Stjr break; 464131447Stjr } 465131447Stjr } 46698038Sache } 46798038Sache 468131447Stjr *options = opts; 46998038Sache return LONGINT_OK; 47098038Sache} 47198038Sache 472131447Stjrint 473131447Stjrhuman_options (char const *spec, bool report_errors, uintmax_t *block_size) 47498038Sache{ 475131447Stjr int opts; 476131447Stjr strtol_error e = humblock (spec, block_size, &opts); 47798038Sache if (*block_size == 0) 47898038Sache { 47998038Sache *block_size = default_block_size (); 48098038Sache e = LONGINT_INVALID; 48198038Sache } 48298038Sache if (e != LONGINT_OK && report_errors) 48398038Sache STRTOL_FATAL_ERROR (spec, _("block size"), e); 484131447Stjr return opts; 48598038Sache} 486