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

Attachment: 0001-du-Added-group-reporting-feature.patch
Description: Text Data


reply via email to

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