Hi,

a thread on freebsd-stable@ [1] about problems with du(1) and compressed zfs 
filesystems got me looking for a possible solution.  Attached is a diff for 
du(1) that adds two new options:

 -A to display the apparent size of the file instead of the used blocks.
 -B bsize to specify a custom blocksize.  In particular one <512byte

The GNU du(1) has --apparent-size for -A, but we don't like long options.  
That's not to say that it couldn't be added for script compat. -B is probably 
not that interesting, but it can be helpful and came for free.

Any objections against the general concept?  It's rather complicated to get 
the apparent size of a directory hierarchy without scripting.  I often wonder 
if some hierarchy will fit on a CD/DVD and compressed zfs makes this really 
difficult.

As for the code, I know that there are a couple of style(9) errors in there - 
mostly because the lines already exceeded 80 chars before my changes and I 
plan to clean that up before I commit - should there be enough support for the 
change itself.

Thoughts?

[1] http://lists.freebsd.org/pipermail/freebsd-stable/2008-October/045698.html

-- 
/"\  Best regards,                      | [EMAIL PROTECTED]
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | [EMAIL PROTECTED]
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News
Index: du.1
===================================================================
--- du.1        (revision 184513)
+++ du.1        (working copy)
@@ -40,11 +40,12 @@
 .Nd display disk usage statistics
 .Sh SYNOPSIS
 .Nm
+.Op Fl A
 .Op Fl H | L | P
 .Op Fl a | s | d Ar depth
 .Op Fl c
 .Op Fl l
-.Op Fl h | k | m
+.Op Fl h | k | m | B Ar blocksize
 .Op Fl n
 .Op Fl x
 .Op Fl I Ar mask
@@ -60,6 +61,14 @@
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl A
+Display the apparent size instead of the diskusage.
+This can be helpful to find sparse files and when operating on
+compressed volumes.
+.It Fl B Ar blocksize
+Display block counts in
+.Ar blocksize
+byte blocks.
 .It Fl H
 Symbolic links on the command line are followed, symbolic links in file
 hierarchies are not followed.
@@ -136,14 +145,14 @@
 If the environment variable
 .Ev BLOCKSIZE
 is set, and the
-.Fl k
-option is not specified, the block counts will be displayed in units of that
+.Fl k, m, h, B
+options are not specified, the block counts will be displayed in units of that
 size block.
 If
 .Ev BLOCKSIZE
 is not set, and the
-.Fl k
-option is not specified, the block counts will be displayed in 512-byte blocks.
+.Fl k, m, h, B
+options are not specified, the block counts will be displayed in 512-byte 
blocks.
 .El
 .Sh SEE ALSO
 .Xr df 1 ,
Index: du.c
===================================================================
--- du.c        (revision 184513)
+++ du.c        (working copy)
@@ -86,27 +86,39 @@
        FTS             *fts;
        FTSENT          *p;
        off_t           savednumber = 0;
-       long            blocksize;
+       long            blocksize = 0;
        int             ftsoptions;
        int             listall;
        int             depth;
        int             Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag;
-       int             hflag, lflag, ch, notused, rval;
+       int             Aflag, hflag, lflag, ch, notused, rval;
        char            **save;
        static char     dot[] = ".";
 
        setlocale(LC_ALL, "");
 
        Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag =
-           lflag = 0;
+           Aflag = lflag = 0;
 
        save = argv;
        ftsoptions = 0;
        depth = INT_MAX;
        SLIST_INIT(&ignores);
 
