Make the columns in the output of df(1) line up, even for very large
filesystems. We now keep track of the maximum width required for every variable-width field instead of just the first one. PR: bin/15510 MFC after: 1 week
This commit is contained in:
parent
0754580f02
commit
62edbd31c7
145
bin/df/df.c
145
bin/df/df.c
@ -91,6 +91,16 @@ static const char rcsid[] =
|
||||
#define TERA_SI_SZ (TERA_SZ(1000ULL))
|
||||
#define PETA_SI_SZ (PETA_SZ(1000ULL))
|
||||
|
||||
/* Maximum widths of various fields. */
|
||||
struct maxwidths {
|
||||
int mntfrom;
|
||||
int total;
|
||||
int used;
|
||||
int avail;
|
||||
int iused;
|
||||
int ifree;
|
||||
};
|
||||
|
||||
unsigned long long vals_si [] = {1, KILO_SI_SZ, MEGA_SI_SZ, GIGA_SI_SZ, TERA_SI_SZ, PETA_SI_SZ};
|
||||
unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
|
||||
unsigned long long *valp;
|
||||
@ -102,28 +112,36 @@ unit_t unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
|
||||
int bread(off_t, void *, int);
|
||||
int checkvfsname(const char *, char **);
|
||||
char *getmntpt(char *);
|
||||
int longwidth(long);
|
||||
char *makenetvfslist(void);
|
||||
char **makevfslist(char *);
|
||||
void prthuman(struct statfs *, long);
|
||||
void prthumanval(double);
|
||||
void prtstat(struct statfs *, int);
|
||||
void prtstat(struct statfs *, struct maxwidths *);
|
||||
long regetmntinfo(struct statfs **, long, char **);
|
||||
int ufs_df(char *, int);
|
||||
int ufs_df(char *, struct maxwidths *);
|
||||
unit_t unit_adjust(double *);
|
||||
void update_maxwidths(struct maxwidths *, struct statfs *);
|
||||
void usage(void);
|
||||
|
||||
int aflag = 0, hflag, iflag, nflag;
|
||||
struct ufs_args mdev;
|
||||
|
||||
static __inline int imax(int a, int b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat stbuf;
|
||||
struct statfs statfsbuf, *mntbuf;
|
||||
struct maxwidths maxwidths;
|
||||
const char *fstype;
|
||||
char *mntpath, *mntpt, **vfslist;
|
||||
long mntsize;
|
||||
int ch, i, maxwidth, rv, width;
|
||||
int ch, i, rv;
|
||||
|
||||
fstype = "ufs";
|
||||
|
||||
@ -184,27 +202,21 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
|
||||
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
|
||||
maxwidth = 0;
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
width = strlen(mntbuf[i].f_mntfromname);
|
||||
if (width > maxwidth)
|
||||
maxwidth = width;
|
||||
}
|
||||
bzero(&maxwidths, sizeof(maxwidths));
|
||||
for (i = 0; i < mntsize; i++)
|
||||
update_maxwidths(&maxwidths, &mntbuf[i]);
|
||||
|
||||
rv = 0;
|
||||
if (!*argv) {
|
||||
mntsize = regetmntinfo(&mntbuf, mntsize, vfslist);
|
||||
if (vfslist != NULL) {
|
||||
maxwidth = 0;
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
width = strlen(mntbuf[i].f_mntfromname);
|
||||
if (width > maxwidth)
|
||||
maxwidth = width;
|
||||
}
|
||||
bzero(&maxwidths, sizeof(maxwidths));
|
||||
for (i = 0; i < mntsize; i++)
|
||||
update_maxwidths(&maxwidths, &mntbuf[i]);
|
||||
}
|
||||
for (i = 0; i < mntsize; i++) {
|
||||
if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
|
||||
prtstat(&mntbuf[i], maxwidth);
|
||||
prtstat(&mntbuf[i], &maxwidths);
|
||||
}
|
||||
exit(rv);
|
||||
}
|
||||
@ -234,13 +246,13 @@ main(int argc, char *argv[])
|
||||
}
|
||||
if (mount(fstype, mntpt, MNT_RDONLY,
|
||||
&mdev) != 0) {
|
||||
rv = ufs_df(*argv, maxwidth) || rv;
|
||||
rv = ufs_df(*argv, &maxwidths) || rv;
|
||||
(void)rmdir(mntpt);
|
||||
free(mntpath);
|
||||
continue;
|
||||
} else if (statfs(mntpt, &statfsbuf) == 0) {
|
||||
statfsbuf.f_mntonname[0] = '\0';
|
||||
prtstat(&statfsbuf, maxwidth);
|
||||
prtstat(&statfsbuf, &maxwidths);
|
||||
} else {
|
||||
warn("%s", *argv);
|
||||
rv = 1;
|
||||
@ -261,9 +273,11 @@ main(int argc, char *argv[])
|
||||
rv = 1;
|
||||
continue;
|
||||
}
|
||||
if (argc == 1)
|
||||
maxwidth = strlen(statfsbuf.f_mntfromname) + 1;
|
||||
prtstat(&statfsbuf, maxwidth);
|
||||
if (argc == 1) {
|
||||
bzero(&maxwidths, sizeof(maxwidths));
|
||||
update_maxwidths(&maxwidths, &statfsbuf);
|
||||
}
|
||||
prtstat(&statfsbuf, &maxwidths);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
@ -372,53 +386,106 @@ prthumanval(double bytes)
|
||||
* Print out status about a filesystem.
|
||||
*/
|
||||
void
|
||||
prtstat(struct statfs *sfsp, int maxwidth)
|
||||
prtstat(struct statfs *sfsp, struct maxwidths *mwp)
|
||||
{
|
||||
static long blocksize;
|
||||
static int headerlen, timesthrough;
|
||||
static const char *header;
|
||||
long used, availblks, inodes;
|
||||
|
||||
if (maxwidth < 11)
|
||||
maxwidth = 11;
|
||||
if (++timesthrough == 1) {
|
||||
mwp->mntfrom = imax(mwp->mntfrom, strlen("Filesystem"));
|
||||
if (hflag) {
|
||||
header = " Size";
|
||||
headerlen = strlen(header);
|
||||
(void)printf("%-*.*s %-s Used Avail Capacity",
|
||||
maxwidth, maxwidth, "Filesystem", header);
|
||||
mwp->total = mwp->used = mwp->avail = strlen(header);
|
||||
} else {
|
||||
header = getbsize(&headerlen, &blocksize);
|
||||
(void)printf("%-*.*s %-s Used Avail Capacity",
|
||||
maxwidth, maxwidth, "Filesystem", header);
|
||||
mwp->total = imax(mwp->total, headerlen);
|
||||
}
|
||||
mwp->used = imax(mwp->used, strlen("Used"));
|
||||
mwp->avail = imax(mwp->avail, strlen("Avail"));
|
||||
|
||||
(void)printf("%-*s %-*s %*s %*s Capacity", mwp->mntfrom,
|
||||
"Filesystem", mwp->total, header, mwp->used, "Used",
|
||||
mwp->avail, "Avail");
|
||||
if (iflag) {
|
||||
mwp->iused = imax(mwp->iused, strlen(" iused"));
|
||||
mwp->ifree = imax(mwp->ifree, strlen("ifree"));
|
||||
(void)printf(" %*s %*s %%iused", mwp->iused - 2,
|
||||
"iused", mwp->ifree, "ifree");
|
||||
}
|
||||
if (iflag)
|
||||
(void)printf(" iused ifree %%iused");
|
||||
(void)printf(" Mounted on\n");
|
||||
}
|
||||
(void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
|
||||
(void)printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname);
|
||||
used = sfsp->f_blocks - sfsp->f_bfree;
|
||||
availblks = sfsp->f_bavail + used;
|
||||
if (hflag) {
|
||||
prthuman(sfsp, used);
|
||||
} else {
|
||||
(void)printf(" %*ld %8ld %8ld", headerlen,
|
||||
(void)printf(" %*ld %*ld %*ld", mwp->total,
|
||||
fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
|
||||
fsbtoblk(used, sfsp->f_bsize, blocksize),
|
||||
fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize));
|
||||
mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize),
|
||||
mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize,
|
||||
blocksize));
|
||||
}
|
||||
(void)printf(" %5.0f%%",
|
||||
availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
|
||||
if (iflag) {
|
||||
inodes = sfsp->f_files;
|
||||
used = inodes - sfsp->f_ffree;
|
||||
(void)printf(" %7ld %7ld %5.0f%% ", used, sfsp->f_ffree,
|
||||
inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
|
||||
(void)printf(" %*ld %*ld %4.0f%% ", mwp->iused, used,
|
||||
mwp->ifree, sfsp->f_ffree, inodes == 0 ? 100.0 :
|
||||
(double)used / (double)inodes * 100.0);
|
||||
} else
|
||||
(void)printf(" ");
|
||||
(void)printf(" %s\n", sfsp->f_mntonname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the maximum field-width information in `mwp' based on
|
||||
* the filesystem specified by `sfsp'.
|
||||
*/
|
||||
void
|
||||
update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp)
|
||||
{
|
||||
static long blocksize;
|
||||
int dummy;
|
||||
|
||||
if (blocksize == 0)
|
||||
getbsize(&dummy, &blocksize);
|
||||
|
||||
mwp->mntfrom = imax(mwp->mntfrom, strlen(sfsp->f_mntfromname));
|
||||
mwp->total = imax(mwp->total, longwidth(fsbtoblk(sfsp->f_blocks,
|
||||
sfsp->f_bsize, blocksize)));
|
||||
mwp->used = imax(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
|
||||
sfsp->f_bfree, sfsp->f_bsize, blocksize)));
|
||||
mwp->avail = imax(mwp->avail, longwidth(fsbtoblk(sfsp->f_bavail,
|
||||
sfsp->f_bsize, blocksize)));
|
||||
mwp->iused = imax(mwp->iused, longwidth(sfsp->f_files -
|
||||
sfsp->f_ffree));
|
||||
mwp->ifree = imax(mwp->ifree, longwidth(sfsp->f_ffree));
|
||||
}
|
||||
|
||||
/* Return the width in characters of the specified long. */
|
||||
int
|
||||
longwidth(long val)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
/* Negative or zero values require one extra digit. */
|
||||
if (val <= 0) {
|
||||
val = -val;
|
||||
len++;
|
||||
}
|
||||
while (val > 0) {
|
||||
len++;
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
/*
|
||||
* This code constitutes the pre-system call Berkeley df code for extracting
|
||||
* information from filesystem superblocks.
|
||||
@ -433,7 +500,7 @@ union {
|
||||
int rfd;
|
||||
|
||||
int
|
||||
ufs_df(char *file, int maxwidth)
|
||||
ufs_df(char *file, struct maxwidths *mwp)
|
||||
{
|
||||
struct statfs statfsbuf;
|
||||
struct statfs *sfsp;
|
||||
@ -469,7 +536,7 @@ ufs_df(char *file, int maxwidth)
|
||||
mntpt = "";
|
||||
memmove(&sfsp->f_mntonname[0], mntpt, (size_t)MNAMELEN);
|
||||
memmove(&sfsp->f_mntfromname[0], file, (size_t)MNAMELEN);
|
||||
prtstat(sfsp, maxwidth);
|
||||
prtstat(sfsp, mwp);
|
||||
(void)close(rfd);
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user