bin/117944: [PATCH] add a du(1) -l option to count hardlinks multiple times

Giorgos Keramidas keramida at FreeBSD.org
Fri Nov 9 08:50:02 PST 2007


>Number:         117944
>Category:       bin
>Synopsis:       [PATCH] add a du(1) -l option to count hardlinks multiple times
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Nov 09 16:50:01 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     Giorgos Keramidas
>Release:        FreeBSD 8.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD kobe 8.0-CURRENT FreeBSD 8.0-CURRENT #0:
Sun Nov 4 06:20:54 EET 2007 build at kobe:/home/build/obj/home/build/src/sys/KOBE i386

>Description:

While testing an Ubuntu installation at home, I discovered the -l
option of du(1), which allows one to count hardlinked files multiple
times.

This was useful when trying to count the disk size of two Mercurial
repository clones, which by default use hard-links for their metadata
directories.  With our current du(1) utility, one sees:

  keramida at kobe:/home/keramida/hg/doc$ du -sk bsd/.hg el/.hg
  8312    bsd/.hg
  698     el/.hg
  keramida at kobe:/home/keramida/hg/doc$ du -sk el/.hg
  8288    el/.hg
  keramida at kobe:/home/keramida/hg/doc$

Now it's obvious that hard links in el/.hg would require that we either
run du(1) many times, or patch our du(1) utility to make the hard link
checks optional.

The Linux version of du(1) uses the -l option to turn off the hard link
checks, so I wrote from scratch a short patch to do the same.

The patch attached below is also available at:
http://people.freebsd.org/~keramida/diff/du-hardlinks-00.patch

>How-To-Repeat:
>Fix:

--- du-hardlinks-00.patch begins here ---
diff -r 2d7179484ba4 du.1
--- a/du.1	Fri Nov 09 18:17:29 2007 +0200
+++ b/du.1	Fri Nov 09 18:25:17 2007 +0200
@@ -32,7 +32,7 @@
 .\"	@(#)du.1	8.2 (Berkeley) 4/1/94
 .\" $FreeBSD: src/usr.bin/du/du.1,v 1.32 2006/09/29 15:20:44 ru Exp $
 .\"
-.Dd May 6, 2006
+.Dd November 9, 2007
 .Dt DU 1
 .Os
 .Sh NAME
@@ -43,6 +43,7 @@
 .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 n
 .Op Fl x
@@ -94,6 +95,15 @@ Display a grand total.
 Display a grand total.
 .It Fl k
 Display block counts in 1024-byte (1-Kbyte) blocks.
+.It Fl l
+If a file has multiple hard links, count its size many times.
+The default behavior of
+.Nm
+is to count files with multiple hard links only once.
+When the
+.Fl l
+option is specified, the hard link checks are disabled, and these files
+are counted (and displayed) as many times as they are found.
 .It Fl m
 Display block counts in 1048576-byte (1-Mbyte) blocks.
 .It Fl n
@@ -120,11 +130,6 @@ or
 .Fl L
 options are specified, storage used by any symbolic links which are
 followed is not counted or displayed.
-.Pp
-Files having multiple hard links are counted (and displayed) a single
-time per
-.Nm
-execution.
 .Sh ENVIRONMENT
 .Bl -tag -width BLOCKSIZE
 .It Ev BLOCKSIZE
diff -r 2d7179484ba4 du.c
--- a/du.c	Fri Nov 09 18:17:29 2007 +0200
+++ b/du.c	Fri Nov 09 18:25:17 2007 +0200
@@ -90,20 +90,22 @@ main(int argc, char *argv[])
 	int		ftsoptions;
 	int		listall;
 	int		depth;
-	int		Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, hflag, ch, notused, rval;
+	int		Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag,
+			hflag, lflag, ch, notused, rval;
 	char 		**save;
 	static char	dot[] = ".";
 
 	setlocale(LC_ALL, "");
 
-	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag = 0;
+	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag =
+	    lflag = 0;
 
 	save = argv;
 	ftsoptions = 0;
 	depth = INT_MAX;
 	SLIST_INIT(&ignores);
 
-	while ((ch = getopt(argc, argv, "HI:LPasd:chkmnrx")) != -1)
+	while ((ch = getopt(argc, argv, "HI:LPasd:chklmnrx")) != -1)
 		switch (ch) {
 			case 'H':
 				Hflag = 1;
@@ -149,6 +151,9 @@ main(int argc, char *argv[])
 				hflag = 0;
 				if (setenv("BLOCKSIZE", "1024", 1) == -1)
 					warnx("setenv: cannot set BLOCKSIZE=1024");
+				break;
+			case 'l':
+				lflag = 1;
 				break;
 			case 'm':
 				hflag = 0;
@@ -261,7 +266,7 @@ main(int argc, char *argv[])
 				if (ignorep(p))
 					break;
 
-				if (p->fts_statp->st_nlink > 1 && linkchk(p))
+				if (lflag == 0 && p->fts_statp->st_nlink > 1 && linkchk(p))
 					break;
 
 				if (listall || p->fts_level == 0) {
@@ -447,7 +452,8 @@ usage(void)
 usage(void)
 {
 	(void)fprintf(stderr,
-		"usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k | -m] [-n] [-x] [-I mask] [file ...]\n");
+		"usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] "
+		"[-l] [-h | -k | -m] [-n] [-x] [-I mask] [file ...]\n");
 	exit(EX_USAGE);
 }
 
--- du-hardlinks-00.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list