From rotel@indigo.ie  Sun Dec 28 06:20:26 1997
Received: from ginseng.indigo.ie (ts01-05.waterford.indigo.ie [194.125.139.36])
          by hub.freebsd.org (8.8.7/8.8.7) with SMTP id GAA16025
          for <FreeBSD-gnats-submit@freebsd.org>; Sun, 28 Dec 1997 06:20:17 -0800 (PST)
          (envelope-from rotel@indigo.ie)
Received: (qmail 1953 invoked by uid 1000); 28 Dec 1997 14:24:36 -0000
Message-Id: <19971228142436.1952.qmail@ginseng.indigo.ie>
Date: 28 Dec 1997 14:24:36 -0000
From: rotel@indigo.ie
Reply-To: rotel@indigo.ie
To: FreeBSD-gnats-submit@freebsd.org
Subject: new -c option for du(1) + small fix
X-Send-Pr-Version: 3.2

>Number:         5388
>Category:       bin
>Synopsis:       new -c option for du(1) + small fix
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Dec 28 06:30:02 PST 1997
>Closed-Date:    Mon Dec 29 12:56:46 PST 1997
>Last-Modified:  Mon Dec 29 12:56:59 PST 1997
>Originator:     Niall Smart
>Release:        FreeBSD 2.2.5-STABLE i386
>Organization:
>Environment:
>Description:

Hi,

I have included patches for du(1), these patches:

 * add a -c option which displays the grand total of all files
   counted.
   
 * re-word parts of the man page which I felt were badly worded
   or ambiguous.
   
 * change the behaviour of argument processing so that when more
   than one of the -P, -H and -L options are specified it will
   print an error message, rather than choosing the last option
   specified, this behaviour is more logical and consistent with
   other utilities.
 
 * change the behaviour of argument processing so that negative
   arguments to the -d option are not allowed.


Regards,


Niall

>How-To-Repeat:
>Fix:

*** du.c~	Sun Dec 28 14:11:41 1997
--- du.c	Sun Dec 28 14:00:28 1997
***************
*** 44,49 ****
--- 44,50 ----
  static char sccsid[] = "@(#)du.c	8.5 (Berkeley) 5/4/95";
  #endif /* not lint */
  
+ 
  #include <sys/param.h>
  #include <sys/stat.h>
  
***************
*** 56,118 ****
  #include <string.h>
  #include <unistd.h>
  
