From 1aa8a0a95b42cf07baa881dbf022cc6a96444186 Mon Sep 17 00:00:00 2001 From: "Jordan K. Hubbard" Date: Mon, 29 Dec 1997 20:56:21 +0000 Subject: [PATCH] * 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 --- usr.bin/du/du.1 | 57 ++++++------- usr.bin/du/du.c | 212 +++++++++++++++++++++++++++--------------------- 2 files changed, 145 insertions(+), 124 deletions(-) diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1 index e84a710c0611..0934fcafc9a7 100644 --- a/usr.bin/du/du.1 +++ b/usr.bin/du/du.1 @@ -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 , diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c index 8c0724c3dda8..4c81e6257fdb 100644 --- a/usr.bin/du/du.c +++ b/usr.bin/du/du.c @@ -44,6 +44,7 @@ static char copyright[] = static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; #endif /* not lint */ + #include #include @@ -56,63 +57,75 @@ static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; #include #include -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(¬used, &blocksize); + (void) getbsize(¬used, &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;