Subject: bin/36541: cleaner df(1) output, and another output format option
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Greg A. Woods <woods@planix.com>
List: netbsd-bugs
Date: 06/23/2007 23:30:00
>Number:         36541
>Category:       bin
>Synopsis:       cleaner df(1) output, and another output format option
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jun 23 23:30:00 +0000 2007
>Originator:     Greg A. Woods
>Release:        netbsd-current 2007/06/22
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:
	
	
System: NetBSD
>Description:

	there's way too much space wasted in the current "df" output

	a "-g" option to mimic the SysVr4 and SunOS-5 options is also
	offered

	the "-P" output was also not standards-conforming

>How-To-Repeat:

>Fix:

cvs diff: Diffing bin/df
Index: bin/df/df.1
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/bin/df/df.1,v
retrieving revision 1.40
diff -u -r1.40 df.1
--- bin/df/df.1	28 Jan 2007 09:56:13 -0000	1.40
+++ bin/df/df.1	12 Feb 2007 20:28:38 -0000
@@ -37,7 +37,8 @@
 .Nd display free disk space
 .Sh SYNOPSIS
 .Nm
-.Op Fl aghiklmnP
+.Op Fl aGklmn
+.Op Fl g | Fl i | Fl P
 .Op Fl t Ar type
 .Op Ar file | Ar file_system ...
 .Sh DESCRIPTION
@@ -71,11 +72,27 @@
 including those that were mounted with the
 .Dv MNT_IGNORE
 flag.
-.It Fl g
+.It Fl G
 The
-.Fl g
+.Fl G
 option causes the numbers to be reported in gigabytes (1024*1024*1024
 bytes).
+.It Fl g
+Display all the fields of the structure(s) returned by
+.Xr statvfs 2 .
+This option cannot be used with the
+.Fl i
+or
+.Fl P
+options.
+This option will override the
+.Fl G ,
+.Fl h ,
+.Fl k ,
+and
+.Fl m
+options, as well as any setting of
+.Ev BLOCKSIZE .
 .It Fl h
 "Human-readable" output.
 Use unit suffixes: Byte, Kilobyte, Megabyte,
@@ -136,6 +153,11 @@
     \*[Lt]space used\*[Gt], \*[Lt]space free\*[Gt], \*[Lt]percentage used\*[Gt],
     \*[Lt]file system root\*[Gt]
 .Ed
+.Pp
+Note that the
+.Fl i
+option may not be specified with
+.Fl P .
 .It Fl t Ar type
 Is used to indicate the actions should only be taken on
 filesystems of the specified type.
@@ -155,7 +177,7 @@
 If the environment variable
 .Ev BLOCKSIZE
 is set, and the
-.Fl g ,
+.Fl G ,
 .Fl h ,
 .Fl k
 and
Index: bin/df/df.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/bin/df/df.c,v
retrieving revision 1.72
diff -u -r1.72 df.c
--- bin/df/df.c	4 Sep 2006 16:32:57 -0000	1.72
+++ bin/df/df.c	12 Feb 2007 20:14:37 -0000
@@ -77,7 +77,7 @@
 const char *
 	strpct64(uint64_t, uint64_t, u_int);
 
-int	aflag, hflag, iflag, lflag, nflag, Pflag;
+int	aflag, gflag, hflag, iflag, lflag, nflag, Pflag;
 long 	usize = 0;
 char	**typelist = NULL;
 
@@ -90,15 +90,18 @@
 	int ch, i, maxwidth, width;
 	char *mntpt;
 
-	while ((ch = getopt(argc, argv, "aghiklmnPt:")) != -1)
+	while ((ch = getopt(argc, argv, "aGghiklmnPt:")) != -1)
 		switch (ch) {
 		case 'a':
 			aflag = 1;
 			break;
-		case 'g':
+		case 'G':
 			hflag = 0;
 			usize = 1024 * 1024 * 1024;
 			break;
+		case 'g':
+			gflag = 1;
+			break;
 		case 'h':
 			hflag = 1;
 			usize = 0;
@@ -132,6 +135,12 @@
 		default:
 			usage();
 		}
+
+	if (gflag && (Pflag || iflag))
+		errx(1, "only one of -g and -P or -i may be specified");
+	if (Pflag && iflag)
+		errx(1, "only one of -P and -i may be specified");
+
 	argc -= optind;
 	argv += optind;
 
@@ -343,8 +352,55 @@
 	int64_t used, availblks, inodes;
 	int64_t bavail;
 