! int	 linkchk __P((FTSENT *));
! static void	 usage __P((void));
  
  int
  main(argc, argv)
  	int argc;
  	char *argv[];
  {
! 	FTS *fts;
! 	FTSENT *p;
! 	long blocksize;
! 	int ftsoptions, listdirs, listfiles, depth;
! 	int Hflag, Lflag, Pflag, aflag, ch, notused, rval, sflag, dflag;
! 	char **save;
  
  	save = argv;
! 	Hflag = Lflag = Pflag = aflag = sflag = dflag = 0;
  	depth = INT_MAX;
! 	ftsoptions = FTS_PHYSICAL;
! 	while ((ch = getopt(argc, argv, "HLPad:ksx")) != -1)
  		switch (ch) {
! 		case 'H':
! 			Hflag = 1;
! 			Lflag = Pflag = 0;
! 			break;
! 		case 'L':
! 			Lflag = 1;
! 			Hflag = Pflag = 0;
! 			break;
! 		case 'P':
! 			Pflag = 1;
! 			Hflag = Lflag = 0;
! 			break;
! 		case 'a':
! 			aflag = 1;
! 			break;
! 		case 'k':
! 			putenv("BLOCKSIZE=1024");
! 			break;
! 		case 's':
! 			sflag = 1;
! 			break;
! 		case 'x':
! 			ftsoptions |= FTS_XDEV;
! 			break;
! 		case 'd':
! 			dflag = 1;
! 			depth=atoi(optarg);
! 			if(errno == ERANGE) {
! 				(void)fprintf(stderr, "Invalid argument to option d: %s", optarg);
  				usage();
- 			}
- 			break;
- 		case '?':
- 		default:
- 			usage();
  		}
  	argc -= optind;
  	argv += optind;
  
--- 57,131 ----
  #include <string.h>
  #include <unistd.h>
  
! int		linkchk __P((FTSENT *));
! static void	usage __P((void));
  
  int
  main(argc, argv)
  	int argc;
  	char *argv[];
  {
! 	FTS		*fts;
! 	FTSENT		*p;
! 	FTSENT		*savedp;
! 	long		blocksize;
! 	int		ftsoptions;
! 	int		listall;
! 	int		depth;
! 	int		Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, ch, notused, rval;
! 	char 		**save;
  
+ 	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = 0;
+ 	
  	save = argv;
! 	ftsoptions = 0;
  	depth = INT_MAX;
! 	
! 	while ((ch = getopt(argc, argv, "HLPad:ksxc")) != -1)
  		switch (ch) {
! 			case 'H':
! 				Hflag = 1;
! 				break;
! 			case 'L':
! 				if (Pflag)
! 					usage();
! 				Lflag = 1;
! 				break;
! 			case 'P':
! 				if (Lflag)
! 					usage();
! 				Pflag = 1;
! 				break;
! 			case 'a':
! 				aflag = 1;
! 				break;
! 			case 'k':
! 				putenv("BLOCKSIZE=1024");
! 				break;
! 			case 's':
! 				sflag = 1;
! 				break;
! 			case 'x':
! 				ftsoptions |= FTS_XDEV;
! 				break;
! 			case 'd':
! 				dflag = 1;
! 				errno = 0;
! 				depth = atoi(optarg);
! 				if (errno == ERANGE || depth < 0) {
! 					(void) fprintf(stderr, "Invalid argument to option d: %s", optarg);
! 					usage();
! 				}
! 				break;
! 			case 'c':
! 				cflag = 1;
! 				break;
! 			case '?':
! 			case 'h':
! 			default:
  				usage();
  		}
+ 
  	argc -= optind;
  	argv += optind;
  
***************
*** 128,154 ****
  	 * very nasty, very fast.  The bottom line is that it's documented in
  	 * the man page, so it's a feature.
  	 */
  	if (Hflag)
  		ftsoptions |= FTS_COMFOLLOW;
! 	if (Lflag) {
! 		ftsoptions &= ~FTS_PHYSICAL;
  		ftsoptions |= FTS_LOGICAL;
! 	}
  
  	if (aflag) {
  		if (sflag || dflag)
  			usage();
! 		listdirs = listfiles = 1;
  	} else if (sflag) {
  		if (dflag)
  			usage();
! 		listdirs = listfiles = 0;
! 	} else if (dflag) {
! 		listfiles = 0;
! 		listdirs = 1;
! 	} else {
! 		listfiles = 0;
! 		listdirs = 1;
  	}
  
  	if (!*argv) {
--- 141,172 ----
  	 * very nasty, very fast.  The bottom line is that it's documented in
  	 * the man page, so it's a feature.
  	 */
+ 
+ 	if (Hflag + Lflag + Pflag > 1)
+ 		usage();
+ 
+ 	if (Hflag + Lflag + Pflag == 0)
+ 		Pflag = 1;			/* -P (physical) is default */
+ 
  	if (Hflag)
  		ftsoptions |= FTS_COMFOLLOW;
! 
! 	if (Lflag)
  		ftsoptions |= FTS_LOGICAL;
! 
! 	if (Pflag)
! 		ftsoptions |= FTS_PHYSICAL;
! 
! 	listall = 0;
  
  	if (aflag) {
  		if (sflag || dflag)
  			usage();
! 		listall = 1;
  	} else if (sflag) {
  		if (dflag)
  			usage();
! 		depth = 0;
  	}
  
  	if (!*argv) {
***************
*** 157,216 ****
  		argv[1] = NULL;
  	}
  
! 	(void)getbsize(&notused, &blocksize);
  	blocksize /= 512;
  
  	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
! 		err(1, NULL);
  
! 	for (rval = 0; (p = fts_read(fts)) != NULL;)
  		switch (p->fts_info) {
! 		case FTS_D:			/* Ignore. */
! 			break;
! 		case FTS_DP:
! 			p->fts_parent->fts_number +=
! 			    p->fts_number += p->fts_statp->st_blocks;
! 			/*
! 			 * If listing each directory, or not listing files
! 			 * or directories and this is post-order of the
! 			 * root of a traversal, display the total.
! 			 */
! 			if ((p->fts_level <= depth && listdirs) || 
!                             (!listfiles && !p->fts_level))
! 				(void)printf("%ld\t%s\n",
! 				    howmany(p->fts_number, blocksize),
! 				    p->fts_path);
! 			break;
! 		case FTS_DC:			/* Ignore. */
! 			break;
! 		case FTS_DNR:			/* Warn, continue. */
! 		case FTS_ERR:
! 		case FTS_NS:
! 			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
! 			rval = 1;
! 			break;
! 		default:
! 			if (p->fts_statp->st_nlink > 1 && linkchk(p))
! 				break;
! 			/*
! 			 * If listing each file, or a non-directory file was
! 			 * the root of a traversal, display the total.
! 			 */
! 			if (listfiles || !p->fts_level)
! 				(void)printf("%qd\t%s\n",
! 				    howmany(p->fts_statp->st_blocks, blocksize),
! 				    p->fts_path);
! 			p->fts_parent->fts_number += p->fts_statp->st_blocks;
  		}
  	if (errno)
  		err(1, "fts_read");
  	exit(rval);
  }
  
  typedef struct _ID {
  	dev_t	dev;
  	ino_t	inode;
  } ID;
  
  int
  linkchk(p)
--- 175,240 ----
  		argv[1] = NULL;
  	}
  
! 	(void) getbsize(&notused, &blocksize);
  	blocksize /= 512;
  
+ 	rval = 0;
+ 	
  	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
! 		err(1, "fts_open");
  
! 	while ((p = fts_read(fts)) != NULL) {
! 		savedp = p;
  		switch (p->fts_info) {
! 			case FTS_D:			/* Ignore. */
! 				break;
! 			case FTS_DP:
! 				p->fts_parent->fts_number +=
! 				    p->fts_number += p->fts_statp->st_blocks;
! 				
! 				if (p->fts_level <= depth)
! 					(void) printf("%ld\t%s\n",
! 					    howmany(p->fts_number, blocksize),
! 					    p->fts_path);
! 				break;
! 			case FTS_DC:			/* Ignore. */
! 				break;
! 			case FTS_DNR:			/* Warn, continue. */
! 			case FTS_ERR:
! 			case FTS_NS:
! 				warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
! 				rval = 1;
! 				break;
! 			default:
! 				if (p->fts_statp->st_nlink > 1 && linkchk(p))
! 					break;
! 				
! 				if (listall || p->fts_level == 0)
! 					(void) printf("%qd\t%s\n",
! 					    howmany(p->fts_statp->st_blocks, blocksize),
! 					    p->fts_path);
! 
! 				p->fts_parent->fts_number += p->fts_statp->st_blocks;
  		}
+ 	}
+ 
  	if (errno)
  		err(1, "fts_read");
+ 
+ 	if (cflag) {
+ 		p = savedp->fts_parent;
+ 		(void) printf("%ld\ttotal\n", howmany(p->fts_number, blocksize));
+ 	}
+ 
  	exit(rval);
  }
  
