1 /* human.c -- print human readable file size
2 Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Originally contributed by lm@sgi.com;
19 --si, output block size selection, and large file support
20 added by eggert@twinsun.com. */
26 #include <sys/types.h>
40 #ifndef HAVE_DECL_GETENV
46 # define _(Text) gettext (Text)
57 static const char suffixes[] =
70 /* Convert N to a human readable format in BUF.
72 N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must
75 If OUTPUT_BLOCK_SIZE is positive, use units of OUTPUT_BLOCK_SIZE in
76 the output number. OUTPUT_BLOCK_SIZE must be a multiple of
77 FROM_BLOCK_SIZE or vice versa.
79 If OUTPUT_BLOCK_SIZE is negative, use a format like "127k" if
80 possible, using powers of -OUTPUT_BLOCK_SIZE; otherwise, use
81 ordinary decimal format. Normally -OUTPUT_BLOCK_SIZE is either
82 1000 or 1024; it must be at least 2. Most people visually process
83 strings of 3-4 digits effectively, but longer strings of digits are
84 more prone to misinterpretation. Hence, converting to an
85 abbreviated form usually improves readability. Use a suffix
86 indicating which power is being used. For example, assuming
87 -OUTPUT_BLOCK_SIZE is 1024, 8500 would be converted to 8.3k,
88 133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
89 than -OUTPUT_BLOCK_SIZE aren't modified. */
92 human_readable (uintmax_t n, char *buf,
93 int from_block_size, int output_block_size)
102 /* 0 means adjusted N == AMT.TENTHS;
103 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
104 2 means adjusted N == AMT.TENTHS + 0.05;
105 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
108 if (output_block_size < 0)
110 base = -output_block_size;
116 to_block_size = output_block_size;
119 p = buf + LONGEST_HUMAN_READABLE;
123 /* Suppress `used before initialized' warning. */
127 /* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE units. */
129 if (to_block_size <= from_block_size)
131 int multiplier = from_block_size / to_block_size;
132 amt = n * multiplier;
133 tenths = rounding = 0;
135 if (amt / multiplier != n)
137 /* Overflow occurred during multiplication. We should use
138 multiple precision arithmetic here, but we'll be lazy and
139 resort to floating point. This can yield answers that
140 are slightly off. In practice it is quite rare to
141 overflow uintmax_t, so this is good enough for now. */
143 double damt = n * (double) multiplier;
146 sprintf (buf, "%.0f", damt);
157 while (e * base <= damt && power < sizeof suffixes - 1);
161 sprintf (buf, "%.1f%c", damt, suffixes[power]);
162 if (4 < strlen (buf))
163 sprintf (buf, "%.0f%c", damt, suffixes[power]);
171 int divisor = to_block_size / from_block_size;
172 int r10 = (n % divisor) * 10;
173 int r2 = (r10 % divisor) * 2;
175 tenths = r10 / divisor;
176 rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
180 /* Use power of BASE notation if adjusted AMT is large enough. */
182 if (base && base <= amt)
188 int r10 = (amt % base) * 10 + tenths;
189 int r2 = (r10 % base) * 2 + (rounding >> 1);
192 rounding = (r2 < base
194 : 2 + (base < r2 + rounding));
197 while (base <= amt && power < sizeof suffixes - 1);
199 *--p = suffixes[power];
203 tenths += 2 < rounding + (tenths & 1);
220 if (5 < tenths + (2 < rounding + (amt & 1)))
224 if (amt == base && power < sizeof suffixes - 1)
226 *p = suffixes[power + 1];
234 *--p = '0' + (int) (amt % 10);
235 while ((amt /= 10) != 0);
241 /* The default block size used for output. This number may change in
242 the future as disks get larger. */
243 #ifndef DEFAULT_BLOCK_SIZE
244 # define DEFAULT_BLOCK_SIZE 1024
247 static char const *const block_size_args[] = { "human-readable", "si", 0 };
248 static int const block_size_types[] = { -1024, -1000 };
251 humblock (char const *spec, int *block_size)
255 if (! spec && ! (spec = getenv ("BLOCK_SIZE")))
256 *block_size = getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE;
257 else if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_types)))
258 *block_size = block_size_types[i];
263 strtol_error e = xstrtoul (spec, &ptr, 0, &val, "eEgGkKmMpPtTyYzZ0");
267 return LONGINT_INVALID_SUFFIX_CHAR;
268 if ((int) val < 0 || val != (int) val)
269 return LONGINT_OVERFLOW;
270 *block_size = (int) val;
277 human_block_size (char const *spec, int report_errors, int *block_size)
279 strtol_error e = humblock (spec, block_size);
280 if (e != LONGINT_OK && report_errors)
281 STRTOL_FATAL_ERROR (spec, _("block size"), e);