Bug 27240

Summary: df does not support -l option
Product: Base System Reporter: Jim.Pirzyk <Jim.Pirzyk>
Component: binAssignee: Jim Pirzyk <pirzyk>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.3-RELEASE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Jim.Pirzyk 2001-05-10 06:10:01 UTC
	df does not support -l as it does on Linux, Solaris, SunOS
	IRIX, AIX and UNICOS

How-To-Repeat: 	df -l
Comment 1 Garrett A. Wollman 2001-05-10 15:50:16 UTC
<<On Wed, 9 May 2001 22:06:47 -0700 (PDT), Jim.Pirzyk@disney.com said:

> + 		case 'l':
> + 			if (vfslist != NULL)
> + 				errx(1, "-l and -t are mutally exclusive.");
> + 			vfslist = makevfslist("nonfs");
> + 			break;

Actually, that's not the right way to implement this function.  The
correct way would be to scan the list of available filesystem types
and look for ones without the VFCF_NETWORK flag.

-GAWollman
Comment 2 Peter Pentchev 2001-05-10 16:38:48 UTC
On Thu, May 10, 2001 at 08:00:05AM -0700, Garrett Wollman wrote:
> The following reply was made to PR bin/27240; it has been noted by GNATS.
> 
> From: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
> To: Jim.Pirzyk@disney.com
> Cc: FreeBSD-gnats-submit@FreeBSD.ORG
> Subject: bin/27240: df does not support '-l' option
> Date: Thu, 10 May 2001 10:50:16 -0400 (EDT)
> 
>  <<On Wed, 9 May 2001 22:06:47 -0700 (PDT), Jim.Pirzyk@disney.com said:
>  
>  > + 		case 'l':
>  > + 			if (vfslist != NULL)
>  > + 				errx(1, "-l and -t are mutally exclusive.");
>  > + 			vfslist = makevfslist("nonfs");
>  > + 			break;
>  
>  Actually, that's not the right way to implement this function.  The
>  correct way would be to scan the list of available filesystem types
>  and look for ones without the VFCF_NETWORK flag.

OK, how about the following patch - it just gets all filesystems, and then
processes only those for which statfs(2) has set the MNT_LOCAL flag.

G'luck,
Peter

-- 
This sentence every third, but it still comprehensible.

Index: src/bin/df/df.1
===================================================================
RCS file: /home/ncvs/src/bin/df/df.1,v
retrieving revision 1.22
diff -u -r1.22 df.1
--- src/bin/df/df.1	2001/02/01 16:24:49	1.22
+++ src/bin/df/df.1	2001/05/10 15:37:55
@@ -44,7 +44,7 @@
 .Fl b | h | H | k |
 .Fl m | P
 .Oc
-.Op Fl ain
+.Op Fl ailn
 .Op Fl t Ar type
 .Op Ar file | filesystem ...
 .Sh DESCRIPTION
@@ -91,6 +91,8 @@
 this overrides the
 .Ev BLOCKSIZE
 specification from the environment.
+.It Fl l
+Only display information about locally-mounted filesystems.
 .It Fl m
 Use 1048576-byte (1-Mbyte) blocks rather than the default.  Note that
 this overrides the
@@ -106,7 +108,7 @@
 will not request new statistics from the filesystems, but will respond
 with the possibly stale statistics that were previously obtained.
 .It Fl P
-Use POSIX compliant output of 512-byte blocks rather than the default. 
+Use POSIX compliant output of 512-byte blocks rather than the default.
 Note that this overrides the
 .Ev BLOCKSIZE
 specification from the environment.
Index: src/bin/df/df.c
===================================================================
RCS file: /home/ncvs/src/bin/df/df.c,v
retrieving revision 1.26
diff -u -r1.26 df.c
--- src/bin/df/df.c	2001/05/09 08:44:15	1.26
+++ src/bin/df/df.c	2001/05/10 15:37:56
@@ -107,7 +107,7 @@
 unit_t	  unit_adjust __P((double *));
 void	  usage __P((void));
 
-int	aflag = 0, hflag, iflag, nflag;
+int	aflag, hflag, iflag, lflag, nflag;
 struct	ufs_args mdev;
 
 int
@@ -124,7 +124,7 @@
 	fstype = "ufs";
 
 	vfslist = NULL;