+ 
  typedef struct _ID {
  	dev_t	dev;
  	ino_t	inode;
  } ID;
+ 
  
  int
  linkchk(p)
*** du.1~	Sun Dec 28 14:11:45 1997
--- du.1	Sun Dec 28 14:00:28 1997
***************
*** 40,47 ****
  .Nd display disk usage statistics
  .Sh SYNOPSIS
  .Nm du
! .Op Fl H | Fl L | Fl P
  .Op Fl a | s | d Ar depth
  .Op Fl k
  .Op Fl x
  .Op Ar file ...
--- 40,48 ----
  .Nd display disk usage statistics
  .Sh SYNOPSIS
  .Nm du
! .Op Fl P | Fl H | Fl L
  .Op Fl a | s | d Ar depth
+ .Op Fl c
  .Op Fl k
  .Op Fl x
  .Op Ar file ...
***************
*** 53,89 ****
  argument.
  If no file is specified, the block usage of the hierarchy rooted in
  the current directory is displayed.
- The number of blocks are in the same units as that returned by the
- .Xr stat 2
- system call, i.e. 512-byte blocks.
  If the
  .Fl k
! flag is specified, the number displayed is the number of 1024-byte
! blocks.
  Partial numbers of blocks are rounded up.
  .Pp
  The options are as follows:
  .Bl -tag -width Ds
  .It Fl H
