summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-03-27 05:47:56 +0000
committerJim Meyering <jim@meyering.net>1997-03-27 05:47:56 +0000
commitcc093a994519836364d627b418b38365a2519277 (patch)
treecd1688f39fade8b3b6b57333be089c9ba7ec624f /src
parent3416bdb6e177f8883ccdceb3e15a5704fa0f56e6 (diff)
downloadcoreutils-cc093a994519836364d627b418b38365a2519277.tar.xz
(main): Implement new --max-depth=N option.
Based on the idea and a patch from Torbjorn Lindgren. (du_files): Likewise. (count_entry): Likewise.
Diffstat (limited to 'src')
-rw-r--r--src/du.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/du.c b/src/du.c
index e43617b15..5ab897b4e 100644
--- a/src/du.c
+++ b/src/du.c
@@ -53,6 +53,7 @@
#include "system.h"
#include "save-cwd.h"
#include "error.h"
+#include "xstrtol.h"
#undef convert_blocks
#define convert_blocks(b, size) (size == size_kilobytes ? ((b) + 1) / 2 : \
@@ -112,7 +113,8 @@ char *xrealloc ();
static int hash_insert __P ((ino_t ino, dev_t dev));
static int hash_insert2 __P ((struct htab *_htab, ino_t ino, dev_t dev));
-static long count_entry __P ((char *ent, int top, dev_t last_dev));
+static long count_entry __P ((const char *ent, int top, dev_t last_dev,
+ int max_depth));
static void du_files __P ((char **files));
static void hash_init __P ((unsigned int modulus,
unsigned int entry_tab_size));
@@ -146,6 +148,12 @@ static int opt_separate_dirs = 0;
/* If nonzero, dereference symlinks that are command line arguments. */
static int opt_dereference_arguments = 0;
+/* Show the total for each directory that is at most MAX_DEPTH levels
+ down from the root of the hierarchy. The root is at level 0, so
+ `du --max-depth=0' is equivalent to `du -s.' `du --max-depth=1' is
+ like `du -s *' but includes directories whose names begin with `.'. */
+static int max_depth = INT_MAX;
+
enum output_size
{
size_blocks, /* 512-byte blocks. */
@@ -194,6 +202,7 @@ static struct option const long_options[] =
{"dereference-args", no_argument, &opt_dereference_arguments, 1},
{"human-readable", no_argument, NULL, 'h'},
{"kilobytes", no_argument, NULL, 'k'},
+ {"max-depth", required_argument, NULL, 13},
{"megabytes", no_argument, NULL, 'm'},
{"one-file-system", no_argument, &opt_one_file_system, 1},
{"separate-dirs", no_argument, &opt_separate_dirs, 1},
@@ -232,6 +241,8 @@ Summarize disk usage of each FILE, recursively for directories.\n\
-S, --separate-dirs do not include size of subdirectories\n\
-s, --summarize display only a total for each argument\n\
-x, --one-file-system skip directories on different filesystems\n\
+ --max-depth=N FIXME how deep to recurse before not showing the size,\n\
+ --depth=0 is equal to -s aka --summarize.\n\
--help display this help and exit\n\
--version output version information and exit\n\
"));
@@ -271,6 +282,7 @@ main (int argc, char **argv)
while ((c = getopt_long (argc, argv, "abchklmsxDLS", long_options, NULL))
!= -1)
{
+ long int tmp_long;
switch (c)
{
case 0: /* Long option. */
@@ -299,6 +311,14 @@ main (int argc, char **argv)
opt_human_readable = 0;
break;
+ case 13: /* --max-depth=N */
+ if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
+ || tmp_long < 0 || tmp_long > INT_MAX)
+ error (1, 0, _("invalid maximum depth `%s'"), optarg);
+
+ max_depth = (int) tmp_long;
+ break;
+
case 'm':
output_size = size_megabytes;
opt_human_readable = 0;
@@ -455,7 +475,7 @@ du_files (char **files)
if (!opt_combined_arguments)
hash_reset ();
- count_entry (arg, 1, 0);
+ count_entry (arg, 1, 0, max_depth);
/* chdir if `count_entry' has changed the working directory. */
if (stat (".", &stat_buf))
@@ -490,9 +510,10 @@ du_files (char **files)
(in units determined by `output_size') of file or directory ENT.
TOP is one for external calls, zero for recursive calls.
LAST_DEV is the device that the parent directory of ENT is on. */
+/* FIXME: describe DEPTH */
static long
-count_entry (char *ent, int top, dev_t last_dev)
+count_entry (const char *ent, int top, dev_t last_dev, int depth)
{
long size;
@@ -585,7 +606,7 @@ count_entry (char *ent, int top, dev_t last_dev)
{
str_concatc (path, namep);
- size += count_entry (namep, 0, dir_dev);
+ size += count_entry (namep, 0, dir_dev, depth - 1);
str_trunc (path, pathlen);
namep += strlen (namep) + 1;
@@ -601,7 +622,7 @@ count_entry (char *ent, int top, dev_t last_dev)
_("cannot change to `..' from directory %s"), path->text);
str_trunc (path, pathlen - 1); /* Remove the "/" we added. */
- if (!opt_summarize_only || top)
+ if ((!opt_summarize_only && depth >= 0) || top)
{
if (opt_human_readable)
{