-	if (maxwidth < 11)
-		maxwidth = 11;
+	if (gflag) {
+		/*
+		 * From SunOS-5.6:
+		 *
+		 * /var               (/dev/dsk/c0t0d0s3 ):         8192 block size          1024 frag size  
+		 *   984242 total blocks     860692 free blocks   859708 available         249984 total files
+		 *   248691 free files      8388611 filesys id  
+		 *      ufs fstype       0x00000004 flag             255 filename length
+		 *
+		 */
+		(void) printf("%10s (%-12s): %7ld block size %12ld frag size\n",
+			      sfsp->f_mntonname,
+			      sfsp->f_mntfromname,
+			      sfsp->f_iosize,	/* On UFS/FFS systems this is
+						 * also called the "optimal
+						 * transfer block size" but it
+						 * is of course the file
+						 * system's block size too.
+						 */
+			      sfsp->f_bsize);	/* not so surprisingly the
+						 * "fundamental file system
+						 * block size" is the frag
+						 * size.
+						 */
+		(void) printf("%10" PRId64 " total blocks %10" PRId64 " free blocks  %10" PRId64 " available\n",
+			      (uint64_t) sfsp->f_blocks,
+			      (uint64_t) sfsp->f_bfree,
+			      (uint64_t) sfsp->f_bavail);
+		(void) printf("%10" PRId64 " total files  %10" PRId64 " free files %12lx filesys id\n",
+			      (uint64_t) sfsp->f_ffree,
+			      (uint64_t) sfsp->f_files,
+			      sfsp->f_fsid);
+		(void) printf("%10s fstype  %#15lx flag  %17ld filename length\n",
+			      sfsp->f_fstypename,
+			      sfsp->f_flag,
+			      sfsp->f_namemax);
+		(void) printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64 " asyncwrites\n\n",
+			      (unsigned long) sfsp->f_owner,
+			      sfsp->f_syncwrites,
+			      sfsp->f_asyncwrites);
+
+		/*
+		 * a consession by the structured programming police to the
+		 * indentation police....
+		 */
+		return;
+	}
+	if (maxwidth < 12)
+		maxwidth = 12;
 	if (++timesthrough == 1) {
 		switch (blocksize = usize) {
 		case 1024:
@@ -367,38 +423,67 @@
 				header = getbsize(&headerlen, &blocksize);
 			break;
 		}
-		(void)printf("%-*.*s %s      Used %9s Capacity",
-		    maxwidth, maxwidth, "Filesystem", header,
-		    Pflag ? "Available" : "Avail");
-		if (iflag)
-			(void)printf("  iused    ifree  %%iused");
-		(void)printf("  Mounted on\n");
+		if (Pflag) {
+			/* "Filesystem 1024-blocks Used Available Capacity Mounted on\n" */
+			/* "Filesystem 512-blocks Used Available Capacity Mounted on\n" */
+			(void) printf("Filesystem %s Used Available Capacity Mounted on\n", header);
+		} else {
+			(void) printf("%-*.*s %s       Used      Avail %%Cap",
+				      maxwidth - (headerlen - 9),
+				      maxwidth - (headerlen - 9),
+				      "Filesystem", header);
+			if (iflag)
+				(void) printf("    iUsed  iAvail %%iCap");
+			(void) printf(" Mounted on\n");
+		}
 	}
-	(void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
 	used = sfsp->f_blocks - sfsp->f_bfree;
 	bavail = sfsp->f_bfree - sfsp->f_bresvd;
 	availblks = bavail + used;
+	if (Pflag) {
+		/*
+		 * "%s %d %d %d %s %s\n", <file system name>, <total space>,                    
+		 * <space used>, <space free>, <percentage used>, <file system root>              
+		 */
+		(void) printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s %s\n",
+			      sfsp->f_mntfromname,
+			      fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
+			      fsbtoblk(used, sfsp->f_bsize, blocksize),
+			      fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize),
+			      availblks == 0 ? full : strpct64((uint64_t) used,
+							       (uint64_t) availblks, 0),
+			      sfsp->f_mntonname);
+		/*
+		 * another consession by the structured programming police to
+		 * the indentation police....
+		 *
+		 * Note iflag cannot be set when Pflag is set.
+		 */
+		return;
+	}
+
+	(void) printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
+
 	if (hflag)
 		prthuman(sfsp, used, bavail);
 	else
-		(void)printf(" %*" PRId64 " %9" PRId64 " %9" PRId64, headerlen,
+		(void) printf("%10" PRId64 " %10" PRId64 " %10" PRId64,
 		    fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
 		    fsbtoblk(used, sfsp->f_frsize, blocksize),
 		    fsbtoblk(bavail, sfsp->f_frsize, blocksize));
-	(void)printf("%7s",
+	(void)printf(" %4s",
 	    availblks == 0 ? full :
 	    /* We know that these values are never negative */
 	    strpct64((uint64_t)used, (uint64_t)availblks, 0));
 	if (iflag) {
 		inodes = sfsp->f_files;
 		used = inodes - sfsp->f_ffree;
-		(void)printf(" %8ld %8ld %6s ",
+		(void) printf(" %8ld %8ld %4s",
 		    (u_long)used, (u_long)sfsp->f_ffree,
 		    inodes == 0 ? (used == 0 ? empty : full) :
 		    strpct64((uint64_t)used, (uint64_t)inodes, 0));
-	} else
-		(void)printf("  ");
-	(void)printf("  %s\n", sfsp->f_mntonname);
+	}
+	(void)printf(" %s\n", sfsp->f_mntonname);
 }
 
 void
@@ -406,7 +491,7 @@
 {
 
 	(void)fprintf(stderr,
-	    "usage: %s [-aghiklmnP] [-t type] [file | file_system ...]\n",
+	    "usage: %s [-aGghklmn] [-i|-p] [-t type] [file | file_system ...]\n",
 	    getprogname());
 	exit(1);
 	/* NOTREACHED */

>Unformatted: