Clip directory sizes to fit in a signed 64bit integer

This mostly avoids the issue of getting negative sizes. It's still
possible to get a negative size after refresh or deletion, I'll get to
that in a bit.
This commit is contained in:
Yorhel 2012-11-22 13:33:32 +01:00
parent 2bc1b3e479
commit ad84603bee
5 changed files with 15 additions and 4 deletions

View file

@ -276,6 +276,10 @@ links, and will thus be scanned and counted multiple times.
Some minor glitches may appear when displaying filenames that contain multibyte Some minor glitches may appear when displaying filenames that contain multibyte
or multicolumn characters. or multicolumn characters.
All sizes are internally represented as a signed 64bit integer. If you have a
directory larger than 8 EiB minus one byte, ncdu will clip its size to 8 EiB
minus one byte.
Please report any other bugs you may find at the bug tracker, which can be Please report any other bugs you may find at the bug tracker, which can be
found on the web site at http://dev.yorhel.nl/ncdu found on the web site at http://dev.yorhel.nl/ncdu

View file

@ -84,8 +84,8 @@ static void hlink_check(struct dir *d) {
if(pt==par) if(pt==par)
i=0; i=0;
if(i) { if(i) {
par->size += d->size; par->size = adds64(par->size, d->size);
par->asize += d->asize; par->asize = adds64(par->size, d->asize);
} }
} }
} }

View file

@ -29,6 +29,7 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>

View file

@ -287,8 +287,8 @@ struct dir *getroot(struct dir *d) {
void addparentstats(struct dir *d, int64_t size, int64_t asize, int items) { void addparentstats(struct dir *d, int64_t size, int64_t asize, int items) {
while(d) { while(d) {
d->size += size; d->size = adds64(d->size, size);
d->asize += asize; d->asize = adds64(d->asize, asize);
d->items += items; d->items += items;
d = d->parent; d = d->parent;
} }

View file

@ -81,6 +81,12 @@ char *getpath(struct dir *);
/* returns the root element of the given dir struct */ /* returns the root element of the given dir struct */
struct dir *getroot(struct dir *); struct dir *getroot(struct dir *);
/* Add two positive signed 64-bit integers. Returns INT64_MAX if the result
* would overflow.
* I use uint64_t's to detect the overflow, as (a + b < 0) relies on undefined
* behaviour, and (INT64_MAX - b >= a) didn't work for some reason. */
#define adds64(a, b) ((uint64_t)(a) + (uint64_t)(b) > (uint64_t)INT64_MAX ? INT64_MAX : (a)+(b))
/* Adds a value to the size, asize and items fields of *d and its parents */ /* Adds a value to the size, asize and items fields of *d and its parents */
void addparentstats(struct dir *, int64_t, int64_t, int); void addparentstats(struct dir *, int64_t, int64_t, int);