Date: Tue, 30 Nov 1999 00:30:45 -0700 From: Warner Losh <imp@village.org> To: matt@csis.gvsu.edu, freebsd-hackers@FreeBSD.ORG Subject: Re: Human readable df Message-ID: <199911300730.AAA00409@harmony.village.org> In-Reply-To: Your message of "Mon, 29 Nov 1999 23:57:48 MST." <199911300657.XAA99880@harmony.village.org> References: <199911300657.XAA99880@harmony.village.org> <19991129230436.A6501@badmofo>
next in thread | previous in thread | raw e-mail | index | archive | help
Here's a slightly better patch. It tries harder to fill up the 5 digit field with as many sig figs as possible (always up to 3). It uses better constants for things than the magic numbers of the first patch. I've not tried to patch the man page yet. Also patched where the gross use of "BKMGTP"[unit], the disorder in the prototypes. I also fixed it so that disk larger then 1000Pbytes are displayed in petabytes rather than bytes like the old code. I think this looks a little better than the orignial patch singe it now gives the same resolution of data for each file system. I experimented with setting the throttle from 1000.00 the previous unit to 2000.00 the previous unit to give it a more multi-meter look and to give higher resolution around 1 which would give you a more linear amount of data (taken as the log of the rounding error), but that didn't look as good, so I left it on the cutting room floor. I also experimented with a format that looked like /dev/da0s1e 192.M 167.M 9.22M 95% /usr but that too didn't look good to my eye, even though it was more pedantically correct from a sigfig point of view (since 200M means there is one sig fig, while 200.M means two, at least in the sig fig system I learned in high school). Here's the output Filesystem Size Used Avail Capacity Mounted on /dev/da0s1a 62.0M 31.0M 26.1M 54% / /dev/da0s1e 192M 167M 9.22M 95% /usr /dev/da0s1d 61.4M 11.3M 45.2M 20% /var /dev/da0s1f 288M 247M 18.4M 93% /usr/local /dev/da0s1g 2.17G 1.88G 122M 94% /home procfs 4.00K 4.00K 0B 100% /proc /dev/sd1a 990M 376M 534M 41% /jaz /dev/da2s4c 1.94G 1.72G 68.0M 96% /hawk /dev/da3s4a 3.93G 1.95G 1.67G 54% /u Warner P.S. I thought of doing a -H as well that used real SI units rather than the traditional CS si-ish units, but thought better of it. I also didn't use the new ki, Mi, et al either since that would just make the display look wrong to my eye (I was also unsure of their exact spelling :-). Index: df.c =================================================================== RCS file: /home/imp/FreeBSD/CVS/src/bin/df/df.c,v retrieving revision 1.22 diff -u -r1.22 df.c --- df.c 1999/11/01 04:57:43 1.22 +++ df.c 1999/11/30 07:19:07 @@ -59,21 +59,28 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -int checkvfsname __P((const char *, char **)); -char **makevfslist __P((char *)); -long regetmntinfo __P((struct statfs **, long, char **)); +typedef enum { NONE = 0, KILO, MEGA, GIGA, TERA, PETA /* , EXA */ } unit_t; +const char *unit_string = "BKMGTP"; + int bread __P((off_t, void *, int)); +int checkvfsname __P((const char *, char **)); char *getmntpt __P((char *)); +char **makevfslist __P((char *)); +void prthuman __P((struct statfs *, long)); +void prthumanval __P((double)); void prtstat __P((struct statfs *, int)); +long regetmntinfo __P((struct statfs **, long, char **)); int ufs_df __P((char *, int)); +unit_t unit_adjust __P((double *)); void usage __P((void)); -int aflag = 0, iflag, nflag; +int aflag = 0, iflag, nflag, hflag; struct ufs_args mdev; int @@ -88,11 +95,14 @@ char *mntpt, *mntpath, **vfslist; vfslist = NULL; - while ((ch = getopt(argc, argv, "aiknt:")) != -1) + while ((ch = getopt(argc, argv, "ahiknt:")) != -1) switch (ch) { case 'a': aflag = 1; break; + case 'h': + hflag = 1; + break; case 'i': iflag = 1; break; @@ -272,20 +282,26 @@ if (maxwidth < 11) maxwidth = 11; if (++timesthrough == 1) { - header = getbsize(&headerlen, &blocksize); - (void)printf("%-*.*s %s Used Avail Capacity", + if(hflag) + header = " Size"; + else + header = getbsize(&headerlen, &blocksize); + (void)printf("%-*.*s %s Used Avail Capacity", maxwidth, maxwidth, "Filesystem", header); if (iflag) (void)printf(" iused ifree %%iused"); - (void)printf(" Mounted on\n"); + (void)printf(" Mounted on\n"); } (void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname); used = sfsp->f_blocks - sfsp->f_bfree; availblks = sfsp->f_bavail + used; - (void)printf(" %*ld %8ld %8ld", headerlen, - fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize), - fsbtoblk(used, sfsp->f_bsize, blocksize), - fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize)); + if(hflag) + prthuman(sfsp, used); + else + (void)printf(" %*ld %8ld %8ld", headerlen, + fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize), + fsbtoblk(used, sfsp->f_bsize, blocksize), + fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize)); (void)printf(" %5.0f%%", availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); if (iflag) { @@ -295,7 +311,74 @@ inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0); } else (void)printf(" "); - (void)printf(" %s\n", sfsp->f_mntonname); + (void)printf(" %s\n", sfsp->f_mntonname); +} + +/* + * "human-readable" output: use 3 digits max.--put unit suffixes at + * the end. Makes output compact and easy-to-read esp. on huge disks. + */ + +unit_t +unit_adjust(val) + double *val; +{ +#define K(a) ((a) * (1ULL<< 10)) +#define M(a) ((a) * (1ULL<< 20)) +#define G(a) ((a) * (1ULL<< 30)) +#define T(a) ((a) * (1ULL<< 40)) +#define P(a) ((a) * (1ULL<< 50)) + double abval; + unit_t unit; + + abval = fabs(*val); + if (abval < K(1)) + unit = NONE; + else if (abval < K(1000.0)) { + unit = KILO; + *val /= K(1); + } else if (abval < M(1000.0)) { + unit = MEGA; + *val /= M(1); + } else if (abval < G(1000.0)) { + unit = GIGA; + *val /= G(1.0); + } else if (abval < T(1000.0)) { + unit = TERA; + *val /= T(1.0); + } else { + unit = PETA; + *val /= P(1.0); + } + return (unit); +} + +void +prthumanval(bytes) + double bytes; +{ + unit_t unit; + + unit = unit_adjust(&bytes); + + if (bytes == 0) + (void)printf(" 0B"); + else if (bytes > 100) + (void)printf(" %5.0f%c", bytes, unit_string[unit]); + else if (bytes > 10) + (void)printf(" %5.1f%c", bytes, unit_string[unit]); + else + (void)printf(" %5.2f%c", bytes, unit_string[unit]); +} + +void +prthuman(sfsp, used) + struct statfs *sfsp; + long used; +{ + prthumanval((double)(sfsp->f_blocks) * (double)(sfsp->f_bsize)); + prthumanval((double)(used) * (double)(sfsp->f_bsize)); + prthumanval((double)(sfsp->f_bavail) * (double)(sfsp->f_bsize)); } /* To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199911300730.AAA00409>