du -A / -B options [Re: zfs quota question]

Max Laier max at love2party.net
Sat Nov 1 13:14:47 PDT 2008


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,                      | mlaier at freebsd.org
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | mlaier at EFnet
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News
-------------- next part --------------
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);
 }
 


More information about the freebsd-hackers mailing list