* 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.

PR:		5388
Submitted by:	Niall Smart <rotel@indigo.ie>
This commit is contained in:
Jordan K. Hubbard 1997-12-29 20:56:21 +00:00
parent de92741516
commit 1aa8a0a95b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=32097
2 changed files with 145 additions and 124 deletions

View File

@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)du.1 8.2 (Berkeley) 4/1/94
.\" $Id: du.1,v 1.8 1997/02/22 19:54:52 peter Exp $
.\" $Id: du.1,v 1.9 1997/06/30 06:50:06 charnier Exp $
.\"
.Dd April 1, 1994
.Dt DU 1
@ -40,8 +40,9 @@
.Nd display disk usage statistics
.Sh SYNOPSIS
.Nm du
.Op Fl H | Fl L | Fl P
.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,37 +54,37 @@ and for each directory in the file hierarchy rooted in each directory
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.
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 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.
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 the file hierarchy.
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
Displays all directories only
Display an entry for all files and directories
.Ar depth
directories deep.
.It Fl c
Display a grand total.
.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.
Display block counts in 1024-byte (1-Kbyte) blocks.
.It Fl x
Filesystem mount points are not traversed.
.El
@ -101,13 +102,6 @@ or
.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
@ -120,8 +114,11 @@ If the environment variable
.Ev BLOCKSIZE
is set, and the
.Fl k
option is not specified, the block counts will be displayed in units of that
size block.
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 ,

View File

@ -44,6 +44,7 @@ static char copyright[] =
static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
@ -56,63 +57,75 @@ static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95";
#include <string.h>
#include <unistd.h>
int linkchk __P((FTSENT *));
static void usage __P((void));
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;
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;
Hflag = Lflag = Pflag = aflag = sflag = dflag = 0;
ftsoptions = 0;
depth = INT_MAX;
ftsoptions = FTS_PHYSICAL;
while ((ch = getopt(argc, argv, "HLPad:ksx")) != -1)
while ((ch = getopt(argc, argv, "HLPad:ksxc")) != -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);
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();
}
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
@ -128,27 +141,32 @@ main(argc, argv)
* 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_PHYSICAL;
if (Lflag)
ftsoptions |= FTS_LOGICAL;
}
if (Pflag)
ftsoptions |= FTS_PHYSICAL;
listall = 0;
if (aflag) {
if (sflag || dflag)
usage();
listdirs = listfiles = 1;
listall = 1;
} else if (sflag) {
if (dflag)
usage();
listdirs = listfiles = 0;
} else if (dflag) {
listfiles = 0;
listdirs = 1;
} else {
listfiles = 0;
listdirs = 1;
depth = 0;
}
if (!*argv) {
@ -157,61 +175,67 @@ main(argc, argv)
argv[1] = NULL;
}
(void)getbsize(&notused, &blocksize);
(void) getbsize(&notused, &blocksize);
blocksize /= 512;
rval = 0;
if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
err(1, NULL);
err(1, "fts_open");
for (rval = 0; (p = fts_read(fts)) != NULL;)
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 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))
case FTS_D: /* Ignore. */
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;
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)
FTSENT *p;