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 08:01:22 -0500

>From f91dc617c5966edeba9f5c643e8be49ed106ffcc Mon Sep 17 00:00:00 2001
From: Daniel Gall <address@hidden>
Date: Wed, 7 Feb 2018 01:57:26 -0500
Subject: [PATCH 3/3] du: fixed typo from last commit

We want user subtotals to be prefaced by "Users" rather than
"Groups".
---
 src/du.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/du.c b/src/du.c
index 53349c2..f0eafa9 100644
--- a/src/du.c
+++ b/src/du.c
@@ -458,7 +458,7 @@ print_size (const struct duinfo *pdui, const char *string)
     {
       uintmax_t i=0;
       struct passwd *u;
-      printf(" Groups");
+      printf(" Users");
       for (i=0; i<65535; i++){
         if (pdui->user_size[i] > 0)
           {
-- 
2.10.2


On Wed, Feb 7, 2018 at 6:55 AM, Daniel Gall <address@hidden> wrote:
> Sigh I am new at git.  Will have to fix that printf (" Groups"); back to 
> Users.
>
> On Wed, Feb 7, 2018 at 6:54 AM, Daniel Gall <address@hidden> wrote:
>> 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: 0003-du-fixed-typo-from-last-commit.patch
Description: Text Data


reply via email to

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