[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: |
Wed, 28 Feb 2018 01:05:56 -0500 |
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
>>>>>>
0001-du-Added-group-reporting-feature.patch
Description: Text Data