-	while ((ch = getopt(argc, argv, "abgHhikmnPt:")) != -1)
+	while ((ch = getopt(argc, argv, "abgHhiklmnPt:")) != -1)
 		switch (ch) {
 		case 'a':
 			aflag = 1;
@@ -154,6 +154,9 @@
 			putenv("BLOCKSIZE=1k");
 			hflag = 0;
 			break;
+		case 'l':
+			lflag = 1;
+			break;
 		case 'm':
 			putenv("BLOCKSIZE=1m");
 			hflag = 0;
@@ -188,12 +191,16 @@
 		if (vfslist != NULL) {
 			maxwidth = 0;
 			for (i = 0; i < mntsize; i++) {
+				if (lflag && !(mntbuf[i].f_flags & MNT_LOCAL))
+					continue;
 				width = strlen(mntbuf[i].f_mntfromname);
 				if (width > maxwidth)
 					maxwidth = width;
 			}
 		}
 		for (i = 0; i < mntsize; i++) {
+			if (lflag && !(mntbuf[i].f_flags & MNT_LOCAL))
+				continue;
 			if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
 				prtstat(&mntbuf[i], maxwidth);
 		}
@@ -203,7 +210,7 @@
 	for (; *argv; argv++) {
 		if (stat(*argv, &stbuf) < 0) {
 			err = errno;
-			if ((mntpt = getmntpt(*argv)) == 0) {
+			if ((mntpt = getmntpt(*argv)) == NULL) {
 				warn("%s", *argv);
 				rv = 1;
 				continue;
@@ -232,7 +239,9 @@
 					continue;
 				} else if (statfs(mntpt, &statfsbuf) == 0) {
 					statfsbuf.f_mntonname[0] = '\0';
-					prtstat(&statfsbuf, maxwidth);
+					if (!lflag ||
+					    (statfsbuf.f_flags & MNT_LOCAL))
+						prtstat(&statfsbuf, maxwidth);
 				} else {
 					warn("%s", *argv);
 					rv = 1;
@@ -255,7 +264,8 @@
 		}
 		if (argc == 1)
 			maxwidth = strlen(statfsbuf.f_mntfromname) + 1;
-		prtstat(&statfsbuf, maxwidth);
+		if (!lflag || (statfsbuf.f_flags & MNT_LOCAL))
+			prtstat(&statfsbuf, maxwidth);
 	}
 	return (rv);
 }
@@ -289,12 +299,15 @@
 	int i, j;
 	struct statfs *mntbuf;
 
-	if (vfslist == NULL)
+	if (!lflag && (vfslist == NULL))
 		return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT));
 
 	mntbuf = *mntbufp;
 	for (j = 0, i = 0; i < mntsize; i++) {
-		if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
+		if (lflag && !(mntbuf[i].f_flags & MNT_LOCAL))
+			continue;
+		if ((vfslist != NULL) &&
+		    checkvfsname(mntbuf[i].f_fstypename, vfslist))
 			continue;
 		if (!nflag)
 			(void)statfs(mntbuf[i].f_mntonname,&mntbuf[j]);
@@ -462,7 +475,7 @@
 	sfsp = &statfsbuf;
 	sfsp->f_type = 1;
 	strcpy(sfsp->f_fstypename, "ufs");
-	sfsp->f_flags = 0;
+	sfsp->f_flags = MNT_LOCAL;
 	sfsp->f_bsize = sblock.fs_fsize;
 	sfsp->f_iosize = sblock.fs_bsize;
 	sfsp->f_blocks = sblock.fs_dsize;
@@ -506,6 +519,6 @@
 {
 
 	(void)fprintf(stderr,
-	    "usage: df [-b | -H | -h | -k | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
+	    "usage: df [-b | -H | -h | -k | -l | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
 	exit(EX_USAGE);
 }
Comment 3 Jim.Pirzyk 2001-05-10 18:40:22 UTC
Ok, so I have a question.  How do I get vfsconf from the kernel?
I can get maxvfsconf from there via the sysctl CTL_VFS, VFS_GENERIC,
VFS_MAXTYPENUM.

- JimP

On Thursday 10 May 2001 07:50 am, Garrett Wollman wrote:
> <<On Wed, 9 May 2001 22:06:47 -0700 (PDT), Jim.Pirzyk@disney.com said:
> > + 		case 'l':
> > + 			if (vfslist != NULL)
> > + 				errx(1, "-l and -t are mutally exclusive.");
> > + 			vfslist = makevfslist("nonfs");
> > + 			break;
>
> Actually, that's not the right way to implement this function.  The
> correct way would be to scan the list of available filesystem types
> and look for ones without the VFCF_NETWORK flag.
>
> -GAWollman

-- 
--- @(#) $Id: dot.signature,v 1.9 2000/07/10 16:43:05 pirzyk Exp $
    __o   Jim.Pirzyk@disney.com -------------------------------------
 _'\<,_   Senior Systems Engineer, Walt Disney Feature Animation 
(*)/ (*)
Comment 4 Peter Pentchev 2001-05-10 19:38:15 UTC
On Thu, May 10, 2001 at 11:30:02AM -0700, Peter Pentchev wrote:
> The following reply was made to PR bin/27240; it has been noted by GNATS.
[snip]
>   
>   	(void)fprintf(stderr,
>  -	    "usage: df [-b | -H | -h | -k | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
>  +	    "usage: df [-b | -H | -h | -k | -l | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
>   	exit(EX_USAGE);
>   }

Er, oops :)

OK, so "-l" should be added to the second set of flags [-ailn], not
to the blocksize-specification ones.

G'luck,
Peter

-- 
No language can express every thought unambiguously, least of all this one.
Comment 5 Bruce Evans 2001-05-11 08:02:55 UTC
On Thu, 10 May 2001, Peter Pentchev wrote:

>  >   	(void)fprintf(stderr,
>  >  -	    "usage: df [-b | -H | -h | -k | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
>  >  +	    "usage: df [-b | -H | -h | -k | -l | -m | -P] [-ain] [-t type] [file | filesystem ...]\n");
>  >   	exit(EX_USAGE);
>  >   }
>  
>  Er, oops :)
>  
>  OK, so "-l" should be added to the second set of flags [-ailn], not
>  to the blocksize-specification ones.

