coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Du feature request - user reporting


From: Daniel Gall
Subject: Re: Du feature request - user reporting
Date: Wed, 7 Feb 2018 06:54:12 -0500

And I had to clarify a variable name to enable trivial integration of
the group subtotal reporting feature requested in other
correspondence.

Also, this feature (user subtotal reporting) will be really useful for
quickly getting at which users are the primary space hogs in large
shared directories.  An admin doesn't care if a user has 10,000 files
of 4KiB each.  An admin definitely does care if another user's 3 files
consume several GiB.  Especially in /tmp.  Also in large shared
directories in fast scratch file systems like lustre or GPFS.

>From 9c728a4cde1d023131a5a675b878de3a05dec920 Mon Sep 17 00:00:00 2001
From: Daniel Gall <address@hidden>
Date: Wed, 7 Feb 2018 01:48:13 -0500
Subject: [PATCH 2/2] du: clarified a variable name

The user subtotal reporting feature should integrate trivially
with the group subtotal reporting feature described in other
correspondence.  Thus I changed a variable name for clarity in
reading.  passwd *g is now passwd *u.
---
 src/du.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/du.c b/src/du.c
index a1d06d5..53349c2 100644
--- a/src/du.c
+++ b/src/du.c
@@ -457,17 +457,17 @@ print_size (const struct duinfo *pdui, const char *string)
   if (opt_user_sizes)
     {
       uintmax_t i=0;
-      struct passwd *g;
-      printf(" Users");
+      struct passwd *u;
+      printf(" Groups");
       for (i=0; i<65535; i++){
         if (pdui->user_size[i] > 0)
           {
-            g = getpwuid(i);
+            u = getpwuid(i);
             printf (",");
-            if (g == NULL){
+            if (u == NULL){
               printf (" %Ld:", (long long unsigned int)i);
             }else{
-              printf(" %s:", g->pw_name);
+              printf(" %s:", u->pw_name);
             }
             print_only_size(pdui->user_size[i]);
           }
-- 
2.10.2


On Wed, Feb 7, 2018 at 6:35 AM, Daniel Gall <address@hidden> wrote:
> From d57cf221746eadf87e612f8d4596cbed91f4860d Mon Sep 17 00:00:00 2001
> From: Daniel Gall <address@hidden>
> Date: Wed, 7 Feb 2018 01:27:43 -0500
> Subject: [PATCH] :Added user subtotal repoting to du
>
> ---
>  NEWS               |   2 +
>  doc/coreutils.texi |   5 ++
>  src/du.c           | 179 
> ++++++++++++++++++++++++++++++++++++++++++++++++++---
>  3 files changed, 176 insertions(+), 10 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 8a9e09e..6192b07 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -56,6 +56,8 @@ GNU coreutils NEWS
>  -*- outline -*-
>
>    timeout now supports the --verbose option to diagnose forced termination.
>
> +  du now supports the -u option for user reporting
> +
>  ** Improvements
>
>    dd now supports iflag=direct with arbitrary sized files on all file 
> systems.
> diff --git a/doc/coreutils.texi b/doc/coreutils.texi
> index cdde136..fb61345 100644
> --- a/doc/coreutils.texi
> +++ b/doc/coreutils.texi
> @@ -12100,6 +12100,11 @@ the newline and any later characters are
> ignored; if @env{TIME_STYLE}
>  begins with @samp{posix-} the @samp{posix-} is ignored; and if
>  @env{TIME_STYLE} is @samp{locale} it is ignored.
>
> +@item -u
> +@opindex -u
> +@cindex user reporting
> +Show user subtotals for each item reported on.
> +
>  @item -X @var{file}
>  @itemx --exclude-from=@var{file}
>  @opindex -X @var{file}
> diff --git a/src/du.c b/src/du.c
> index ac4489f..a1d06d5 100644
> --- a/src/du.c
> +++ b/src/du.c
> @@ -37,6 +37,7 @@
>  #include "fprintftime.h"
>  #include "human.h"
>  #include "mountlist.h"
> +#include "pwd.h"
>  #include "quote.h"
>  #include "stat-size.h"
>  #include "stat-time.h"
> @@ -61,6 +62,9 @@ extern bool fts_debug;
>  # define FTS_CROSS_CHECK(Fts)
>  #endif
>
> +/* If true, display user size info. */
> +bool opt_user_sizes = false;
> +
>  /* A set of dev/ino pairs to help identify files and directories
>     whose sizes have already been counted.  */
>  static struct di_set *di_files;
> @@ -81,6 +85,9 @@ struct duinfo
>    /* Number of inodes in directory.  */
>    uintmax_t inodes;
>
> +  /* Pointer to array of uid indexed size subtotals. */
> +  uintmax_t *user_size;
> +
>    /* Latest timestamp found.  If tmax.tv_sec == TYPE_MINIMUM (time_t)
>       && tmax.tv_nsec < 0, no timestamp has been found.  */
>    struct timespec tmax;
> @@ -90,28 +97,62 @@ struct duinfo
>  static inline void
>  duinfo_init (struct duinfo *a)
>  {
> +  uintmax_t i = 0;
>    a->size = 0;
>    a->inodes = 0;
>    a->tmax.tv_sec = TYPE_MINIMUM (time_t);
>    a->tmax.tv_nsec = -1;
> +  if (opt_user_sizes)
> +    {
> +      for (i=0; i<65535; i++)
> +        {
> +      a->user_size[i] = 0;
> +    }
> +    }
>  }
>
>  /* Set directory data.  */
>  static inline void
> -duinfo_set (struct duinfo *a, uintmax_t size, struct timespec tmax)
> +duinfo_set (struct duinfo *a, uintmax_t size, struct timespec tmax,
> uintmax_t uid)
>  {
> +  uintmax_t uid_u = (uintmax_t)uid;
> +  uintmax_t uid_s;
>    a->size = size;
>    a->inodes = 1;
>    a->tmax = tmax;
> +  if (opt_user_sizes)
> +    {
> +      if (uid_u > 65534)
> +        {
> +      uid_s = 65534;
> +    }
> +      else
> +        {
> +      uid_s = uid_u;
> +    }
> +      if (uid_s >=0 && uid_s <=65534)
> +        {
> +      a->user_size[uid_s] = size;
> +    }
> +    }
>  }
>
>  /* Accumulate directory data.  */
>  static inline void
>  duinfo_add (struct duinfo *a, struct duinfo const *b)
>  {
> +  uintmax_t i = 0;
>    uintmax_t sum = a->size + b->size;
>    a->size = a->size <= sum ? sum : UINTMAX_MAX;
>    a->inodes = a->inodes + b->inodes;
> +  if (opt_user_sizes)
> +    {
> +      for (i=0; i<65535; i++)
> +        {
> +          sum = a->user_size[i] + b->user_size[i];
> +          a->user_size[i] = a->user_size[i] <= sum ? sum : UINTMAX_MAX;
> +        }
> +    }
>    if (timespec_cmp (a->tmax, b->tmax) < 0)
>      a->tmax = b->tmax;
>  }
> @@ -239,6 +280,7 @@ static struct option const long_options[] =
>    {"threshold", required_argument, NULL, 't'},
>    {"time", optional_argument, NULL, TIME_OPTION},
>    {"time-style", required_argument, NULL, TIME_STYLE_OPTION},
> +  {"user-reporting", no_argument, NULL, 'u'},
>    {GETOPT_HELP_OPTION_DECL},
>    {GETOPT_VERSION_OPTION_DECL},
>    {NULL, 0, NULL, 0}
> @@ -346,6 +388,7 @@ Summarize disk usage of the set of FILEs,
> recursively for directories.\n\
>                              FORMAT is interpreted like in 'date'\n\
>  "), stdout);
>        fputs (_("\
> +  -u, --user-reporting also print user subtotals\n\
>    -X, --exclude-from=FILE  exclude files that match any pattern in FILE\n\
>        --exclude=PATTERN    exclude files that match PATTERN\n\
>    -x, --one-file-system    skip directories on different file systems\n\
> @@ -411,7 +454,25 @@ print_size (const struct duinfo *pdui, const char 
> *string)
>    print_only_size (opt_inodes
>                     ? pdui->inodes
>                     : pdui->size);
> -
> +  if (opt_user_sizes)
> +    {
> +      uintmax_t i=0;
> +      struct passwd *g;
> +      printf(" Users");
> +      for (i=0; i<65535; i++){
> +        if (pdui->user_size[i] > 0)
> +          {
> +            g = getpwuid(i);
> +            printf (",");
> +            if (g == NULL){
> +              printf (" %Ld:", (long long unsigned int)i);
> +            }else{
> +              printf(" %s:", g->pw_name);
> +            }
> +            print_only_size(pdui->user_size[i]);
> +          }
> +      }
> +    }
>    if (opt_time)
>      {
>        putchar ('\t');
> @@ -506,6 +567,12 @@ process_file (FTS *fts, FTSENT *ent)
>    const struct stat *sb = ent->fts_statp;
>    int info = ent->fts_info;
>
> +  if(opt_user_sizes)
> +    {
> +      dui.user_size = xcalloc (65536, sizeof (uintmax_t));
> +      dui_to_print.user_size = xcalloc (65536, sizeof (uintmax_t));
> +    }
> +
>    if (info == FTS_DNR)
>      {
>        /* An error occurred, but the size is known, so count it.  */
> @@ -530,7 +597,18 @@ process_file (FTS *fts, FTSENT *ent)
>            if (info == FTS_NS || info == FTS_SLNONE)
>              {
>                error (0, ent->fts_errno, _("cannot access %s"), quoteaf 
> (file));
> -              return false;
> +              if(opt_user_sizes)
> +                {
> +                  if (dui.user_size != NULL)
> +                    {
> +                      free(dui.user_size);
> +                    }
> +                  if (dui_to_print.user_size != NULL)
> +                    {
> +                      free(dui_to_print.user_size);
> +                    }
> +                }
> +          return false;
>              }
>
>            /* The --one-file-system (-x) option cannot exclude anything
> @@ -558,13 +636,34 @@ process_file (FTS *fts, FTSENT *ent)
>                FTSENT const *e = fts_read (fts);
>                assert (e == ent);
>              }
> -
> +          if(opt_user_sizes)
> +            {
> +              if (dui.user_size != NULL)
> +                {
> +                  free(dui.user_size);
> +                }
> +              if (dui_to_print.user_size != NULL)
> +                {
> +                  free(dui_to_print.user_size);
> +                }
> +            }
>            return true;
>          }
>
>        switch (info)
>          {
>          case FTS_D:
> +      if(opt_user_sizes)
> +            {
> +              if (dui.user_size != NULL)
> +                {
> +                  free(dui.user_size);
> +                }
> +              if (dui_to_print.user_size != NULL)
> +                {
> +                  free(dui_to_print.user_size);
> +                }
> +            }
>            return true;
>
>          case FTS_ERR:
> @@ -574,6 +673,17 @@ process_file (FTS *fts, FTSENT *ent)
>            break;
>
>          case FTS_DC:
> +      if(opt_user_sizes)
> +            {
> +              if (dui.user_size != NULL)
> +                {
> +                  free(dui.user_size);
> +                }
> +              if (dui_to_print.user_size != NULL)
> +                {
> +                  free(dui_to_print.user_size);
> +                }
> +            }
>            /* If not following symlinks and not a (bind) mount point.  */
>            if (cycle_warning_required (fts, ent)
>                && ! mount_point_in_fts_cycle (ent))
> @@ -584,22 +694,46 @@ process_file (FTS *fts, FTSENT *ent)
>            return true;
>          }
>      }
> -
>    duinfo_set (&dui,
>                (apparent_size
>                 ? MAX (0, sb->st_size)
>                 : (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE),
>                (time_type == time_mtime ? get_stat_mtime (sb)
>                 : time_type == time_atime ? get_stat_atime (sb)
> -               : get_stat_ctime (sb)));
> +               : get_stat_ctime (sb)),
> +           sb->st_uid);
>
>    level = ent->fts_level;
> -  dui_to_print = dui;
> +
> +  if (opt_user_sizes)
> +    {
> +      duinfo_set (&dui_to_print,
> +              (apparent_size
> +               ? MAX (0, sb->st_size)
> +               : (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE),
> +              (time_type == time_mtime ? get_stat_mtime (sb)
> +               : time_type == time_atime ? get_stat_atime (sb)
> +               : get_stat_ctime (sb)),
> +               sb->st_uid);
> +    }
> +  else
> +    {
> +      dui_to_print = dui;
> +    }
>
>    if (n_alloc == 0)
>      {
> +      size_t i;
>        n_alloc = level + 10;
>        dulvl = xcalloc (n_alloc, sizeof *dulvl);
> +      if(opt_user_sizes)
> +        {
> +          for (i=0; i<n_alloc; i++)
> +            {
> +              dulvl[i].ent.user_size = xcalloc (65536, sizeof (uintmax_t));
> +              dulvl[i].subdir.user_size = xcalloc (65536, sizeof 
> (uintmax_t));
> +            }
> +        }
>      }
>    else
>      {
> @@ -613,14 +747,23 @@ process_file (FTS *fts, FTSENT *ent)
>               Clear the accumulators for *all* levels between prev_level
>               and the current one.  The depth may change dramatically,
>               e.g., from 1 to 10.  */
> +          size_t i;
>
>            if (n_alloc <= level)
>              {
>                dulvl = xnrealloc (dulvl, level, 2 * sizeof *dulvl);
> +              if(opt_user_sizes)
> +                {
> +                  for (i=n_alloc; i<level*2; i++)
> +                    {
> +                      dulvl[i].ent.user_size = xcalloc (65536, sizeof
> (uintmax_t));
> +                      dulvl[i].subdir.user_size = xcalloc (65536,
> sizeof (uintmax_t));
> +                    }
> +                }
>                n_alloc = level * 2;
>              }
>
> -          for (size_t i = prev_level + 1; i <= level; i++)
> +          for (i = prev_level + 1; i <= level; i++)
>              {
>                duinfo_init (&dulvl[i].ent);
>                duinfo_init (&dulvl[i].subdir);
> @@ -666,6 +809,18 @@ process_file (FTS *fts, FTSENT *ent)
>          print_size (&dui_to_print, file);
>      }
>
> +  if(opt_user_sizes)
> +    {
> +      if (dui.user_size != NULL)
> +        {
> +          free(dui.user_size);
> +        }
> +      if (dui_to_print.user_size != NULL)
> +        {
> +          free(dui_to_print.user_size);
> +        }
> +    }
> +
>    return ok;
>  }
>
> @@ -678,7 +833,6 @@ static bool
>  du_files (char **files, int bit_flags)
>  {
>    bool ok = true;
> -
>    if (*files)
>      {
>        FTS *fts = xfts_open (files, bit_flags, NULL);
> @@ -755,7 +909,7 @@ main (int argc, char **argv)
>    while (true)
>      {
>        int oi = -1;
> -      int c = getopt_long (argc, argv, "0abd:chHklmst:xB:DLPSX:",
> +      int c = getopt_long (argc, argv, "0abd:chHklmst:uxB:DLPSX:",
>                             long_options, &oi);
>        if (c == -1)
>          break;
> @@ -850,6 +1004,11 @@ main (int argc, char **argv)
>            }
>            break;
>
> +        case 'u':
> +          tot_dui.user_size = xcalloc (65536, sizeof (uintmax_t));
> +          opt_user_sizes = true;
> +          break;
> +
>          case 'x':
>            bit_flags |= FTS_XDEV;
>            break;
> --
> 2.10.2

Attachment: 0002-du-clarified-a-variable-name.patch
Description: Text Data


reply via email to

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