]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
(fts_debug, opt_all, apparent_size, opt_count_all,
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 2 Aug 2004 19:43:38 +0000 (19:43 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 2 Aug 2004 19:43:38 +0000 (19:43 +0000)
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.

src/du.c

index 61f03248564df9d0062da22912d62b0d4a1147a6..a3a368ad2152e0e1b51dc82f605b97c1204368ed 100644 (file)
--- 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);
 }