[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Du feature request - user reporting
From: |
Daniel Gall |
Subject: |
Re: Du feature request - user reporting |
Date: |
Wed, 7 Feb 2018 06:55:10 -0500 |
Sigh I am new at git. Will have to fix that printf (" Groups"); back to Users.
On Wed, Feb 7, 2018 at 6:54 AM, Daniel Gall <address@hidden> wrote:
> And I had to clarify a variable name to enable trivial integration of
> the group subtotal reporting feature requested in other
> correspondence.
>
> Also, this feature (user subtotal reporting) will be really useful for
> quickly getting at which users are the primary space hogs in large
> shared directories. An admin doesn't care if a user has 10,000 files
> of 4KiB each. An admin definitely does care if another user's 3 files
> consume several GiB. Especially in /tmp. Also in large shared
> directories in fast scratch file systems like lustre or GPFS.
>
> From 9c728a4cde1d023131a5a675b878de3a05dec920 Mon Sep 17 00:00:00 2001
> From: Daniel Gall <address@hidden>
> Date: Wed, 7 Feb 2018 01:48:13 -0500
> Subject: [PATCH 2/2] du: clarified a variable name
>
> The user subtotal reporting feature should integrate trivially
> with the group subtotal reporting feature described in other
> correspondence. Thus I changed a variable name for clarity in
> reading. passwd *g is now passwd *u.
> ---
> src/du.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/src/du.c b/src/du.c
> index a1d06d5..53349c2 100644
> --- a/src/du.c
> +++ b/src/du.c
> @@ -457,17 +457,17 @@ print_size (const struct duinfo *pdui, const char
> *string)
> if (opt_user_sizes)
> {
> uintmax_t i=0;
> - struct passwd *g;
> - printf(" Users");
> + struct passwd *u;
> + printf(" Groups");
> for (i=0; i<65535; i++){
> if (pdui->user_size[i] > 0)
> {
> - g = getpwuid(i);
> + u = getpwuid(i);
> printf (",");
> - if (g == NULL){
> + if (u == NULL){
> printf (" %Ld:", (long long unsigned int)i);
> }else{
> - printf(" %s:", g->pw_name);
> + printf(" %s:", u->pw_name);
> }
> print_only_size(pdui->user_size[i]);
> }
> --
> 2.10.2
>
>
> On Wed, Feb 7, 2018 at 6:35 AM, Daniel Gall <address@hidden> wrote:
>> From d57cf221746eadf87e612f8d4596cbed91f4860d Mon Sep 17 00:00:00 2001
>> From: Daniel Gall <address@hidden>
>> 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<n_alloc; i++)
>> + {
>> + dulvl[i].ent.user_size = xcalloc (65536, sizeof (uintmax_t));
>> + dulvl[i].subdir.user_size = xcalloc (65536, sizeof
>> (uintmax_t));
>> + }
>> + }
>> }
>> else
>> {
>> @@ -613,14 +747,23 @@ process_file (FTS *fts, FTSENT *ent)
>> Clear the accumulators for *all* levels between prev_level
>> and the current one. The depth may change dramatically,
>> e.g., from 1 to 10. */
>> + size_t i;
>>
>> if (n_alloc <= level)
>> {
>> dulvl = xnrealloc (dulvl, level, 2 * sizeof *dulvl);
>> + if(opt_user_sizes)
>> + {
>> + for (i=n_alloc; i<level*2; i++)
>> + {
>> + dulvl[i].ent.user_size = xcalloc (65536, sizeof
>> (uintmax_t));
>> + dulvl[i].subdir.user_size = xcalloc (65536,
>> sizeof (uintmax_t));
>> + }
>> + }
>> n_alloc = level * 2;
>> }
>>
>> - for (size_t i = prev_level + 1; i <= level; i++)
>> + for (i = prev_level + 1; i <= level; i++)
>> {
>> duinfo_init (&dulvl[i].ent);
>> duinfo_init (&dulvl[i].subdir);
>> @@ -666,6 +809,18 @@ process_file (FTS *fts, FTSENT *ent)
>> print_size (&dui_to_print, file);
>> }
>>
>> + 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 ok;
>> }
>>
>> @@ -678,7 +833,6 @@ static bool
>> du_files (char **files, int bit_flags)
>> {
>> bool ok = true;
>> -
>> if (*files)
>> {
>> FTS *fts = xfts_open (files, bit_flags, NULL);
>> @@ -755,7 +909,7 @@ main (int argc, char **argv)
>> while (true)
>> {
>> int oi = -1;
>> - int c = getopt_long (argc, argv, "0abd:chHklmst:xB:DLPSX:",
>> + int c = getopt_long (argc, argv, "0abd:chHklmst:uxB:DLPSX:",
>> long_options, &oi);
>> if (c == -1)
>> break;
>> @@ -850,6 +1004,11 @@ main (int argc, char **argv)
>> }
>> break;
>>
>> + case 'u':
>> + tot_dui.user_size = xcalloc (65536, sizeof (uintmax_t));
>> + opt_user_sizes = true;
>> + break;
>> +
>> case 'x':
>> bit_flags |= FTS_XDEV;
>> break;
>> --
>> 2.10.2