mirror of
https://code.blicky.net/yorhel/ncdu.git
synced 2026-01-13 01:08:41 -09:00
Implemented hardlink detection
This commit is contained in:
parent
188265c594
commit
757bdff7ed
1 changed files with 47 additions and 9 deletions
50
src/calc.c
50
src/calc.c
|
|
@ -53,7 +53,12 @@ struct dir *root; /* root directory struct we're calculating */
|
||||||
struct dir *orig; /* original directory, when recalculating */
|
struct dir *orig; /* original directory, when recalculating */
|
||||||
dev_t curdev; /* current device we're calculating on */
|
dev_t curdev; /* current device we're calculating on */
|
||||||
int anpos; /* position of the animation string */
|
int anpos; /* position of the animation string */
|
||||||
int curpathl = 0, lasterrl = 0;
|
struct link_inode { /* list of all non-dirs with nlink > 1 */
|
||||||
|
dev_t dev;
|
||||||
|
ino_t ino;
|
||||||
|
} *links = NULL;
|
||||||
|
int curpathl = 0, lasterrl = 0, linksl = 0, linkst = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* adds name to curpath */
|
/* adds name to curpath */
|
||||||
|
|
@ -86,6 +91,7 @@ void calc_leavepath() {
|
||||||
int calc_item(struct dir *par, char *name) {
|
int calc_item(struct dir *par, char *name) {
|
||||||
struct dir *t, *d;
|
struct dir *t, *d;
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
|
int i;
|
||||||
|
|
||||||
if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -130,6 +136,31 @@ int calc_item(struct dir *par, char *name) {
|
||||||
for(t=d->parent; t!=NULL; t=t->parent)
|
for(t=d->parent; t!=NULL; t=t->parent)
|
||||||
t->items++;
|
t->items++;
|
||||||
|
|
||||||
|
/* check for hard links.
|
||||||
|
An item is only considered a hard link if it's not a directory,
|
||||||
|
has st_nlink > 1, and is already present in the links array */
|
||||||
|
if(!S_ISDIR(fs.st_mode) && fs.st_nlink > 1) {
|
||||||
|
for(i=0; i<linkst; i++)
|
||||||
|
if(links[i].dev == fs.st_dev && links[i].ino == fs.st_ino)
|
||||||
|
break;
|
||||||
|
/* found in the list, set size = 0 */
|
||||||
|
if(i != linkst)
|
||||||
|
fs.st_blocks = fs.st_size = 0;
|
||||||
|
/* not found, add to the list */
|
||||||
|
else {
|
||||||
|
if(++linkst > linksl) {
|
||||||
|
linksl *= 2;
|
||||||
|
if(!linksl) {
|
||||||
|
linksl = 64;
|
||||||
|
links = malloc(linksl);
|
||||||
|
} else
|
||||||
|
links = realloc(links, linksl);
|
||||||
|
}
|
||||||
|
links[i].dev = fs.st_dev;
|
||||||
|
links[i].ino = fs.st_ino;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* count the size */
|
/* count the size */
|
||||||
if(!(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
|
if(!(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
|
||||||
d->size = fs.st_blocks * S_BLKSIZE;
|
d->size = fs.st_blocks * S_BLKSIZE;
|
||||||
|
|
@ -297,6 +328,7 @@ void calc_process() {
|
||||||
char *path, *name;
|
char *path, *name;
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
struct dir *t;
|
struct dir *t;
|
||||||
|
int n;
|
||||||
|
|
||||||
/* check root directory */
|
/* check root directory */
|
||||||
if((path = path_real(curpath)) == NULL) {
|
if((path = path_real(curpath)) == NULL) {
|
||||||
|
|
@ -365,11 +397,20 @@ void calc_process() {
|
||||||
} else
|
} else
|
||||||
curpath[0] = 0;
|
curpath[0] = 0;
|
||||||
|
|
||||||
/* start calculating */
|
/* calculate */
|
||||||
if(!calc_dir(root, name) && !failed) {
|
n = calc_dir(root, name);
|
||||||
|
|
||||||
|
/* free some resources */
|
||||||
if(!path[1] && strcmp(name, "."))
|
if(!path[1] && strcmp(name, "."))
|
||||||
free(name);
|
free(name);
|
||||||
free(path);
|
free(path);
|
||||||
|
if(linksl) {
|
||||||
|
linksl = linkst = 0;
|
||||||
|
free(links);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
if(!n && !failed) {
|
||||||
if(root->sub == NULL) {
|
if(root->sub == NULL) {
|
||||||
freedir(root);
|
freedir(root);
|
||||||
failed = 1;
|
failed = 1;
|
||||||
|
|
@ -403,9 +444,6 @@ void calc_process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* something went wrong... */
|
/* something went wrong... */
|
||||||
if(!path[1] && strcmp(name, "."))
|
|
||||||
free(name);
|
|
||||||
free(path);
|
|
||||||
freedir(root);
|
freedir(root);
|
||||||
calc_fail:
|
calc_fail:
|
||||||
while(failed && !input_handle(0))
|
while(failed && !input_handle(0))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue