/** %l: link target */ static int bfs_printf_l(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { if (ftwbuf->typeflag != BFTW_LNK) { return 0; } char *target = xreadlinkat(ftwbuf->at_fd, ftwbuf->at_path, 0); if (!target) { return -1; } int ret = fprintf(file, directive->str, target); free(target); return ret; }
struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, int flags) { struct dirtree *dt = NULL; struct stat st; int len = 0, linklen = 0; if (name) { // open code this because haven't got node to call dirtree_parentfd() on yet int fd = parent ? parent->data : AT_FDCWD; if (xfstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW))) goto error; if (S_ISLNK(st.st_mode)) { if (0>(linklen = xreadlinkat(fd, name, libbuf, 4095))) goto error; libbuf[linklen++]=0; } len = strlen(name); } dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); dt->parent = parent; if (name) { memcpy(&(dt->st), &st, sizeof(struct stat)); strcpy(dt->name, name); if (linklen) { dt->symlink = memcpy(len+(char *)dt, libbuf, linklen); dt->data = --linklen; } } return dt; error: if (!(flags&DIRTREE_SHUTUP) && notdotdot(name)) { char *path = parent ? dirtree_path(parent, 0) : ""; perror_msg("%s%s%s", path, parent ? "/" : "", name); if (parent) free(path); } if (parent) parent->symlink = (char *)1; free(dt); return 0; }