/* checks an individual file for hard links and updates its cicrular linked * list, also updates the sizes of the parent dirs */ static void hlink_check(struct dir *d) { struct dir *t, *pt, *par; int i; /* add to links table */ khiter_t k = kh_put(hl, links, d, &i); /* found in the table? update hlnk */ if(!i) { t = d->hlnk = kh_key(links, k); if(t->hlnk != NULL) for(t=t->hlnk; t->hlnk!=d->hlnk; t=t->hlnk) ; t->hlnk = d; } /* now update the sizes of the parent directories, * This works by only counting this file in the parent directories where this * file hasn't been counted yet, which can be determined from the hlnk list. * XXX: This may not be the most efficient algorithm to do this */ for(i=1,par=d->parent; i&∥ par=par->parent) { if(d->hlnk) for(t=d->hlnk; i&&t!=d; t=t->hlnk) for(pt=t->parent; i&&pt; pt=pt->parent) if(pt==par) i=0; if(i) { par->size = adds64(par->size, d->size); par->asize = adds64(par->size, d->asize); } } }
/* removes item from the hlnk circular linked list and size counts of the parents */ static void freedir_hlnk(struct dir *d) { struct dir *t, *par, *pt; int i; if(!(d->flags & FF_HLNKC)) return; /* remove size from parents. * This works the same as with adding: only the parents in which THIS is the * only occurence of the hard link will be modified, if the same file still * exists within the parent it shouldn't get removed from the count. * XXX: Same note as for dir_mem.c / hlink_check(): * this is probably not the most efficient algorithm */ for(i=1,par=d->parent; i&∥ par=par->parent) { if(d->hlnk) for(t=d->hlnk; i&&t!=d; t=t->hlnk) for(pt=t->parent; i&&pt; pt=pt->parent) if(pt==par) i=0; if(i) { par->size = adds64(par->size, -d->size); par->asize = adds64(par->size, -d->asize); } } /* remove from hlnk */ if(d->hlnk) { for(t=d->hlnk; t->hlnk!=d; t=t->hlnk) ; t->hlnk = d->hlnk; } }
void addparentstats(struct dir *d, int64_t size, int64_t asize, int items) { while(d) { d->size = adds64(d->size, size); d->asize = adds64(d->asize, asize); d->items += items; d = d->parent; } }