coreutils
[Top][All Lists]
Advanced

[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, 7 Feb 2018 08:01:54 -0500

>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
>>>>

Attachment: 0002-du-added-Groups-intro-to-group-reporting.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]