Copying the output of `man df | col -b' should help avoid this bug and the
misformatting of the output into more than 80 columns.  (Previously, the
line was only too long in the source code.)

Bruce
Comment 6 Jim.Pirzyk 2001-05-11 16:18:39 UTC
So here is the complete patch using VFCF_NETWORK flag to generate the list
of networked filesystems.

On Thursday 10 May 2001 07:50 am, Garrett Wollman wrote:
> <<On Wed, 9 May 2001 22:06:47 -0700 (PDT), Jim.Pirzyk@disney.com said:
> > + 		case 'l':
> > + 			if (vfslist != NULL)
> > + 				errx(1, "-l and -t are mutally exclusive.");
> > + 			vfslist = makevfslist("nonfs");
> > + 			break;
>
> Actually, that's not the right way to implement this function.  The
> correct way would be to scan the list of available filesystem types
> and look for ones without the VFCF_NETWORK flag.
>
> -GAWollman

*** ./bin/df/df.1.orig	Mon Mar  5 01:55:59 2001
--- ./bin/df/df.1	Thu May 10 12:01:01 2001
***************
*** 44,50 ****
  .Fl b | h | H | k |
  .Fl m | P
  .Oc
! .Op Fl ain
  .Op Fl t Ar type
  .Op Ar file | filesystem ...
  .Sh DESCRIPTION
--- 44,50 ----
  .Fl b | h | H | k |
  .Fl m | P
  .Oc
! .Op Fl ailn
  .Op Fl t Ar type
  .Op Ar file | filesystem ...
  .Sh DESCRIPTION
***************
*** 91,96 ****
--- 91,98 ----
  this overrides the
  .Ev BLOCKSIZE
  specification from the environment.
+ .It Fl l
+ Only display information about locally-mounted filesystems.
  .It Fl m
  Use 1048576-byte (1-Mbyte) blocks rather than the default.  Note that
  this overrides the
***************
*** 106,112 ****
  will not request new statistics from the filesystems, but will respond
  with the possibly stale statistics that were previously obtained.
  .It Fl P
! Use POSIX compliant output of 512-byte blocks rather than the default. 
  Note that this overrides the
  .Ev BLOCKSIZE
  specification from the environment.
--- 108,114 ----
  will not request new statistics from the filesystems, but will respond
  with the possibly stale statistics that were previously obtained.
  .It Fl P
! Use POSIX compliant output of 512-byte blocks rather than the default.
  Note that this overrides the
  .Ev BLOCKSIZE
  specification from the environment.
*** ./bin/df/df.c.orig	Mon Jun 12 20:19:40 2000
--- ./bin/df/df.c	Fri May 11 08:15:02 2001
***************
*** 54,59 ****
--- 54,60 ----
  #include <sys/param.h>
  #include <sys/stat.h>
  #include <sys/mount.h>
+ #include <sys/sysctl.h>
  #include <ufs/ufs/ufsmount.h>
  
  #include <err.h>
***************
*** 96,101 ****
--- 97,103 ----
  int unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
  
  int	  checkvfsname __P((const char *, char **));
+ char	 *makenetvfslist __P((void));
  char	**makevfslist __P((char *));
  long	  regetmntinfo __P((struct statfs **, long, char **));
  int	  bread __P((off_t, void *, int));
***************
*** 122,128 ****
  	char *mntpt, *mntpath, **vfslist;
  
  	vfslist = NULL;
! 	while ((ch = getopt(argc, argv, "abgHhikmnPt:")) != -1)
  		switch (ch) {
  		case 'a':
  			aflag = 1;
--- 124,130 ----
  	char *mntpt, *mntpath, **vfslist;
  
  	vfslist = NULL;
! 	while ((ch = getopt(argc, argv, "abgHhiklmnPt:")) != -1)
  		switch (ch) {
  		case 'a':
  			aflag = 1;
***************
*** 152,157 ****
--- 154,164 ----
  			putenv("BLOCKSIZE=1k");
  			hflag = 0;
  			break;
+ 		case 'l':
+ 			if (vfslist != NULL)
+ 				errx(1, "-l and -t are mutually exclusive.");
+ 			vfslist = makevfslist(makenetvfslist());
+ 			break;
  		case 'm':
  			putenv("BLOCKSIZE=1m");
  			hflag = 0;
***************
*** 506,511 ****
  {
  
  	(void)fprintf(stderr,
! 	    "usage: df [-b | -H | -h | -k | -m | -P] [-ain] [-t type] [file | 
filesystem ...]\n");
  	exit(EX_USAGE);
  }
--- 513,564 ----
  {
  
  	(void)fprintf(stderr,
! 	    "usage: df [-b | -H | -h | -k | -m | -P] [-ailn] [-t type] [file | 
filesystem ...]\n");
  	exit(EX_USAGE);
+ }
+ 
+ char *makenetvfslist()
+ {
+ 	char *str, *strptr, **listptr;
+ 	int mib[3], maxvfsconf, miblen, cnt=0, i;
+ 	struct ovfsconf *ptr;
+ 
+ 	mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM;
+ 	miblen=sizeof(maxvfsconf);
+ 	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &maxvfsconf, &miblen, NULL, 
0)) {
+ 		warnx("sysctl failed");
+ 		return (NULL);
+ 	}
+ 
+ 	if ((listptr=malloc(sizeof(char*) * maxvfsconf)) == NULL) {
+ 		warnx("malloc failed");
+ 		return (NULL);
+ 	}
+ 
+ 	for (ptr=getvfsent();ptr;ptr=getvfsent())
+ 		if (ptr->vfc_flags & VFCF_NETWORK) {
+ 			listptr[cnt++] = strdup (ptr->vfc_name);
+ 			if (! listptr[cnt-1]) {
+ 				warnx("malloc failed");
+ 				return (NULL);
+ 			}
+ 		}
+ 
+ 	if ((str = malloc(sizeof(char)*(32*cnt+cnt+2))) == NULL) {
+ 		warnx("malloc failed");
+ 		free(listptr);
+ 		return (NULL);
+ 	}
+ 
+ 	*str = 'n'; *(str+1) = 'o';
+ 	for (i = 0,strptr=str+2; i < cnt; i++,strptr++) {
+ 		strncpy (strptr, listptr[i], 32);
+ 		strptr+=strlen(listptr[i]);
+ 		*strptr=',';
+ 		free(listptr[i]);
+ 	}
+ 	*(--strptr) = NULL;
+ 
+ 	free(listptr);
+ 	return (str);
  }

-- 
--- @(#) $Id: dot.signature,v 1.9 2000/07/10 16:43:05 pirzyk Exp $
    __o   Jim.Pirzyk@disney.com -------------------------------------
 _'\<,_   Senior Systems Engineer, Walt Disney Feature Animation 
(*)/ (*)
Comment 7 Peter Pentchev 2001-05-11 16:48:06 UTC
OK, so I did it again - replied to -bugs, not GNATS. 
Here, GNATS, have a copy.

G'luck,
Peter

-- 
because I didn't think of a good beginning of it.

On Fri, May 11, 2001 at 06:46:36PM +0300, Peter Pentchev wrote:
> On Fri, May 11, 2001 at 08:30:03AM -0700, Jim Pirzyk wrote:
> > The following reply was made to PR bin/27240; it has been noted by GNATS.
> > 
> > From: Jim Pirzyk <Jim.Pirzyk@disney.com>
> > To: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
> > Cc: FreeBSD-gnats-submit@FreeBSD.ORG
> > Subject: Re: bin/27240: df does not support '-l' option
> > Date: Fri, 11 May 2001 08:18:39 -0700
> > 
> >  So here is the complete patch using VFCF_NETWORK flag to generate the list
> >  of networked filesystems.
> 
> I still think the MNT_LOCAL way is cleaner - no mucking up with kernel
> internal defines (sysctl's do tend to change from time to time), but only
> using well-known and well-documented information exported by the statfs(2)
> interface.
Comment 8 Jim Pirzyk freebsd_committer freebsd_triage 2001-06-04 19:39:16 UTC
Responsible Changed
From-To: freebsd-bugs->pirzyk

Assigned the bug to myself to see that it gets commited 
(the fixes that is, not the bug or the committer :)
Comment 9 Jim Pirzyk freebsd_committer freebsd_triage 2001-06-05 00:07:51 UTC
State Changed
From-To: open->closed

Applied the VFCF_NETWORK version of the patches, will be MFC'ed in 
2 weeks.