[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Du feature request - group reporting
From: |
Daniel Gall |
Subject: |
Re: Du feature request - group reporting |
Date: |
Fri, 2 Mar 2018 00:22:24 -0500 |
Have I done something incorrectly? How or does this feature request
proceed from here?
Thank you for considering it.
Dan.
On Wednesday, February 28, 2018, Daniel Gall <address@hidden>
wrote:
> uggh and i'm not current with master. one more time.
>
> From bbbbd12345c4585de20f2fef304c6b5c7185d2a2 Mon Sep 17 00:00:00 2001
> From: Daniel Gall <address@hidden>
> Date: Tue, 27 Feb 2018 20:05:01 -0500
> Subject: [PATCH] du: Added group reporting feature
>
> ---
> NEWS | 2 +
> doc/coreutils.texi | 5 ++
> src/du.c | 176 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++---
> 3 files changed, 174 insertions(+), 9 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 5fa6928..a136cc9 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -61,6 +61,8 @@ GNU coreutils NEWS
> -*- outline -*-
>
> timeout now supports the --verbose option to diagnose forced
> termination.
>
> + du now supports the -g option for group 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..d220012 100644
> --- a/doc/coreutils.texi
> +++ b/doc/coreutils.texi
> @@ -11910,6 +11910,11 @@ is at level 0, so @code{du --max-depth=0} is
> equivalent to @code{du -s}.
> @c --files0-from=FILE
> @filesZeroFromOption{du,, with the @option{--total} (@option{-c}) option}
>
> +@item -g
> +@opindex -g
> +@cindex group reporting
> +Show group subtotals for each item reported on.
> +
> @item -H
> @opindex -H
> Equivalent to @option{--dereference-args} (@option{-D}).
> diff --git a/src/du.c b/src/du.c
> index ac4489f..97edb5d 100644
> --- a/src/du.c
> +++ b/src/du.c
> @@ -35,6 +35,7 @@
> #include "error.h"
> #include "exclude.h"
> #include "fprintftime.h"
> +#include "grp.h"
> #include "human.h"
> #include "mountlist.h"
> #include "quote.h"
> @@ -61,6 +62,9 @@ extern bool fts_debug;
> # define FTS_CROSS_CHECK(Fts)
> #endif
>
> +/* If true, display group size info. */
> +bool opt_group_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;
> @@ -80,7 +84,7 @@ struct duinfo
>
> /* Number of inodes in directory. */
> uintmax_t inodes;
> -
> + uintmax_t *group_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 +94,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_group_sizes)
> + {
> + for (i=0; i<65535; i++)
> + {
> + a->group_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 gid)
> {
> + uintmax_t gid_u = (uintmax_t)gid;
> + uintmax_t gid_s;
> a->size = size;
> a->inodes = 1;
> a->tmax = tmax;
> + if (opt_group_sizes)
> + {
> + if (gid_u > 65534)
> + {
> + gid_s = 65534;
> + }
> + else
> + {
> + gid_s = gid_u;
> + }
> + if (gid_s >=0 && gid_s <=65534)
> + {
> + a->group_size[gid_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_group_sizes)
> + {
> + for (i=0; i<65535; i++)
> + {
> + sum = a->group_size[i] + b->group_size[i];
> + a->group_size[i] = a->group_size[i] <= sum ? sum : UINTMAX_MAX;
> + }
> + }
> if (timespec_cmp (a->tmax, b->tmax) < 0)
> a->tmax = b->tmax;
> }
> @@ -226,6 +264,7 @@ static struct option const long_options[] =
> {"exclude", required_argument, NULL, EXCLUDE_OPTION},
> {"exclude-from", required_argument, NULL, 'X'},
> {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
> + {"group-reporting", no_argument, NULL, 'g'},
> {"human-readable", no_argument, NULL, 'h'},
> {"inodes", no_argument, NULL, INODES_OPTION},
> {"si", no_argument, NULL, HUMAN_SI_OPTION},
> @@ -317,6 +356,7 @@ Summarize disk usage of the set of FILEs,
> recursively for directories.\n\
> --files0-from=F summarize disk usage of the\n\
> NUL-terminated file names specified in file
> F;\n\
> if F is -, then read names from standard
> input\n\
> + -g, --group-reporting also print group subtotals\n\
> -H equivalent to --dereference-args (-D)\n\
> -h, --human-readable print sizes in human readable format (e.g.,
> 1K 234M 2G)\
> \n\
> @@ -411,7 +451,25 @@ print_size (const struct duinfo *pdui, const char
> *string)
> print_only_size (opt_inodes
> ? pdui->inodes
> : pdui->size);
> -
> + if (opt_group_sizes)
> + {
> + uintmax_t i=0;
> + struct group *g;
> + printf(" Groups");
> + for (i=0; i<65535; i++){
> + if (pdui->group_size[i] > 0)
> + {
> + g = getgrgid(i);
> + printf (",");
> + if (g == NULL){
> + printf (" %Ld:", (long long unsigned int)i);
> + }else{
> + printf(" %s:", g->gr_name);
> + }
> + print_only_size(pdui->group_size[i]);
> + }
> + }
> + }
> if (opt_time)
> {
> putchar ('\t');
> @@ -506,6 +564,12 @@ process_file (FTS *fts, FTSENT *ent)
> const struct stat *sb = ent->fts_statp;
> int info = ent->fts_info;
>
> + if(opt_group_sizes)
> + {
> + dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> + dui_to_print.group_size = xcalloc (65536, sizeof (uintmax_t));
> + }
> +
> if (info == FTS_DNR)
> {
> /* An error occurred, but the size is known, so count it. */
> @@ -530,7 +594,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_group_sizes)
> + {
> + if (dui.group_size != NULL)
> + {
> + free(dui.group_size);
> + }
> + if (dui_to_print.group_size != NULL)
> + {
> + free(dui_to_print.group_size);
> + }
> + }
> + return false;
> }
>
> /* The --one-file-system (-x) option cannot exclude anything
> @@ -558,13 +633,34 @@ process_file (FTS *fts, FTSENT *ent)
> FTSENT const *e = fts_read (fts);
> assert (e == ent);
> }
> -
> + if(opt_group_sizes)
> + {
> + if (dui.group_size != NULL)
> + {
> + free(dui.group_size);
> + }
> + if (dui_to_print.group_size != NULL)
> + {
> + free(dui_to_print.group_size);
> + }
> + }
> return true;
> }
>
> switch (info)
> {
> case FTS_D:
> + if(opt_group_sizes)
> + {
> + if (dui.group_size != NULL)
> + {
> + free(dui.group_size);
> + }
> + if (dui_to_print.group_size != NULL)
> + {
> + free(dui_to_print.group_size);
> + }
> + }
> return true;
>
> case FTS_ERR:
> @@ -574,6 +670,17 @@ process_file (FTS *fts, FTSENT *ent)
> break;
>
> case FTS_DC:
> + if(opt_group_sizes)
> + {
> + if (dui.group_size != NULL)
> + {
> + free(dui.group_size);
> + }
> + if (dui_to_print.group_size != NULL)
> + {
> + free(dui_to_print.group_size);
> + }
> + }
> /* If not following symlinks and not a (bind) mount point. */
> if (cycle_warning_required (fts, ent)
> && ! mount_point_in_fts_cycle (ent))
> @@ -591,15 +698,40 @@ process_file (FTS *fts, FTSENT *ent)
> : (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_gid);
>
> level = ent->fts_level;
> - dui_to_print = dui;
> +
> + if (opt_group_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_gid);
> + }
> + else
> + {
> + dui_to_print = dui;
> + }
>
> if (n_alloc == 0)
> {
> + size_t i;
> n_alloc = level + 10;
> dulvl = xcalloc (n_alloc, sizeof *dulvl);
> + if(opt_group_sizes)
> + {
> + for (i=0; i<n_alloc; i++)
> + {
> + dulvl[i].ent.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> + dulvl[i].subdir.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> + }
> + }
> }
> else
> {
> @@ -613,14 +745,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_group_sizes)
> + {
> + for (i=n_alloc; i<level*2; i++)
> + {
> + dulvl[i].ent.group_size = xcalloc (65536,
> sizeof (uintmax_t));
> + dulvl[i].subdir.group_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 +807,18 @@ process_file (FTS *fts, FTSENT *ent)
> print_size (&dui_to_print, file);
> }
>
> + if(opt_group_sizes)
> + {
> + if (dui.group_size != NULL)
> + {
> + free(dui.group_size);
> + }
> + if (dui_to_print.group_size != NULL)
> + {
> + free(dui_to_print.group_size);
> + }
> + }
> +
> return ok;
> }
>
> @@ -755,7 +908,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, "0abgd:chHklmst:xB:DLPSX:",
> long_options, &oi);
> if (c == -1)
> break;
> @@ -800,6 +953,11 @@ main (int argc, char **argv)
> output_block_size = 1;
> break;
>
> + case 'g':
> + tot_dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> + opt_group_sizes = true;
> + break;
> +
> case 'k':
> human_output_opts = 0;
> output_block_size = 1024;
> --
> 2.10.2
>
>
> On Wed, Feb 28, 2018 at 12:59 AM, Daniel Gall <address@hidden>
> wrote:
> > Ok, here it all is in one commit.
> >
> > From f170b214684f870e81ab79c83a0dd87206fee4af Mon Sep 17 00:00:00 2001
> > From: Daniel Gall <address@hidden>
> > Date: Tue, 27 Feb 2018 19:51:34 -0500
> > Subject: [PATCH] du: Added group reporting feature
> >
> > ---
> > NEWS | 7 +--
> > doc/coreutils.texi | 5 ++
> > src/du.c | 176 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++---
> > 3 files changed, 174 insertions(+), 14 deletions(-)
> >
> > diff --git a/NEWS b/NEWS
> > index 5fa6928..97ccc2c 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -16,11 +16,6 @@ GNU coreutils NEWS
> > -*- outline -*-
> > that caused -u to sometimes override -n.
> > [bug introduced with coreutils-7.1]
> >
> > - 'cp -a --no-preserve=mode' now sets appropriate default permissions
> > - for non regular files like fifos and character device nodes etc.
> > - Previously it would have set executable bits on created special files.
> > - [bug introduced with coreutils-8.20]
> > -
> >
> > * Noteworthy changes in release 8.29 (2017-12-27) [stable]
> >
> > @@ -61,6 +56,8 @@ GNU coreutils NEWS
> > -*- outline -*-
> >
> > timeout now supports the --verbose option to diagnose forced
> termination.
> >
> > + du now supports the -g option for group 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..d220012 100644
> > --- a/doc/coreutils.texi
> > +++ b/doc/coreutils.texi
> > @@ -11910,6 +11910,11 @@ is at level 0, so @code{du --max-depth=0} is
> > equivalent to @code{du -s}.
> > @c --files0-from=FILE
> > @filesZeroFromOption{du,, with the @option{--total} (@option{-c})
> option}
> >
> > +@item -g
> > +@opindex -g
> > +@cindex group reporting
> > +Show group subtotals for each item reported on.
> > +
> > @item -H
> > @opindex -H
> > Equivalent to @option{--dereference-args} (@option{-D}).
> > diff --git a/src/du.c b/src/du.c
> > index ac4489f..97edb5d 100644
> > --- a/src/du.c
> > +++ b/src/du.c
> > @@ -35,6 +35,7 @@
> > #include "error.h"
> > #include "exclude.h"
> > #include "fprintftime.h"
> > +#include "grp.h"
> > #include "human.h"
> > #include "mountlist.h"
> > #include "quote.h"
> > @@ -61,6 +62,9 @@ extern bool fts_debug;
> > # define FTS_CROSS_CHECK(Fts)
> > #endif
> >
> > +/* If true, display group size info. */
> > +bool opt_group_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;
> > @@ -80,7 +84,7 @@ struct duinfo
> >
> > /* Number of inodes in directory. */
> > uintmax_t inodes;
> > -
> > + uintmax_t *group_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 +94,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_group_sizes)
> > + {
> > + for (i=0; i<65535; i++)
> > + {
> > + a->group_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 gid)
> > {
> > + uintmax_t gid_u = (uintmax_t)gid;
> > + uintmax_t gid_s;
> > a->size = size;
> > a->inodes = 1;
> > a->tmax = tmax;
> > + if (opt_group_sizes)
> > + {
> > + if (gid_u > 65534)
> > + {
> > + gid_s = 65534;
> > + }
> > + else
> > + {
> > + gid_s = gid_u;
> > + }
> > + if (gid_s >=0 && gid_s <=65534)
> > + {
> > + a->group_size[gid_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_group_sizes)
> > + {
> > + for (i=0; i<65535; i++)
> > + {
> > + sum = a->group_size[i] + b->group_size[i];
> > + a->group_size[i] = a->group_size[i] <= sum ? sum :
> UINTMAX_MAX;
> > + }
> > + }
> > if (timespec_cmp (a->tmax, b->tmax) < 0)
> > a->tmax = b->tmax;
> > }
> > @@ -226,6 +264,7 @@ static struct option const long_options[] =
> > {"exclude", required_argument, NULL, EXCLUDE_OPTION},
> > {"exclude-from", required_argument, NULL, 'X'},
> > {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
> > + {"group-reporting", no_argument, NULL, 'g'},
> > {"human-readable", no_argument, NULL, 'h'},
> > {"inodes", no_argument, NULL, INODES_OPTION},
> > {"si", no_argument, NULL, HUMAN_SI_OPTION},
> > @@ -317,6 +356,7 @@ Summarize disk usage of the set of FILEs,
> > recursively for directories.\n\
> > --files0-from=F summarize disk usage of the\n\
> > NUL-terminated file names specified in file
> F;\n\
> > if F is -, then read names from standard
> input\n\
> > + -g, --group-reporting also print group subtotals\n\
> > -H equivalent to --dereference-args (-D)\n\
> > -h, --human-readable print sizes in human readable format (e.g.,
> > 1K 234M 2G)\
> > \n\
> > @@ -411,7 +451,25 @@ print_size (const struct duinfo *pdui, const char
> *string)
> > print_only_size (opt_inodes
> > ? pdui->inodes
> > : pdui->size);
> > -
> > + if (opt_group_sizes)
> > + {
> > + uintmax_t i=0;
> > + struct group *g;
> > + printf(" Groups");
> > + for (i=0; i<65535; i++){
> > + if (pdui->group_size[i] > 0)
> > + {
> > + g = getgrgid(i);
> > + printf (",");
> > + if (g == NULL){
> > + printf (" %Ld:", (long long unsigned int)i);
> > + }else{
> > + printf(" %s:", g->gr_name);
> > + }
> > + print_only_size(pdui->group_size[i]);
> > + }
> > + }
> > + }
> > if (opt_time)
> > {
> > putchar ('\t');
> > @@ -506,6 +564,12 @@ process_file (FTS *fts, FTSENT *ent)
> > const struct stat *sb = ent->fts_statp;
> > int info = ent->fts_info;
> >
> > + if(opt_group_sizes)
> > + {
> > + dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> > + dui_to_print.group_size = xcalloc (65536, sizeof (uintmax_t));
> > + }
> > +
> > if (info == FTS_DNR)
> > {
> > /* An error occurred, but the size is known, so count it. */
> > @@ -530,7 +594,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_group_sizes)
> > + {
> > + if (dui.group_size != NULL)
> > + {
> > + free(dui.group_size);
> > + }
> > + if (dui_to_print.group_size != NULL)
> > + {
> > + free(dui_to_print.group_size);
> > + }
> > + }
> > + return false;
> > }
> >
> > /* The --one-file-system (-x) option cannot exclude anything
> > @@ -558,13 +633,34 @@ process_file (FTS *fts, FTSENT *ent)
> > FTSENT const *e = fts_read (fts);
> > assert (e == ent);
> > }
> > -
> > + if(opt_group_sizes)
> > + {
> > + if (dui.group_size != NULL)
> > + {
> > + free(dui.group_size);
> > + }
> > + if (dui_to_print.group_size != NULL)
> > + {
> > + free(dui_to_print.group_size);
> > + }
> > + }
> > return true;
> > }
> >
> > switch (info)
> > {
> > case FTS_D:
> > + if(opt_group_sizes)
> > + {
> > + if (dui.group_size != NULL)
> > + {
> > + free(dui.group_size);
> > + }
> > + if (dui_to_print.group_size != NULL)
> > + {
> > + free(dui_to_print.group_size);
> > + }
> > + }
> > return true;
> >
> > case FTS_ERR:
> > @@ -574,6 +670,17 @@ process_file (FTS *fts, FTSENT *ent)
> > break;
> >
> > case FTS_DC:
> > + if(opt_group_sizes)
> > + {
> > + if (dui.group_size != NULL)
> > + {
> > + free(dui.group_size);
> > + }
> > + if (dui_to_print.group_size != NULL)
> > + {
> > + free(dui_to_print.group_size);
> > + }
> > + }
> > /* If not following symlinks and not a (bind) mount point. */
> > if (cycle_warning_required (fts, ent)
> > && ! mount_point_in_fts_cycle (ent))
> > @@ -591,15 +698,40 @@ process_file (FTS *fts, FTSENT *ent)
> > : (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_gid);
> >
> > level = ent->fts_level;
> > - dui_to_print = dui;
> > +
> > + if (opt_group_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_gid);
> > + }
> > + else
> > + {
> > + dui_to_print = dui;
> > + }
> >
> > if (n_alloc == 0)
> > {
> > + size_t i;
> > n_alloc = level + 10;
> > dulvl = xcalloc (n_alloc, sizeof *dulvl);
> > + if(opt_group_sizes)
> > + {
> > + for (i=0; i<n_alloc; i++)
> > + {
> > + dulvl[i].ent.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> > + dulvl[i].subdir.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> > + }
> > + }
> > }
> > else
> > {
> > @@ -613,14 +745,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_group_sizes)
> > + {
> > + for (i=n_alloc; i<level*2; i++)
> > + {
> > + dulvl[i].ent.group_size = xcalloc (65536,
> > sizeof (uintmax_t));
> > + dulvl[i].subdir.group_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 +807,18 @@ process_file (FTS *fts, FTSENT *ent)
> > print_size (&dui_to_print, file);
> > }
> >
> > + if(opt_group_sizes)
> > + {
> > + if (dui.group_size != NULL)
> > + {
> > + free(dui.group_size);
> > + }
> > + if (dui_to_print.group_size != NULL)
> > + {
> > + free(dui_to_print.group_size);
> > + }
> > + }
> > +
> > return ok;
> > }
> >
> > @@ -755,7 +908,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, "0abgd:chHklmst:xB:DLPSX:",
> > long_options, &oi);
> > if (c == -1)
> > break;
> > @@ -800,6 +953,11 @@ main (int argc, char **argv)
> > output_block_size = 1;
> > break;
> >
> > + case 'g':
> > + tot_dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> > + opt_group_sizes = true;
> > + break;
> > +
> > case 'k':
> > human_output_opts = 0;
> > output_block_size = 1024;
> > --
> > 2.10.2
> >
> >
> > On Wed, Feb 7, 2018 at 8:01 AM, Daniel Gall <address@hidden>
> wrote:
> >> From 9fa842c9153dc0f68cfcf4ba25fa7f6798b4e2e4 Mon Sep 17 00:00:00 2001
> >> From: Daniel Gall <address@hidden>
> >> Date: Wed, 7 Feb 2018 02:58:52 -0500
> >> Subject: [PATCH 2/2] du: added "Groups" intro to group reporting
> >>
> >> In the event that both the group subtotal reporting feature
> >> and the users subtotal reporting feature are accepted,
> >> invokers may wish to use both features at the same time.
> >> This necessitates some delineation of user vs group reporting.
> >> ---
> >> src/du.c | 1 +
> >> 1 file changed, 1 insertion(+)
> >>
> >> diff --git a/src/du.c b/src/du.c
> >> index a8318ca..97edb5d 100644
> >> --- a/src/du.c
> >> +++ b/src/du.c
> >> @@ -455,6 +455,7 @@ print_size (const struct duinfo *pdui, const char
> *string)
> >> {
> >> uintmax_t i=0;
> >> struct group *g;
> >> + printf(" Groups");
> >> for (i=0; i<65535; i++){
> >> if (pdui->group_size[i] > 0)
> >> {
> >> --
> >> 2.10.2
> >>
> >> On Tue, Feb 6, 2018 at 10:45 PM, Daniel Gall <address@hidden>
> wrote:
> >>> I realized as I was implementing the user subtotal reporting feature
> >>> that if both the user and group reporting features are accepted then
> >>> users will be able to invoke both options and thus the reporting would
> >>> be confusing without some delineation of user vs group reporting
> >>> output. I intend to add a line to the group feature request to try to
> >>> address that.
> >>>
> >>> Dan.
> >>>
> >>> On Mon, Feb 5, 2018 at 7:32 PM, Daniel Gall <address@hidden>
> wrote:
> >>>> From c5b3dc83a762fd96c60d7560249a1815386a5efb Mon Sep 17 00:00:00
> 2001
> >>>> From: Daniel Gall <address@hidden>
> >>>> Date: Mon, 5 Feb 2018 14:30:39 -0500
> >>>> Subject: [PATCH] :Added group reporting to du
> >>>>
> >>>> ---
> >>>> NEWS | 2 +
> >>>> doc/coreutils.texi | 5 ++
> >>>> src/du.c | 175 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++---
> >>>> 3 files changed, 173 insertions(+), 9 deletions(-)
> >>>>
> >>>> diff --git a/NEWS b/NEWS
> >>>> index 8a9e09e..97ccc2c 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 -g option for group 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..d220012 100644
> >>>> --- a/doc/coreutils.texi
> >>>> +++ b/doc/coreutils.texi
> >>>> @@ -11910,6 +11910,11 @@ is at level 0, so @code{du --max-depth=0} is
> >>>> equivalent to @code{du -s}.
> >>>> @c --files0-from=FILE
> >>>> @filesZeroFromOption{du,, with the @option{--total} (@option{-c})
> option}
> >>>>
> >>>> +@item -g
> >>>> +@opindex -g
> >>>> +@cindex group reporting
> >>>> +Show group subtotals for each item reported on.
> >>>> +
> >>>> @item -H
> >>>> @opindex -H
> >>>> Equivalent to @option{--dereference-args} (@option{-D}).
> >>>> diff --git a/src/du.c b/src/du.c
> >>>> index ac4489f..a8318ca 100644
> >>>> --- a/src/du.c
> >>>> +++ b/src/du.c
> >>>> @@ -35,6 +35,7 @@
> >>>> #include "error.h"
> >>>> #include "exclude.h"
> >>>> #include "fprintftime.h"
> >>>> +#include "grp.h"
> >>>> #include "human.h"
> >>>> #include "mountlist.h"
> >>>> #include "quote.h"
> >>>> @@ -61,6 +62,9 @@ extern bool fts_debug;
> >>>> # define FTS_CROSS_CHECK(Fts)
> >>>> #endif
> >>>>
> >>>> +/* If true, display group size info. */
> >>>> +bool opt_group_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;
> >>>> @@ -80,7 +84,7 @@ struct duinfo
> >>>>
> >>>> /* Number of inodes in directory. */
> >>>> uintmax_t inodes;
> >>>> -
> >>>> + uintmax_t *group_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 +94,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_group_sizes)
> >>>> + {
> >>>> + for (i=0; i<65535; i++)
> >>>> + {
> >>>> + a->group_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 gid)
> >>>> {
> >>>> + uintmax_t gid_u = (uintmax_t)gid;
> >>>> + uintmax_t gid_s;
> >>>> a->size = size;
> >>>> a->inodes = 1;
> >>>> a->tmax = tmax;
> >>>> + if (opt_group_sizes)
> >>>> + {
> >>>> + if (gid_u > 65534)
> >>>> + {
> >>>> + gid_s = 65534;
> >>>> + }
> >>>> + else
> >>>> + {
> >>>> + gid_s = gid_u;
> >>>> + }
> >>>> + if (gid_s >=0 && gid_s <=65534)
> >>>> + {
> >>>> + a->group_size[gid_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_group_sizes)
> >>>> + {
> >>>> + for (i=0; i<65535; i++)
> >>>> + {
> >>>> + sum = a->group_size[i] + b->group_size[i];
> >>>> + a->group_size[i] = a->group_size[i] <= sum ? sum :
> UINTMAX_MAX;
> >>>> + }
> >>>> + }
> >>>> if (timespec_cmp (a->tmax, b->tmax) < 0)
> >>>> a->tmax = b->tmax;
> >>>> }
> >>>> @@ -226,6 +264,7 @@ static struct option const long_options[] =
> >>>> {"exclude", required_argument, NULL, EXCLUDE_OPTION},
> >>>> {"exclude-from", required_argument, NULL, 'X'},
> >>>> {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
> >>>> + {"group-reporting", no_argument, NULL, 'g'},
> >>>> {"human-readable", no_argument, NULL, 'h'},
> >>>> {"inodes", no_argument, NULL, INODES_OPTION},
> >>>> {"si", no_argument, NULL, HUMAN_SI_OPTION},
> >>>> @@ -317,6 +356,7 @@ Summarize disk usage of the set of FILEs,
> >>>> recursively for directories.\n\
> >>>> --files0-from=F summarize disk usage of the\n\
> >>>> NUL-terminated file names specified in
> file F;\n\
> >>>> if F is -, then read names from standard
> input\n\
> >>>> + -g, --group-reporting also print group subtotals\n\
> >>>> -H equivalent to --dereference-args (-D)\n\
> >>>> -h, --human-readable print sizes in human readable format (e.g.,
> >>>> 1K 234M 2G)\
> >>>> \n\
> >>>> @@ -411,7 +451,24 @@ print_size (const struct duinfo *pdui, const
> char *string)
> >>>> print_only_size (opt_inodes
> >>>> ? pdui->inodes
> >>>> : pdui->size);
> >>>> -
> >>>> + if (opt_group_sizes)
> >>>> + {
> >>>> + uintmax_t i=0;
> >>>> + struct group *g;
> >>>> + for (i=0; i<65535; i++){
> >>>> + if (pdui->group_size[i] > 0)
> >>>> + {
> >>>> + g = getgrgid(i);
> >>>> + printf (",");
> >>>> + if (g == NULL){
> >>>> + printf (" %Ld:", (long long unsigned int)i);
> >>>> + }else{
> >>>> + printf(" %s:", g->gr_name);
> >>>> + }
> >>>> + print_only_size(pdui->group_size[i]);
> >>>> + }
> >>>> + }
> >>>> + }
> >>>> if (opt_time)
> >>>> {
> >>>> putchar ('\t');
> >>>> @@ -506,6 +563,12 @@ process_file (FTS *fts, FTSENT *ent)
> >>>> const struct stat *sb = ent->fts_statp;
> >>>> int info = ent->fts_info;
> >>>>
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> >>>> + dui_to_print.group_size = xcalloc (65536, sizeof (uintmax_t));
> >>>> + }
> >>>> +
> >>>> if (info == FTS_DNR)
> >>>> {
> >>>> /* An error occurred, but the size is known, so count it. */
> >>>> @@ -530,7 +593,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_group_sizes)
> >>>> + {
> >>>> + if (dui.group_size != NULL)
> >>>> + {
> >>>> + free(dui.group_size);
> >>>> + }
> >>>> + if (dui_to_print.group_size != NULL)
> >>>> + {
> >>>> + free(dui_to_print.group_size);
> >>>> + }
> >>>> + }
> >>>> + return false;
> >>>> }
> >>>>
> >>>> /* The --one-file-system (-x) option cannot exclude
> anything
> >>>> @@ -558,13 +632,34 @@ process_file (FTS *fts, FTSENT *ent)
> >>>> FTSENT const *e = fts_read (fts);
> >>>> assert (e == ent);
> >>>> }
> >>>> -
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + if (dui.group_size != NULL)
> >>>> + {
> >>>> + free(dui.group_size);
> >>>> + }
> >>>> + if (dui_to_print.group_size != NULL)
> >>>> + {
> >>>> + free(dui_to_print.group_size);
> >>>> + }
> >>>> + }
> >>>> return true;
> >>>> }
> >>>>
> >>>> switch (info)
> >>>> {
> >>>> case FTS_D:
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + if (dui.group_size != NULL)
> >>>> + {
> >>>> + free(dui.group_size);
> >>>> + }
> >>>> + if (dui_to_print.group_size != NULL)
> >>>> + {
> >>>> + free(dui_to_print.group_size);
> >>>> + }
> >>>> + }
> >>>> return true;
> >>>>
> >>>> case FTS_ERR:
> >>>> @@ -574,6 +669,17 @@ process_file (FTS *fts, FTSENT *ent)
> >>>> break;
> >>>>
> >>>> case FTS_DC:
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + if (dui.group_size != NULL)
> >>>> + {
> >>>> + free(dui.group_size);
> >>>> + }
> >>>> + if (dui_to_print.group_size != NULL)
> >>>> + {
> >>>> + free(dui_to_print.group_size);
> >>>> + }
> >>>> + }
> >>>> /* If not following symlinks and not a (bind) mount
> point. */
> >>>> if (cycle_warning_required (fts, ent)
> >>>> && ! mount_point_in_fts_cycle (ent))
> >>>> @@ -591,15 +697,40 @@ process_file (FTS *fts, FTSENT *ent)
> >>>> : (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_gid);
> >>>>
> >>>> level = ent->fts_level;
> >>>> - dui_to_print = dui;
> >>>> +
> >>>> + if (opt_group_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_gid);
> >>>> + }
> >>>> + else
> >>>> + {
> >>>> + dui_to_print = dui;
> >>>> + }
> >>>>
> >>>> if (n_alloc == 0)
> >>>> {
> >>>> + size_t i;
> >>>> n_alloc = level + 10;
> >>>> dulvl = xcalloc (n_alloc, sizeof *dulvl);
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + for (i=0; i<n_alloc; i++)
> >>>> + {
> >>>> + dulvl[i].ent.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> >>>> + dulvl[i].subdir.group_size = xcalloc (65536, sizeof
> (uintmax_t));
> >>>> + }
> >>>> + }
> >>>> }
> >>>> else
> >>>> {
> >>>> @@ -613,14 +744,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_group_sizes)
> >>>> + {
> >>>> + for (i=n_alloc; i<level*2; i++)
> >>>> + {
> >>>> + dulvl[i].ent.group_size = xcalloc (65536,
> >>>> sizeof (uintmax_t));
> >>>> + dulvl[i].subdir.group_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 +806,18 @@ process_file (FTS *fts, FTSENT *ent)
> >>>> print_size (&dui_to_print, file);
> >>>> }
> >>>>
> >>>> + if(opt_group_sizes)
> >>>> + {
> >>>> + if (dui.group_size != NULL)
> >>>> + {
> >>>> + free(dui.group_size);
> >>>> + }
> >>>> + if (dui_to_print.group_size != NULL)
> >>>> + {
> >>>> + free(dui_to_print.group_size);
> >>>> + }
> >>>> + }
> >>>> +
> >>>> return ok;
> >>>> }
> >>>>
> >>>> @@ -755,7 +907,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, "0abgd:chHklmst:xB:DLPSX:",
> >>>> long_options, &oi);
> >>>> if (c == -1)
> >>>> break;
> >>>> @@ -800,6 +952,11 @@ main (int argc, char **argv)
> >>>> output_block_size = 1;
> >>>> break;
> >>>>
> >>>> + case 'g':
> >>>> + tot_dui.group_size = xcalloc (65536, sizeof (uintmax_t));
> >>>> + opt_group_sizes = true;
> >>>> + break;
> >>>> +
> >>>> case 'k':
> >>>> human_output_opts = 0;
> >>>> output_block_size = 1024;
> >>>> --
> >>>> 2.10.2
> >>>>
> >>>> On Mon, Feb 5, 2018 at 10:14 AM, Daniel Gall <address@hidden>
> wrote:
> >>>>> Thanks. Will resubmit without it.
> >>>>>
> >>>>> Sent from my iPhone
> >>>>>
> >>>>>> On Feb 5, 2018, at 9:20 AM, Eric Blake <address@hidden> wrote:
> >>>>>>
> >>>>>>> On 02/02/2018 09:27 PM, Daniel Gall wrote:
> >>>>>>> Sorry for the delay; life intervened. In addition to the feature
> add,
> >>>>>>> I found a place where du was calling xcalloc and did not check that
> >>>>>>> the returned pointer was not NULL. I added a check.
> >>>>>>
> >>>>>> Wrong; the contract of xcalloc() is that it CAN'T return NULL (it
> will
> >>>>>> have abort()ed instead, if you are low on memory).
> >>>>>>
> >>>>>>>> From 544c581654cd0dcfb363215801245a7c2dd3fcd3 Mon Sep 17
> 00:00:00 2001
> >>>>>>> From: Daniel Gall <address@hidden>
> >>>>>>> Date: Fri, 2 Feb 2018 17:18:44 -0500
> >>>>>>> Subject: [PATCH] added du group reporting feature and fixed a bug
> where du
> >>>>>>> allocated memory and did not check that the target pointer was not
> NULL after
> >>>>>>> the allocation call.
> >>>>>>
> >>>>>> Too long of a subject line; the best commits include a one-line
> summary
> >>>>>> (~60 characters or less), then a blank line, then more details.
> >>>>>>
> >>>>>>> +++ b/NEWS
> >>>>>>> @@ -32,6 +32,8 @@ GNU coreutils NEWS
> >>>>>>> -*- outline -*-
> >>>>>>> df no longer hangs when given a fifo argument.
> >>>>>>> [bug introduced in coreutils-7.3]
> >>>>>>>
> >>>>>>> + du no longer allocates memory without checking whether the
> >>>>>>> allocation call succeeded.
> >>>>>>
> >>>>>> This change is not needed, as it was not a bug in the first place.
> >>>>>>
> >>>>>> --
> >>>>>> Eric Blake, Principal Software Engineer
> >>>>>> Red Hat, Inc. +1-919-301-3266
> >>>>>> Virtualization: qemu.org | libvirt.org
> >>>>>>
>
- Re: Du feature request - group reporting,
Daniel Gall <=