diff options
-rw-r--r-- | lib/dirtree.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/lib/dirtree.c b/lib/dirtree.c index f4cc620d..02f4b887 100644 --- a/lib/dirtree.c +++ b/lib/dirtree.c @@ -83,20 +83,18 @@ error: char *dirtree_path(struct dirtree *node, int *plen) { + struct dirtree *nn; char *path; - int len; + int len = plen ? *plen : 0; - if (!node) { - path = xmalloc(*plen); - *plen = 0; - return path; - } - - len = (plen ? *plen : 0)+strlen(node->name)+1; - path = dirtree_path(node->parent, &len); - if (len && path[len-1] != '/') path[len++]='/'; - len = stpcpy(path+len, node->name) - path; + for (nn = node; nn; nn = nn->parent) if (*nn->name) len += strlen(nn->name)+1; if (plen) *plen = len; + if (!len) return 0; + path = xmalloc(len)+len; + for (nn = node; nn; nn = nn->parent) if ((len = strlen(nn->name))) { + *--path = '/'*(nn != node); + memcpy(path -= len, nn->name, len); + } return path; } @@ -121,11 +119,11 @@ struct dirtree *dirtree_handle_callback(struct dirtree *new, flags = callback(new); if (S_ISDIR(new->st.st_mode) && (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN))) - flags = dirtree_recurse(new, callback, + flags = dirtree_recurse(new, callback, !*new->name ? AT_FDCWD : openat(dirtree_parentfd(new), new->name, O_CLOEXEC), flags); - // If this had children, it was callback's job to free them already. - if (!(flags & DIRTREE_SAVE)) { + // Free node that didn't request saving and has no saved children. + if (!new->child && !(flags & DIRTREE_SAVE)) { free(new); new = 0; } |