-       while ((ch = getopt(argc, argv, "HI:LPasd:chklmnrx")) != -1)
+       while ((ch = getopt(argc, argv, "AB:HI:LPasd:chklmnrx")) != -1)
                switch (ch) {
+                       case 'A':
+                               Aflag = 1;
+                               if (blocksize == 0)
+                                       blocksize = 1;
+                               break;
+                       case 'B':
+                               blocksize = atoi(optarg);
+                               if (errno == ERANGE || blocksize < 0) {
+                                       warnx("invalid argument to option B: 
%s", optarg);
+                                       usage();
+                               }
+                               break;
                        case 'H':
                                Hflag = 1;
                                break;
@@ -142,23 +154,18 @@
                                cflag = 1;
                                break;
                        case 'h':
-                               if (setenv("BLOCKSIZE", "512", 1) == -1)
-                                       warn(
-                                           "setenv: cannot set BLOCKSIZE=512");
                                hflag = 1;
                                break;
                        case 'k':
                                hflag = 0;
-                               if (setenv("BLOCKSIZE", "1024", 1) == -1)
-                                       warn("setenv: cannot set 
BLOCKSIZE=1024");
+                               blocksize = 1024;
                                break;
                        case 'l':
                                lflag = 1;
                                break;
                        case 'm':
                                hflag = 0;
-                               if (setenv("BLOCKSIZE", "1048576", 1) == -1)
-                                       warn("setenv: cannot set 
BLOCKSIZE=1048576");
+                               blocksize = 1048576;
                                break;
                        case 'n':
                                nodumpflag = 1;
@@ -222,8 +229,8 @@
                argv[1] = NULL;
        }
 
-       (void) getbsize(&notused, &blocksize);
-       blocksize /= 512;
+       if (blocksize == 0)
+               (void) getbsize(&notused, &blocksize);
 
        rval = 0;
 
@@ -241,15 +248,21 @@
                                        break;
 
                                p->fts_parent->fts_bignum +=
-                                   p->fts_bignum += p->fts_statp->st_blocks;
+                                   p->fts_bignum += Aflag ?
+                                   p->fts_statp->st_size :
+                                   p->fts_statp->st_blocks;
 
                                if (p->fts_level <= depth) {
                                        if (hflag) {
-                                               (void) 
prthumanval(howmany(p->fts_bignum, blocksize));
+                                               (void) prthumanval(Aflag ?
+                                                   p->fts_bignum :
+                                                   p->fts_bignum * DEV_BSIZE);
                                                (void) printf("\t%s\n", 
p->fts_path);
                                        } else {
                                        (void) printf("%jd\t%s\n",
-                                           (intmax_t)howmany(p->fts_bignum, 
blocksize),
+                                           (intmax_t)howmany(Aflag ?
+                                           p->fts_bignum :
+                                           p->fts_bignum * DEV_BSIZE, 
blocksize),
                                            p->fts_path);
                                        }
                                }
@@ -272,17 +285,23 @@
 
                                if (listall || p->fts_level == 0) {
                                        if (hflag) {
-                                               (void) 
prthumanval(howmany(p->fts_statp->st_blocks,
-                                                       blocksize));
+                                               (void) prthumanval(Aflag ?
+                                                   p->fts_statp->st_size :
+                                                   p->fts_statp->st_blocks * 
DEV_BSIZE);
                                                (void) printf("\t%s\n", 
p->fts_path);
                                        } else {
                                                (void) printf("%jd\t%s\n",
-                                                       
(intmax_t)howmany(p->fts_statp->st_blocks, blocksize),
-                                                       p->fts_path);
+                                                   (intmax_t)howmany( Aflag ?
+                                                   p->fts_statp->st_size :
+                                                   p->fts_statp->st_blocks *
+                                                   DEV_BSIZE, blocksize),
+                                                   p->fts_path);
                                        }
                                }
 
-                               p->fts_parent->fts_bignum += 
p->fts_statp->st_blocks;
+                               p->fts_parent->fts_bignum += Aflag ? 
+                                   p->fts_statp->st_size :
+                                   p->fts_statp->st_blocks;
                }
                savednumber = p->fts_parent->fts_bignum;
        }
@@ -441,8 +460,6 @@
 {
        char buf[5];
 
-       bytes *= DEV_BSIZE;
-
        humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE,
            HN_B | HN_NOSPACE | HN_DECIMAL);
 
@@ -453,8 +470,9 @@
 usage(void)
 {
        (void)fprintf(stderr,
-               "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] "
-               "[-l] [-h | -k | -m] [-n] [-x] [-I mask] [file ...]\n");
+               "usage: du [-A] [-H | -L | -P] [-a | -s | -d depth] [-c] "
+               "[-l] [-h | -k | -m | -B bsize] [-n] [-x] [-I mask] "
+               "[file ...]\n");
        exit(EX_USAGE);
 }
 
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to