bin/74567: [patch] [2TB] du doesn't handle sizes >1TB

Sergey Salnikov serg at citforum.ru
Tue Nov 30 15:10:13 PST 2004


>Number:         74567
>Category:       bin
>Synopsis:       [patch] [2TB] du doesn't handle sizes >1TB
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 30 23:10:12 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Sergey Salnikov <serg at citforum.ru>
>Release:        FreeBSD 5.3-RELEASE i386
>Organization:
CITForum
>Environment:
System: FreeBSD ftp.citkit.ru 5.3-RELEASE FreeBSD 5.3-RELEASE #0: Sun Nov 21 02:43:28 MSK 2004 serg@:/usr/obj/usr/src/sys/CITKIT i386
>Description:
	There is an integer overflow in du when running it on a 
	directory larger than 1TB.
>How-To-Repeat:
	Run du on any >1TB directory on a 32-bit machine.
	It reports wrong size.
>Fix:
	Here goes the patch. Modified du allocates an int64_t for
	every subdirectory and stores the size there and not in
	fts_number.
	
	Maybe fts_number just has to be 64-bit? It will make
	things faster (no need for extra malloc), but
	involves hacking libc.

--- du-2TB-patch begins here ---
--- du.c.orig	Wed Jul 28 20:03:12 2004
+++ du.c	Wed Dec  1 00:20:29 2004
@@ -82,7 +82,8 @@
 {
 	FTS		*fts;
 	FTSENT		*p;
-	long		blocksize, savednumber = 0;
+	long		blocksize;
+	int64_t		savednumber = 0;
 	int		ftsoptions;
 	int		listall;
 	int		depth;
@@ -219,24 +220,31 @@
 			case FTS_D:			/* Ignore. */
 				if (ignorep(p))
 					fts_set(fts, p, FTS_SKIP);
+				else {
+					if ((!p->fts_parent->fts_pointer
+					     && !(p->fts_parent->fts_pointer = calloc(1, sizeof(int64_t))))
+					    || !(p->fts_pointer = calloc(1, sizeof(int64_t))))
+						err(1, "calloc");
+				}
 				break;
 			case FTS_DP:
 				if (ignorep(p))
 					break;
 
-				p->fts_parent->fts_number +=
-				    p->fts_number += p->fts_statp->st_blocks;
+				*(int64_t *)p->fts_parent->fts_pointer +=
+				    *(int64_t *)p->fts_pointer += p->fts_statp->st_blocks;
 
 				if (p->fts_level <= depth) {
 					if (hflag) {
-						(void) prthumanval(howmany(p->fts_number, blocksize));
+						(void) prthumanval(howmany(*(int64_t *)p->fts_pointer, blocksize));
 						(void) printf("\t%s\n", p->fts_path);
 					} else {
-					(void) printf("%ld\t%s\n",
-					    howmany(p->fts_number, blocksize),
+					(void) printf("%lld\t%s\n",
+					    howmany(*(int64_t *)p->fts_pointer, blocksize),
 					    p->fts_path);
 					}
 				}
+				free(p->fts_pointer);
 				break;
 			case FTS_DC:			/* Ignore. */
 				break;
@@ -265,9 +273,9 @@
 					}
 				}
 
-				p->fts_parent->fts_number += p->fts_statp->st_blocks;
+				*(int64_t *)p->fts_parent->fts_pointer += p->fts_statp->st_blocks;
 		}
-		savednumber = p->fts_parent->fts_number;
+		savednumber = *(int64_t *)p->fts_parent->fts_pointer;
 	}
 
 	if (errno)
@@ -278,7 +286,7 @@
 			(void) prthumanval(howmany(savednumber, blocksize));
 			(void) printf("\ttotal\n");
 		} else {
-			(void) printf("%ld\ttotal\n", howmany(savednumber, blocksize));
+			(void) printf("%lld\ttotal\n", howmany(savednumber, blocksize));
 		}
 	}
 
--- du-2TB-patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list