[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Du feature request - user reporting
From: |
Daniel Gall |
Subject: |
Du feature request - user reporting |
Date: |
Wed, 7 Feb 2018 06:35:05 -0500 |
>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
0001-Added-user-subtotal-repoting-to-du.patch
Description: Text Data
- Du feature request - user reporting,
Daniel Gall <=