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