! Symbolic links on the command line are followed.
! (Symbolic links encountered in the tree traversal are not followed.)
  .It Fl L
! All symbolic links are followed.
! .It Fl P
! No symbolic links are followed.
  .It Fl a
! Display an entry for each file in the file hierarchy.
  .It Fl d Ar depth
! Displays all directories only
  .Ar depth
  directories deep.
  .It Fl k
! Report in 1024-byte (1-Kbyte) blocks rather than the default.  Note that
! this overrides the
! .Ev BLOCKSIZE
! setting from the environment.
! .It Fl s
! Display only the grand total for the specified files.
  .It Fl x
  Filesystem mount points are not traversed.
  .El
--- 54,90 ----
  argument.
  If no file is specified, the block usage of the hierarchy rooted in
  the current directory is displayed.
  If the
  .Fl k
! flag is specified, the number of 1024-byte
! blocks used by the file is displayed, otherwise
! .Xr getbsize 3
! is used to determine the preferred block size.
  Partial numbers of blocks are rounded up.
  .Pp
  The options are as follows:
  .Bl -tag -width Ds
+ .It Fl P
+ No symbolic links are followed. (default)
  .It Fl H
! Symbolic links on the command line are followed, symbolic links in file
! hierarchies are not followed.
  .It Fl L
! Symbolic links on the command line and in file hierarchies are followed.
  .It Fl a
! Display an entry for each file in a file hierarchy.
! .It Fl s
! Display an entry for each specified file. (Equivalent to
! .Fl d
! 0 )
  .It Fl d Ar depth
! Display an entry for all files and directories
  .Ar depth
  directories deep.
+ .It Fl c
+ Display a grand total.
  .It Fl k
! Display block counts in 1024-byte (1-Kbyte) blocks.
  .It Fl x
  Filesystem mount points are not traversed.
  .El
***************
*** 101,113 ****
  .Fl L
  options are specified, storage used by any symbolic links which are
  followed is not counted or displayed.
- The
- .Fl H ,
- .Fl L
- and
- .Fl P
- options override each other and the command's actions are determined
- by the last one specified.
  .Pp
  Files having multiple hard links are counted (and displayed) a single
  time per
--- 102,107 ----
***************
*** 120,127 ****
  .Ev BLOCKSIZE
  is set, and the
  .Fl k
! option is not specified, the block counts will be displayed in units of that
! size block.
  .El
  .Sh SEE ALSO
  .Xr df 1 ,
--- 114,124 ----
  .Ev BLOCKSIZE
  is set, and the
  .Fl k
! option is not specified, the block counts will be displayed in 1024-byte blocks. If
! .Ev BLOCKSIZE
! is not set, and the
! .Fl k
! option is not specified, the block counts will be displayed in 512-byte blocks.
  .El
  .Sh SEE ALSO
  .Xr df 1 ,
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: jkh 
State-Changed-When: Mon Dec 29 12:56:46 PST 1997 
State-Changed-Why:  
Committed to -current, thanks! 
>Unformatted:
