From d57cf221746eadf87e612f8d4596cbed91f4860d Mon Sep 17 00:00:00 2001 From: Daniel Gall
Date: Wed, 7 Feb 2018 01:27:43 -0500 Subject: [PATCH] :Added user subtotal repoting to du --- NEWS | 2 + doc/coreutils.texi | 5 ++ src/du.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 176 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 8a9e09e..6192b07 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,8 @@ GNU coreutils NEWS -*- outline -*- timeout now supports the --verbose option to diagnose forced termination. + du now supports the -u option for user reporting + ** Improvements dd now supports iflag=direct with arbitrary sized files on all file systems. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index cdde136..fb61345 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -12100,6 +12100,11 @@ the newline and any later characters are ignored; if @env{TIME_STYLE} begins with @samp{posix-} the @samp{posix-} is ignored; and if @env{TIME_STYLE} is @samp{locale} it is ignored. +@item -u +@opindex -u +@cindex user reporting +Show user subtotals for each item reported on. + @item -X @var{file} @itemx --exclude-from=@var{file} @opindex -X @var{file} diff --git a/src/du.c b/src/du.c index ac4489f..a1d06d5 100644 --- a/src/du.c +++ b/src/du.c @@ -37,6 +37,7 @@ #include "fprintftime.h" #include "human.h" #include "mountlist.h" +#include "pwd.h" #include "quote.h" #include "stat-size.h" #include "stat-time.h" @@ -61,6 +62,9 @@ extern bool fts_debug; # define FTS_CROSS_CHECK(Fts) #endif +/* If true, display user size info. */ +bool opt_user_sizes = false; + /* A set of dev/ino pairs to help identify files and directories whose sizes have already been counted. */ static struct di_set *di_files; @@ -81,6 +85,9 @@ struct duinfo /* Number of inodes in directory. */ uintmax_t inodes; + /* Pointer to array of uid indexed size subtotals. */ + uintmax_t *user_size; + /* Latest timestamp found. If tmax.tv_sec == TYPE_MINIMUM (time_t) && tmax.tv_nsec < 0, no timestamp has been found. */ struct timespec tmax; @@ -90,28 +97,62 @@ struct duinfo static inline void duinfo_init (struct duinfo *a) { + uintmax_t i = 0; a->size = 0; a->inodes = 0; a->tmax.tv_sec = TYPE_MINIMUM (time_t); a->tmax.tv_nsec = -1; + if (opt_user_sizes) + { + for (i=0; i<65535; i++) + { + a->user_size[i] = 0; + } + } } /* Set directory data. */ static inline void -duinfo_set (struct duinfo *a, uintmax_t size, struct timespec tmax) +duinfo_set (struct duinfo *a, uintmax_t size, struct timespec tmax, uintmax_t uid) { + uintmax_t uid_u = (uintmax_t)uid; + uintmax_t uid_s; a->size = size; a->inodes = 1; a->tmax = tmax; + if (opt_user_sizes) + { + if (uid_u > 65534) + { + uid_s = 65534; + } + else + { + uid_s = uid_u; + } + if (uid_s >=0 && uid_s <=65534) + { + a->user_size[uid_s] = size; + } + } } /* Accumulate directory data. */ static inline void duinfo_add (struct duinfo *a, struct duinfo const *b) { + uintmax_t i = 0; uintmax_t sum = a->size + b->size; a->size = a->size <= sum ? sum : UINTMAX_MAX; a->inodes = a->inodes + b->inodes; + if (opt_user_sizes) + { + for (i=0; i<65535; i++) + { + sum = a->user_size[i] + b->user_size[i]; + a->user_size[i] = a->user_size[i] <= sum ? sum : UINTMAX_MAX; + } + } if (timespec_cmp (a->tmax, b->tmax) < 0) a->tmax = b->tmax; } @@ -239,6 +280,7 @@ static struct option const long_options[] = {"threshold", required_argument, NULL, 't'}, {"time", optional_argument, NULL, TIME_OPTION}, {"time-style", required_argument, NULL, TIME_STYLE_OPTION}, + {"user-reporting", no_argument, NULL, 'u'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} @@ -346,6 +388,7 @@ Summarize disk usage of the set of FILEs, recursively for directories.\n\ FORMAT is interpreted like in 'date'\n\ "), stdout); fputs (_("\ + -u, --user-reporting also print user subtotals\n\ -X, --exclude-from=FILE exclude files that match any pattern in FILE\n\ --exclude=PATTERN exclude files that match PATTERN\n\ -x, --one-file-system skip directories on different file systems\n\ @@ -411,7 +454,25 @@ print_size (const struct duinfo *pdui, const char *string) print_only_size (opt_inodes ? pdui->inodes : pdui->size); - + if (opt_user_sizes) + { + uintmax_t i=0; + struct passwd *g; + printf(" Users"); + for (i=0; i<65535; i++){ + if (pdui->user_size[i] > 0) + { + g = getpwuid(i); + printf (","); + if (g == NULL){ + printf (" %Ld:", (long long unsigned int)i); + }else{ + printf(" %s:", g->pw_name); + } + print_only_size(pdui->user_size[i]); + } + } + } if (opt_time) { putchar ('\t'); @@ -506,6 +567,12 @@ process_file (FTS *fts, FTSENT *ent) const struct stat *sb = ent->fts_statp; int info = ent->fts_info; + if(opt_user_sizes) + { + dui.user_size = xcalloc (65536, sizeof (uintmax_t)); + dui_to_print.user_size = xcalloc (65536, sizeof (uintmax_t)); + } + if (info == FTS_DNR) { /* An error occurred, but the size is known, so count it. */ @@ -530,7 +597,18 @@ process_file (FTS *fts, FTSENT *ent) if (info == FTS_NS || info == FTS_SLNONE) { error (0, ent->fts_errno, _("cannot access %s"), quoteaf (file)); - return false; + if(opt_user_sizes) + { + if (dui.user_size != NULL) + { + free(dui.user_size); + } + if (dui_to_print.user_size != NULL) + { + free(dui_to_print.user_size); + } + } + return false; } /* The --one-file-system (-x) option cannot exclude anything @@ -558,13 +636,34 @@ process_file (FTS *fts, FTSENT *ent) FTSENT const *e = fts_read (fts); assert (e == ent); } - + if(opt_user_sizes) + { + if (dui.user_size != NULL) + { + free(dui.user_size); + } + if (dui_to_print.user_size != NULL) + { + free(dui_to_print.user_size); + } + } return true; } switch (info) { case FTS_D: + if(opt_user_sizes) + { + if (dui.user_size != NULL) + { + free(dui.user_size); + } + if (dui_to_print.user_size != NULL) + { + free(dui_to_print.user_size); + } + } return true; case FTS_ERR: @@ -574,6 +673,17 @@ process_file (FTS *fts, FTSENT *ent) break; case FTS_DC: + if(opt_user_sizes) + { + if (dui.user_size != NULL) + { + free(dui.user_size); + } + if (dui_to_print.user_size != NULL) + { + free(dui_to_print.user_size); + } + } /* If not following symlinks and not a (bind) mount point. */ if (cycle_warning_required (fts, ent) && ! mount_point_in_fts_cycle (ent)) @@ -584,22 +694,46 @@ process_file (FTS *fts, FTSENT *ent) return true; } } - duinfo_set (&dui, (apparent_size ? MAX (0, sb->st_size) : (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE), (time_type == time_mtime ? get_stat_mtime (sb) : time_type == time_atime ? get_stat_atime (sb) - : get_stat_ctime (sb))); + : get_stat_ctime (sb)), + sb->st_uid); level = ent->fts_level; - dui_to_print = dui; + + if (opt_user_sizes) + { + duinfo_set (&dui_to_print, + (apparent_size + ? MAX (0, sb->st_size) + : (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE), + (time_type == time_mtime ? get_stat_mtime (sb) + : time_type == time_atime ? get_stat_atime (sb) + : get_stat_ctime (sb)), + sb->st_uid); + } + else + { + dui_to_print = dui; + } if (n_alloc == 0) { + size_t i; n_alloc = level + 10; dulvl = xcalloc (n_alloc, sizeof *dulvl); + if(opt_user_sizes) + { + for (i=0; i