Skip to content
Snippets Groups Projects
Commit ad84603b authored by Yorhel's avatar Yorhel
Browse files

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.
parent 2bc1b3e4
No related branches found
No related tags found
No related merge requests found
...@@ -276,6 +276,10 @@ links, and will thus be scanned and counted multiple times. ...@@ -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
......
...@@ -84,8 +84,8 @@ static void hlink_check(struct dir *d) { ...@@ -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);
} }
} }
} }
......
...@@ -29,6 +29,7 @@ ...@@ -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>
......
...@@ -287,8 +287,8 @@ struct dir *getroot(struct dir *d) { ...@@ -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;
} }
......
...@@ -81,6 +81,12 @@ char *getpath(struct dir *); ...@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment