du(1): Add --si option to display in terms of powers of 1000

Reviewed by:	cem (earlier version), emaste
Approved by:	emaste (mentor)
Differential Revision:	https://reviews.freebsd.org/D11748
This commit is contained in:
Kyle Evans 2017-08-09 01:19:19 +00:00
parent 1070a9141c
commit 476c601b7a
3 changed files with 60 additions and 21 deletions

View File

@ -28,7 +28,7 @@
.\" @(#)du.1 8.2 (Berkeley) 4/1/94
.\" $FreeBSD$
.\"
.Dd November 4, 2012
.Dd August 8, 2017
.Dt DU 1
.Os
.Sh NAME
@ -63,9 +63,10 @@ Calculate block counts in
.Ar blocksize
byte blocks.
This is different from the
.Fl h, k, m
.Fl h, k, m,
.Fl Fl si
and
.Fl g
.Fl g
options or setting
.Ev BLOCKSIZE
and gives an estimate of how much space the examined file hierarchy would
@ -101,7 +102,7 @@ Display block counts in 1073741824-byte (1 GiB) blocks.
.Dq Human-readable
output.
Use unit suffixes: Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte and Petabyte.
Gigabyte, Terabyte and Petabyte based on powers of 1024.
.It Fl k
Display block counts in 1024-byte (1 kiB) blocks.
.It Fl l
@ -131,6 +132,11 @@ This option exists solely for conformance with
Display an entry for each specified file.
(Equivalent to
.Fl d Li 0 )
.It Fl Fl si
.Dq Human-readable
output.
Use unit suffixes: Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte and Petabyte based on powers of 1000.
.It Fl t Ar threshold
Display only entries for which size exceeds
.Ar threshold .
@ -166,9 +172,9 @@ options override each other and the command's actions are determined
by the last one specified.
.Pp
The
.Fl h, k
.Fl h, k, m
and
.Fl m
.Fl Fl si
options all override each other; the last one specified determines
the block counts used.
.Sh ENVIRONMENT
@ -177,17 +183,17 @@ the block counts used.
If the environment variable
.Ev BLOCKSIZE
is set, and the
.Fl h, k
.Fl h, k, m
or
.Fl m
.Fl Fl si
options are not specified, the block counts will be displayed in units of
that block size.
If
.Ev BLOCKSIZE
is not set, and the
.Fl h, k
.Fl h, k, m
or
.Fl m
.Fl Fl si
options are not specified, the block counts will be displayed in 512-byte
blocks.
.El

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fnmatch.h>
#include <fts.h>
#include <getopt.h>
#include <libutil.h>
#include <locale.h>
#include <stdint.h>
@ -60,6 +61,11 @@ __FBSDID("$FreeBSD$");
#include <sysexits.h>
#include <unistd.h>
#define SI_OPT (CHAR_MAX + 1)
#define UNITS_2 1
#define UNITS_SI 2
static SLIST_HEAD(ignhead, ignentry) ignores;
struct ignentry {
char *mask;
@ -75,10 +81,16 @@ static int ignorep(FTSENT *);
static void siginfo(int __unused);
static int nodumpflag = 0;
static int Aflag;
static int Aflag, hflag;
static long blocksize, cblocksize;
static volatile sig_atomic_t info;
static const struct option long_options[] =
{
{ "si", no_argument, NULL, SI_OPT },
{ NULL, no_argument, NULL, 0 },
};
int
main(int argc, char *argv[])
{
@ -89,14 +101,13 @@ main(int argc, char *argv[])
int ftsoptions;
int depth;
int Hflag, Lflag, aflag, sflag, dflag, cflag;
int hflag, lflag, ch, notused, rval;
int lflag, ch, notused, rval;
char **save;
static char dot[] = ".";
setlocale(LC_ALL, "");
Hflag = Lflag = aflag = sflag = dflag = cflag = hflag =
lflag = Aflag = 0;
Hflag = Lflag = aflag = sflag = dflag = cflag = lflag = Aflag = 0;
save = argv;
ftsoptions = FTS_PHYSICAL;
@ -108,7 +119,8 @@ main(int argc, char *argv[])
depth = INT_MAX;
SLIST_INIT(&ignores);
while ((ch = getopt(argc, argv, "AB:HI:LPasd:cghklmnrt:x")) != -1)
while ((ch = getopt_long(argc, argv, "+AB:HI:LPasd:cghklmnrt:x",
long_options, NULL)) != -1)
switch (ch) {
case 'A':
Aflag = 1;
@ -160,7 +172,7 @@ main(int argc, char *argv[])
blocksize = 1073741824;
break;
case 'h':
hflag = 1;
hflag = UNITS_2;
break;
case 'k':
hflag = 0;
@ -189,6 +201,9 @@ main(int argc, char *argv[])
case 'x':
ftsoptions |= FTS_XDEV;
break;
case SI_OPT:
hflag = UNITS_SI;
break;
case '?':
default:
usage();
@ -270,7 +285,7 @@ main(int argc, char *argv[])
if (p->fts_level <= depth && threshold <=
threshold_sign * howmany(p->fts_bignum *
cblocksize, blocksize)) {
if (hflag) {
if (hflag > 0) {
prthumanval(p->fts_bignum);
(void)printf("\t%s\n", p->fts_path);
} else {
@ -306,7 +321,7 @@ main(int argc, char *argv[])
howmany(p->fts_statp->st_blocks, cblocksize);
if (aflag || p->fts_level == 0) {
if (hflag) {
if (hflag > 0) {
prthumanval(curblocks);
(void)printf("\t%s\n", p->fts_path);
} else {
@ -326,7 +341,7 @@ main(int argc, char *argv[])
err(1, "fts_read");
if (cflag) {
if (hflag) {
if (hflag > 0) {
prthumanval(savednumber);
(void)printf("\ttotal\n");
} else {
@ -474,13 +489,16 @@ static void
prthumanval(int64_t bytes)
{
char buf[5];
int flags;
bytes *= cblocksize;
flags = HN_B | HN_NOSPACE | HN_DECIMAL;
if (!Aflag)
bytes *= DEV_BSIZE;
if (hflag == UNITS_SI)
flags |= HN_DIVISOR_1000;
humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE,
HN_B | HN_NOSPACE | HN_DECIMAL);
humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE, flags);
(void)printf("%4s", buf);
}

View File

@ -141,6 +141,20 @@ m_flag_body()
atf_check -o inline:'1\tA\n1\tB\n1024\tC\n' du -Am A B C
}
atf_test_case si_flag
si_flag_head()
{
atf_set "descr" "Verify --si output"
}
si_flag_body()
{
atf_check truncate -s 1500000 A
atf_check truncate -s 1572864 B
atf_check -o inline:'1.4M\tA\n1.5M\tB\n' du -Ah A B
atf_check -o inline:'1.5M\tA\n1.6M\tB\n' du -A --si A B
}
atf_init_test_cases()
{
atf_add_test_case A_flag
@ -150,4 +164,5 @@ atf_init_test_cases()
atf_add_test_case h_flag
atf_add_test_case k_flag
atf_add_test_case m_flag
atf_add_test_case si_flag
}