summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-08-02 19:43:38 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-08-02 19:43:38 +0000
commite4d5fc228349cf93a89fa184ba0d1e5db52d5fc0 (patch)
tree7c99f696fc5f417f7b82bec45ded385a42326e50 /src
parentc1bbe24045ae919d1fc2dbf225d030828632c7c8 (diff)
downloadcoreutils-e4d5fc228349cf93a89fa184ba0d1e5db52d5fc0.tar.xz
(fts_debug, opt_all, apparent_size, opt_count_all,
print_grand_total, opt_separate_dirs, hash_ins, process_file, main): Use bool for booleans. (max_depth): Now size_t, not int, to avoid an arbitrary limit of INT_MAX on depth. (G_fail): Remove: no longer needed, now that the relevant functions return bool. (process_file): Use return value to signal success rather than setting a global. Remove first_call static var; not needed, since we can look at n_alloc. Use size_t for depths. Remove FIXME about size_t casts, as it's now fixed. Use xnrealloc rather than the obsolescent XREALLOC. Don't bother to check whether reallocation is needed unless level > prev_level. (du_files): Invert sense of result, for consistency with other coreutils code. All callers changed. (main): Allow --max-depth values up to SIZE_MAX.
Diffstat (limited to 'src')
-rw-r--r--src/du.c212
1 files changed, 101 insertions, 111 deletions
diff --git a/src/du.c b/src/du.c
index 61f032485..a3a368ad2 100644
--- a/src/du.c
+++ b/src/du.c
@@ -43,7 +43,7 @@
#include "xfts.h"
#include "xstrtol.h"
-extern int fts_debug;
+extern bool fts_debug;
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "du"
@@ -77,29 +77,29 @@ static Hash_table *htab;
/* Name under which this program was invoked. */
char *program_name;
-/* If nonzero, display counts for all files, not just directories. */
-static int opt_all = 0;
+/* If true, display counts for all files, not just directories. */
+static bool opt_all = false;
-/* If nonzero, rather than using the disk usage of each file,
+/* If true, rather than using the disk usage of each file,
use the apparent size (a la stat.st_size). */
-static int apparent_size = 0;
+static bool apparent_size = false;
-/* If nonzero, count each hard link of files with multiple links. */
-static int opt_count_all = 0;
+/* If true, count each hard link of files with multiple links. */
+static bool opt_count_all = false;
/* If true, output the NUL byte instead of a newline at the end of each line. */
static bool opt_nul_terminate_output = false;
-/* If nonzero, print a grand total at the end. */
-static int print_grand_total = 0;
+/* If true, print a grand total at the end. */
+static bool print_grand_total = false;
/* If nonzero, do not add sizes of subdirectories. */
-static int opt_separate_dirs = 0;
+static bool opt_separate_dirs = false;
/* Show the total for each directory (and file if --all) 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'. */
-static int max_depth = INT_MAX;
+static size_t max_depth = SIZE_MAX;
/* Human-readable options for output. */
static int human_output_opts;
@@ -113,9 +113,6 @@ static struct exclude *exclude;
/* Grand total size of all args, in bytes. */
static uintmax_t tot_size = 0;
-/* Nonzero indicates that du should exit with EXIT_FAILURE upon completion. */
-static int G_fail;
-
#define IS_DIR_TYPE(Type) \
((Type) == FTS_DP \
|| (Type) == FTS_DNR)
@@ -247,10 +244,9 @@ entry_compare (void const *x, void const *y)
}
/* Try to insert the INO/DEV pair into the global table, HTAB.
- If the pair is successfully inserted, return zero.
- Upon failed memory allocation exit nonzero.
- If the pair is already in the table, return nonzero. */
-static int
+ Return true if the pair is successfully inserted,
+ false if the pair is already in the table. */
+static bool
hash_ins (ino_t ino, dev_t dev)
{
struct entry *ent;
@@ -270,13 +266,13 @@ hash_ins (ino_t ino, dev_t dev)
if (ent_from_table == ent)
{
/* Insertion succeeded. */
- return 0;
+ return true;
}
/* That pair is already in the table, so ENT was not inserted. Free it. */
free (ent);
- return 1;
+ return false;
}
/* Initialize the hash table. */
@@ -313,14 +309,15 @@ print_size (uintmax_t n_bytes, const char *string)
/* This function is called once for every file system object that fts
encounters. fts does a depth-first traversal. This function knows
that and accumulates per-directory totals based on changes in
- the depth of the current entry. */
+ the depth of the current entry. It returns true on success. */
-static void
+static bool
process_file (FTS *fts, FTSENT *ent)
{
+ bool ok;
uintmax_t size;
uintmax_t size_to_print;
- static int first_call = 1;
+ size_t level;
static size_t prev_level;
static size_t n_alloc;
/* The sum of the st_size values of all entries in the single directory
@@ -332,11 +329,11 @@ process_file (FTS *fts, FTSENT *ent)
/* The sum of the sizes of all entries in the hierarchy at or below the
directory at the specified level. */
static uintmax_t *sum_subdir;
- int print = 1;
+ bool print = true;
const char *file = ent->fts_path;
const struct stat *sb = ent->fts_statp;
- int skip;
+ bool skip;
/* If necessary, set FTS_SKIP before returning. */
skip = excluded_filename (exclude, ent->fts_name);
@@ -347,23 +344,22 @@ process_file (FTS *fts, FTSENT *ent)
{
case FTS_NS:
error (0, ent->fts_errno, _("cannot access %s"), quote (file));
- G_fail = 1;
- return;
+ return false;
case FTS_ERR:
/* if (S_ISDIR (ent->fts_statp->st_mode) && FIXME */
error (0, ent->fts_errno, _("%s"), quote (file));
- G_fail = 1;
- return;
+ return false;
case FTS_DNR:
/* Don't return just yet, since although the directory is not readable,
we were able to stat it, so we do have a size. */
error (0, ent->fts_errno, _("cannot read directory %s"), quote (file));
- G_fail = 1;
+ ok = false;
break;
default:
+ ok = true;
break;
}
@@ -371,7 +367,7 @@ process_file (FTS *fts, FTSENT *ent)
or if it's the second encounter for a skipped directory, then
return right away. */
if (ent->fts_info == FTS_D || skip)
- return;
+ return ok;
/* If the file is being excluded or if it has already been counted
via a hard link, then don't let it contribute to the sums. */
@@ -379,13 +375,13 @@ process_file (FTS *fts, FTSENT *ent)
|| (!opt_count_all
&& ! S_ISDIR (sb->st_mode)
&& 1 < sb->st_nlink
- && hash_ins (sb->st_ino, sb->st_dev)))
+ && ! hash_ins (sb->st_ino, sb->st_dev)))
{
/* Note that we must not simply return here.
We still have to update prev_level and maybe propagate
some sums up the hierarchy. */
size = 0;
- print = 0;
+ print = false;
}
else
{
@@ -394,49 +390,44 @@ process_file (FTS *fts, FTSENT *ent)
: ST_NBLOCKS (*sb) * ST_NBLOCKSIZE);
}
- if (first_call)
+ level = ent->fts_level;
+ size_to_print = size;
+
+ if (n_alloc == 0)
{
- n_alloc = ent->fts_level + 10;
- sum_ent = XCALLOC (uintmax_t, n_alloc);
- sum_subdir = XCALLOC (uintmax_t, n_alloc);
+ n_alloc = level + 10;
+ sum_ent = xcalloc (n_alloc, sizeof *sum_ent);
+ sum_subdir = xcalloc (n_alloc, sizeof *sum_subdir);
}
else
{
- /* FIXME: it's a shame that we need these `size_t' casts to avoid
- warnings from gcc about `comparison between signed and unsigned'.
- Probably unavoidable, assuming that the struct members
- are of type `int' (historical), since I want variables like
- n_alloc and prev_level to have types that make sense. */
- if (n_alloc <= (size_t) ent->fts_level)
- {
- n_alloc = ent->fts_level * 2;
- sum_ent = XREALLOC (sum_ent, uintmax_t, n_alloc);
- sum_subdir = XREALLOC (sum_subdir, uintmax_t, n_alloc);
- }
- }
-
- size_to_print = size;
-
- if (! first_call)
- {
- if ((size_t) ent->fts_level == prev_level)
+ if (level == prev_level)
{
/* This is usually the most common case. Do nothing. */
}
- else if (ent->fts_level > prev_level)
+ else if (level > prev_level)
{
/* Descending the hierarchy.
Clear the accumulators for *all* levels between prev_level
and the current one. The depth may change dramatically,
e.g., from 1 to 10. */
- int i;
- for (i = prev_level + 1; i <= ent->fts_level; i++)
+ size_t i;
+
+ if (n_alloc <= level)
+ {
+ sum_ent = xnrealloc (sum_ent, level, 2 * sizeof *sum_ent);
+ sum_subdir = xnrealloc (sum_subdir, level,
+ 2 * sizeof *sum_subdir);
+ n_alloc = level * 2;
+ }
+
+ for (i = prev_level + 1; i <= level; i++)
{
sum_ent[i] = 0;
sum_subdir[i] = 0;
}
}
- else /* ent->fts_level < prev_level */
+ else /* level < prev_level */
{
/* Ascending the hierarchy.
Process a directory only after all entries in that
@@ -444,22 +435,20 @@ process_file (FTS *fts, FTSENT *ent)
propagate sums from the children (prev_level) to the parent.
Here, the current level is always one smaller than the
previous one. */
- assert ((size_t) ent->fts_level == prev_level - 1);
+ assert (level == prev_level - 1);
size_to_print += sum_ent[prev_level];
if (!opt_separate_dirs)
size_to_print += sum_subdir[prev_level];
- sum_subdir[ent->fts_level] += (sum_ent[prev_level]
- + sum_subdir[prev_level]);
+ sum_subdir[level] += sum_ent[prev_level] + sum_subdir[prev_level];
}
}
- prev_level = ent->fts_level;
- first_call = 0;
+ prev_level = level;
/* Let the size of a directory entry contribute to the total for the
containing directory, unless --separate-dirs (-S) is specified. */
if ( ! (opt_separate_dirs && IS_DIR_TYPE (ent->fts_info)))
- sum_ent[ent->fts_level] += size;
+ sum_ent[level] += size;
/* Even if this directory is unreadable or we can't chdir into it,
do let its size contribute to the total, ... */
@@ -468,16 +457,16 @@ process_file (FTS *fts, FTSENT *ent)
/* ... but don't print out a total for it, since without the size(s)
of any potential entries, it could be very misleading. */
if (ent->fts_info == FTS_DNR)
- return;
+ return ok;
/* If we're not counting an entry, e.g., because it's a hard link
to a file we've already counted (and --count-links), then don't
print a line for it. */
if (!print)
- return;
+ return ok;
- if ((IS_DIR_TYPE (ent->fts_info) && ent->fts_level <= max_depth)
- || ((opt_all && ent->fts_level <= max_depth) || ent->fts_level == 0))
+ if ((IS_DIR_TYPE (ent->fts_info) && level <= max_depth)
+ || ((opt_all && level <= max_depth) || level == 0))
{
print_only_size (size_to_print);
fputc ('\t', stdout);
@@ -485,18 +474,19 @@ process_file (FTS *fts, FTSENT *ent)
fputc (opt_nul_terminate_output ? '\0' : '\n', stdout);
fflush (stdout);
}
+
+ return ok;
}
/* Recursively print the sizes of the directories (and, if selected, files)
named in FILES, the last entry of which is NULL.
BIT_FLAGS controls how fts works.
- If the fts_open call fails, exit nonzero.
- Otherwise, return nonzero upon error. */
+ Return true if successful. */
static bool
du_files (char **files, int bit_flags)
{
- bool fail = false;
+ bool ok = true;
if (*files)
{
@@ -513,13 +503,13 @@ du_files (char **files, int bit_flags)
{
/* FIXME: try to give a better message */
error (0, errno, _("fts_read failed"));
- fail = true;
+ ok = false;
}
break;
}
FTS_CROSS_CHECK (fts);
- process_file (fts, ent);
+ ok &= process_file (fts, ent);
}
/* Ignore failure, since the only way it can do so is in failing to
@@ -531,7 +521,7 @@ du_files (char **files, int bit_flags)
if (print_grand_total)
print_size (tot_size, _("total"));
- return fail;
+ return ok;
}
int
@@ -539,17 +529,17 @@ main (int argc, char **argv)
{
int c;
char *cwd_only[2];
- int max_depth_specified = 0;
+ bool max_depth_specified = false;
char **files;
- bool fail;
+ bool ok = true;
char *files_from = NULL;
struct Tokens tok;
/* Bit flags that control how fts works. */
int bit_flags = FTS_PHYSICAL | FTS_TIGHT_CYCLE_CHECK;
- /* If nonzero, display only a total for each argument. */
- int opt_summarize_only = 0;
+ /* If true, display only a total for each argument. */
+ bool opt_summarize_only = false;
cwd_only[0] = ".";
cwd_only[1] = NULL;
@@ -567,11 +557,9 @@ main (int argc, char **argv)
human_output_opts = human_options (getenv ("DU_BLOCK_SIZE"), false,
&output_block_size);
- fail = false;
while ((c = getopt_long (argc, argv, DEBUG_OPT "0abchHklmsxB:DLPSX:",
long_options, NULL)) != -1)
{
- long int tmp_long;
switch (c)
{
case 0: /* Long option. */
@@ -579,7 +567,7 @@ main (int argc, char **argv)
#if DU_DEBUG
case 'd':
- fts_debug = 1;
+ fts_debug = true;
break;
#endif
@@ -588,21 +576,21 @@ main (int argc, char **argv)
break;
case 'a':
- opt_all = 1;
+ opt_all = true;
break;
case APPARENT_SIZE_OPTION:
- apparent_size = 1;
+ apparent_size = true;
break;
case 'b':
- apparent_size = 1;
+ apparent_size = true;
human_output_opts = 0;
output_block_size = 1;
break;
case 'c':
- print_grand_total = 1;
+ print_grand_total = true;
break;
case 'h':
@@ -625,18 +613,21 @@ main (int argc, char **argv)
break;
case MAX_DEPTH_OPTION: /* --max-depth=N */
- if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) == LONGINT_OK
- && 0 <= tmp_long && tmp_long <= INT_MAX)
- {
- max_depth_specified = 1;
- max_depth = (int) tmp_long;
- }
- else
- {
- error (0, 0, _("invalid maximum depth %s"),
- quote (optarg));
- fail = true;
- }
+ {
+ unsigned long int tmp_ulong;
+ if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
+ && tmp_ulong <= SIZE_MAX)
+ {
+ max_depth_specified = true;
+ max_depth = tmp_ulong;
+ }
+ else
+ {
+ error (0, 0, _("invalid maximum depth %s"),
+ quote (optarg));
+ ok = false;
+ }
+ }
break;
case 'm': /* obsolescent: FIXME: remove in 2005. */
@@ -645,11 +636,11 @@ main (int argc, char **argv)
break;
case 'l':
- opt_count_all = 1;
+ opt_count_all = true;
break;
case 's':
- opt_summarize_only = 1;
+ opt_summarize_only = true;
break;
case 'x':
@@ -673,7 +664,7 @@ main (int argc, char **argv)
break;
case 'S':
- opt_separate_dirs = 1;
+ opt_separate_dirs = true;
break;
case 'X':
@@ -681,7 +672,7 @@ main (int argc, char **argv)
EXCLUDE_WILDCARDS, '\n'))
{
error (0, errno, "%s", quotearg_colon (optarg));
- fail = true;
+ ok = false;
}
break;
@@ -698,14 +689,14 @@ main (int argc, char **argv)
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
- fail = true;
+ ok = false;
}
}
- if (fail)
+ if (!ok)
usage (EXIT_FAILURE);
- if (opt_all && opt_summarize_only)
+ if (opt_all & opt_summarize_only)
{
error (0, 0, _("cannot both summarize and show all entries"));
usage (EXIT_FAILURE);
@@ -719,9 +710,8 @@ main (int argc, char **argv)
if (opt_summarize_only && max_depth_specified && max_depth != 0)
{
- error (0, 0,
- _("warning: summarizing conflicts with --max-depth=%d"),
- max_depth);
+ unsigned long int d = max_depth;
+ error (0, 0, _("warning: summarizing conflicts with --max-depth=%lu"), d);
usage (EXIT_FAILURE);
}
@@ -797,10 +787,10 @@ main (int argc, char **argv)
}
}
- fail = (i != j);
+ ok = (i == j);
}
- fail |= du_files (files, bit_flags);
+ ok &= du_files (files, bit_flags);
/* This isn't really necessary, but it does ensure we
exercise this function. */
@@ -809,5 +799,5 @@ main (int argc, char **argv)
hash_free (htab);
- exit (fail || G_fail ? EXIT_FAILURE : EXIT_SUCCESS);
+ exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}