summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
index a19fea0..6c95ba0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -38,6 +38,9 @@ char fullsizedat[20]; /* max: 999.999.999.999.999 */
char *getpathdat;
int getpathdatl = 0;
+struct dir **links;
+int linksl = 0, linkst = 0;
+
char *cropstr(const char *from, int s) {
int i, j, o = strlen(from);
@@ -246,3 +249,81 @@ char *getpath(struct dir *cur) {
return getpathdat;
}
+
+/* act = 0 -> just fill the links array
+ act = 1 -> fill array and remove duplicates
+ act = -1 -> use array to re-add duplicates */
+void link_list_rec(struct dir *d, int act) {
+ struct dir *t;
+ int i;
+
+ /* recursion, check sub directories */
+ for(t=d->sub; t!=NULL; t=t->next)
+ link_list_rec(t, act);
+
+ /* not a link candidate? ignore */
+ if(!(d->flags & FF_HLNKC))
+ return;
+
+ /* check against what we've found so far */
+ for(i=0; i<linkst; i++)
+ if(links[i]->dev == d->dev && links[i]->ino == d->ino)
+ break;
+
+ /* found in the list, set link flag and set size to zero */
+ if(act == 1 && i != linkst) {
+ d->flags |= FF_HLNK;
+ for(t=d->parent; t!=NULL; t=t->parent) {
+ t->size -= d->size;
+ t->asize -= d->asize;
+ }
+ d->size = d->asize = 0;
+ return;
+ }
+
+ /* found in the list, reset flag and re-add size */
+ if(act == -1 && i != linkst && d->flags & FF_HLNK) {
+ d->flags -= FF_HLNK;
+ d->size = links[i]->size;
+ d->asize = links[i]->asize;
+ for(t=d->parent; t!=NULL; t=t->parent) {
+ t->size += d->size;
+ t->asize += d->asize;
+ }
+ }
+
+ /* not found, add to the list */
+ if(act == 1 || (act == 0 && !(d->flags & FF_HLNK))) {
+ if(++linkst > linksl) {
+ linksl *= 2;
+ if(!linksl) {
+ linksl = 64;
+ links = malloc(linksl*sizeof(struct dir *));
+ } else
+ links = realloc(links, linksl*sizeof(struct dir *));
+ }
+ links[i] = d;
+ }
+}
+
+
+void link_del(struct dir *par) {
+ while(par->parent != NULL)
+ par = par->parent;
+ link_list_rec(par, 1);
+ linkst = 0;
+}
+
+
+void link_add(struct dir *par) {
+ while(par->parent != NULL)
+ par = par->parent;
+ /* In order to correctly re-add the duplicates, we'll have to pass the entire
+ tree twice, one time to get a list of all links, second time to re-add them */
+ link_list_rec(par, 0);
+ link_list_rec(par, -1);
+ linkst = 0;
+}
+
+
+