summaryrefslogtreecommitdiff
path: root/src/df.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-11-30 10:25:02 +0000
committerJim Meyering <jim@meyering.net>1997-11-30 10:25:02 +0000
commit76916942cae4a1500ff00a0ff7fa80f0e12158fa (patch)
tree810ec98bad40eae32bcc0f02b20a1c3a33278382 /src/df.c
parent72bc3b818f6c7e9e190afee12c133275c88fe59f (diff)
downloadcoreutils-76916942cae4a1500ff00a0ff7fa80f0e12158fa.tar.xz
(<inttypes.h>): Include if HAVE_INTTYPES_H.
("human.h"): Include. (LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS): Remove. (human_readable_base): Renamed from human_blocks; value is now zero or positive integer, not just zero or nonzero. (output_units): New variable; replaces booleans kilobyte_blocks and megabyte_blocks. (long_options): Add --si or -H. (print_header): Adjust to renamed option variables. (human_readable_1k_blocks): Remove. (show_dev): Count blocks using uintmax_t, not long. Calculate percentages using double, not long; this still isn't perfect as it suffers double rounding, but it's more likely to round correctly in practice than using long did. Adjust to renamed option variables. Use new human_readable library function to format uintmax_t values. (usage): Add -H, --si. (main): Adjust to renamed option variables. Use -H if BLOCKSIZE is SI. Add -H.
Diffstat (limited to 'src/df.c')
-rw-r--r--src/df.c186
1 files changed, 67 insertions, 119 deletions
diff --git a/src/df.c b/src/df.c
index 2194998d5..66a82e2aa 100644
--- a/src/df.c
+++ b/src/df.c
@@ -16,9 +16,13 @@
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
- --human-readable and --megabyte options added by lm@sgi.com. */
+ --human-readable and --megabyte options added by lm@sgi.com.
+ --si and large file support added by eggert@twinsun.com. */
#include <config.h>
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
@@ -29,18 +33,13 @@
#include "system.h"
#include "save-cwd.h"
#include "error.h"
+#include "human.h"
char *dirname ();
void strip_trailing_slashes ();
char *xstrdup ();
char *xgetcwd ();
-/* The maximum length of a human-readable string. Be pessimistic
- and assume `int' is 64-bits wide. Converting 2^63 - 1 gives the
- 14-character string, 8796093022208G. The number being converted
- is the number of 1024-byte blocks, so we divide by 1024 * 1024. */
-#define LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS 14
-
/* Name this program was run with. */
char *program_name;
@@ -55,14 +54,11 @@ static int show_all_fs;
command line argument -- even if it's a dummy (automounter) entry. */
static int show_listed_fs;
-/* If nonzero, use variable sized printouts instead of 512-byte blocks. */
-static int human_blocks;
-
-/* If nonzero, use 1K blocks instead of 512-byte blocks. */
-static int kilobyte_blocks;
+/* base used for human style output */
+static int human_readable_base;
-/* If nonzero, use 1M blocks instead of 512-byte blocks. */
-static int megabyte_blocks;
+/* The units to count in. */
+static int output_units;
/* If nonzero, use the POSIX output format. */
static int posix_format;
@@ -119,6 +115,7 @@ static struct option const long_options[] =
{"all", no_argument, &show_all_fs, 1},
{"inodes", no_argument, &inode_format, 1},
{"human-readable", no_argument, 0, 'h'},
+ {"si", no_argument, 0, 'H'},
{"kilobytes", no_argument, 0, 'k'},
{"megabytes", no_argument, 0, 'm'},
{"portability", no_argument, &posix_format, 1},
@@ -145,66 +142,16 @@ print_header (void)
if (inode_format)
printf (" Inodes IUsed IFree %%IUsed");
else
- if (megabyte_blocks)
+ if (output_units == 1024 * 1024)
printf (" MB-blocks Used Available Capacity");
- else if (human_blocks)
+ else if (human_readable_base)
printf (" Size Used Avail Capacity");
else
printf (" %s Used Available Capacity",
- kilobyte_blocks ? "1024-blocks" : " 512-blocks");
+ output_units == 1024 ? "1024-blocks" : " 512-blocks");
printf (" Mounted on\n");
}
-/* Convert N_1K_BYTE_BLOCKS to a more readable string than %d would.
- Most people visually process strings of 3-4 digits effectively,
- but longer strings of digits are more prone to misinterpretation.
- Hence, converting to an abbreviated form usually improves readability.
- Use a suffix indicating multiples of 1024 (M) and 1024*1024 (G).
- For example, 8500 would be converted to 8.3M, 133456345 to 127G,
- and so on. Numbers smaller than 1024 get the `K' suffix. */
-
-static char *
-human_readable_1k_blocks (int n_1k_byte_blocks, char *buf, int buf_len)
-{
- const char *suffix;
- double amt;
- char *p;
-
- assert (buf_len > LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS);
-
- p = buf;
- amt = n_1k_byte_blocks;
-
- if (amt >= 1024 * 1024)
- {
- amt /= (1024 * 1024);
- suffix = "G";
- }
- else if (amt >= 1024)
- {
- amt /= 1024;
- suffix = "M";
- }
- else
- {
- suffix = "K";
- }
-
- if (amt >= 10)
- {
- sprintf (p, "%4.0f%s", amt, suffix);
- }
- else if (amt == 0)
- {
- strcpy (p, "0");
- }
- else
- {
- sprintf (p, "%4.1f%s", amt, suffix);
- }
- return (p);
-}
-
/* If FSTYPE is a type of filesystem that should be listed,
return nonzero, else zero. */
@@ -248,10 +195,10 @@ static void
show_dev (const char *disk, const char *mount_point, const char *fstype)
{
struct fs_usage fsu;
- long blocks_used;
- long blocks_percent_used;
- long inodes_used;
- long inodes_percent_used;
+ uintmax_t blocks_used;
+ double blocks_percent_used;
+ uintmax_t inodes_used;
+ double inodes_percent_used;
const char *stat_file;
if (!selected_fstype (fstype) || excluded_fstype (fstype))
@@ -270,19 +217,6 @@ show_dev (const char *disk, const char *mount_point, const char *fstype)
return;
}
- if (megabyte_blocks)
- {
- fsu.fsu_blocks /= 2*1024;
- fsu.fsu_bfree /= 2*1024;
- fsu.fsu_bavail /= 2*1024;
- }
- else if (kilobyte_blocks)
- {
- fsu.fsu_blocks /= 2;
- fsu.fsu_bfree /= 2;
- fsu.fsu_bavail /= 2;
- }
-
if (fsu.fsu_blocks == 0)
{
if (!show_all_fs && !show_listed_fs)
@@ -292,8 +226,8 @@ show_dev (const char *disk, const char *mount_point, const char *fstype)
else
{
blocks_used = fsu.fsu_blocks - fsu.fsu_bfree;
- blocks_percent_used = (long)
- (blocks_used * 100.0 / (blocks_used + fsu.fsu_bavail) + 0.5);
+ blocks_percent_used =
+ blocks_used * 100.0 / (blocks_used + fsu.fsu_bavail);
}
if (fsu.fsu_files == 0)
@@ -303,8 +237,7 @@ show_dev (const char *disk, const char *mount_point, const char *fstype)
else
{
inodes_used = fsu.fsu_files - fsu.fsu_ffree;
- inodes_percent_used = (long)
- (inodes_used * 100.0 / fsu.fsu_files + 0.5);
+ inodes_percent_used = inodes_used * 100.0 / fsu.fsu_files;
}
if (! disk)
@@ -320,23 +253,27 @@ show_dev (const char *disk, const char *mount_point, const char *fstype)
printf (" %-5s ", fstype);
if (inode_format)
- printf (" %7ld %7ld %7ld %5ld%%",
- fsu.fsu_files, inodes_used, fsu.fsu_ffree, inodes_percent_used);
- else if (human_blocks)
{
- char buf[3][LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS + 1];
- printf (" %4s %4s %5s %5ld%% ",
- human_readable_1k_blocks (fsu.fsu_blocks, buf[0],
- LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS + 1),
- human_readable_1k_blocks (blocks_used, buf[1],
- LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS + 1),
- human_readable_1k_blocks (fsu.fsu_bavail, buf[2],
- LONGEST_HUMAN_READABLE_1K_BYTE_BLOCKS + 1),
- blocks_percent_used);
+ char buf[3][LONGEST_HUMAN_READABLE + 1];
+ printf (" %7s %7s %7s %5.0f%%",
+ human_readable (fsu.fsu_files, buf[0], 1, 1, 0),
+ human_readable (inodes_used, buf[1], 1, 1, 0),
+ human_readable (fsu.fsu_ffree, buf[2], 1, 1, 0),
+ inodes_percent_used);
}
else
- printf (" %7ld %7ld %7ld %5ld%% ",
- fsu.fsu_blocks, blocks_used, fsu.fsu_bavail, blocks_percent_used);
+ {
+ int w = human_readable_base ? 5 : 7;
+ char buf[3][LONGEST_HUMAN_READABLE + 1];
+ printf (" %*s %*s %*s %5.0f%% ",
+ w, human_readable (fsu.fsu_blocks, buf[0], fsu.fsu_blocksize,
+ output_units, human_readable_base),
+ w, human_readable (blocks_used, buf[1], fsu.fsu_blocksize,
+ output_units, human_readable_base),
+ w, human_readable (fsu.fsu_bavail, buf[2], fsu.fsu_blocksize,
+ output_units, human_readable_base),
+ blocks_percent_used);
+ }
if (mount_point)
{
@@ -559,9 +496,10 @@ or all filesystems by default.\n\
\n\
-a, --all include filesystems having 0 blocks\n\
-h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
+ -H, --si likewise, but use powers of 1000 not 1024\n\
-i, --inodes list inode information instead of block usage\n\
- -k, --kilobytes use 1024-byte blocks, not 512 despite POSIXLY_CORRECT\n\
- -m, --megabytes use 1024K-byte blocks, not 512 despite POSIXLY_CORRECT\n\
+ -k, --kilobytes use 1024-byte blocks\n\
+ -m, --megabytes use 1048576-byte blocks\n\
--no-sync do not invoke sync before getting usage info (default)\n\
-P, --portability use the POSIX output format\n\
--sync invoke sync before getting usage info\n\
@@ -595,21 +533,30 @@ main (int argc, char **argv)
show_listed_fs = 0;
if (getenv ("POSIXLY_CORRECT"))
- kilobyte_blocks = 0;
+ output_units = 512;
else
{
char *bs;
- kilobyte_blocks = 1;
if ((bs = getenv ("BLOCKSIZE"))
&& strncmp (bs, "HUMAN", sizeof ("HUMAN") - 1) == 0)
- human_blocks = 1;
+ {
+ human_readable_base = 1024;
+ output_units = 1;
+ }
+ else if (bs && strcmp (bs, "SI") == 0)
+ {
+ human_readable_base = 1000;
+ output_units = 1;
+ }
+ else
+ output_units = 1024;
}
print_type = 0;
posix_format = 0;
exit_status = 0;
- while ((c = getopt_long (argc, argv, "aiF:hkmPTt:vx:", long_options, NULL))
+ while ((c = getopt_long (argc, argv, "aiF:hHkmPTt:vx:", long_options, NULL))
!= -1)
{
switch (c)
@@ -623,19 +570,20 @@ main (int argc, char **argv)
inode_format = 1;
break;
case 'h':
- human_blocks = 1;
- kilobyte_blocks = 1;
- megabyte_blocks = 0;
+ human_readable_base = 1024;
+ output_units = 1;
+ break;
+ case 'H':
+ human_readable_base = 1000;
+ output_units = 1;
break;
case 'k':
- human_blocks = 0;
- kilobyte_blocks = 1;
- megabyte_blocks = 0;
+ human_readable_base = 0;
+ output_units = 1024;
break;
case 'm':
- human_blocks = 0;
- kilobyte_blocks = 0;
- megabyte_blocks = 1;
+ human_readable_base = 0;
+ output_units = 1024 * 1024;
break;
case 'T':
print_type = 1;
@@ -676,11 +624,11 @@ main (int argc, char **argv)
if (show_help)
usage (0);
- if (posix_format && megabyte_blocks)
+ if (posix_format && output_units == 1024 * 1024)
error (1, 0, _("the option for counting 1MB blocks may not be used\n\
with the portable output format"));
- if (posix_format && human_blocks)
+ if (posix_format && human_readable_base)
error (1, 0,
_("the option for printing with adaptive units may not be used\n\
with the portable output format"));