diff options
Diffstat (limited to 'src/du.c')
-rw-r--r-- | src/du.c | 212 |
1 files changed, 101 insertions, 111 deletions
@@ -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); } |