if (dir) {
if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) {
new->data = openat(dirtree_parentfd(new), new->name, O_CLOEXEC);
- dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW);
- if (flags & DIRTREE_COMEAGAIN) flags = callback(new);
+ flags = dirtree_recurse(new, callback, flags);
}
}
// Recursively read/process children of directory node (with dirfd in data),
// filtering through callback().
-void dirtree_recurse(struct dirtree *node,
- int (*callback)(struct dirtree *node), int symfollow)
+int dirtree_recurse(struct dirtree *node,
+ int (*callback)(struct dirtree *node), int flags)
{
struct dirtree *new, **ddt = &(node->child);
struct dirent *entry;
free(path);
close(node->data);
- return;
+ return flags;
}
// according to the fddir() man page, the filehandle in the DIR * can still
// The extra parentheses are to shut the stupid compiler up.
while ((entry = readdir(dir))) {
- if (!(new = dirtree_add_node(node, entry->d_name, symfollow)))
+ if (!(new = dirtree_add_node(node, entry->d_name, flags&DIRTREE_SYMFOLLOW)))
continue;
new = dirtree_handle_callback(new, callback);
if (new == DIRTREE_ABORTVAL) break;
}
}
+ if (flags & DIRTREE_COMEAGAIN) flags = callback(node);
+
// This closes filehandle as well, so note it
closedir(dir);
node->data = -1;
+
+ return flags;
}
// Create dirtree from path, using callback to filter nodes.
long extra; // place for user to store their stuff (can be pointer)
struct stat st;
char *symlink;
- int data; // dirfd for directory, linklen for symlink, -1 = comeagain
+ int data; // dirfd for directory, linklen for symlink
+ char again;
char name[];
};
int dirtree_parentfd(struct dirtree *node);
struct dirtree *dirtree_handle_callback(struct dirtree *new,
int (*callback)(struct dirtree *node));
-void dirtree_recurse(struct dirtree *node,
- int (*callback)(struct dirtree *node), int symfollow);
+int dirtree_recurse(struct dirtree *node, int (*callback)(struct dirtree *node),
+ int symfollow);
struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node));
// help.c
{
char *fpath = NULL;
- if (root->data == -1) {
+ if (root->again) {
xputc('\n');
return 0;
}
if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) {
int flag = 0;
if (S_ISDIR(node->st.st_mode)) {
- if (node->data != -1) return DIRTREE_COMEAGAIN;
+ if (!node->again) return DIRTREE_COMEAGAIN;
flag = AT_REMOVEDIR;
}
unlinkat(dirtree_parentfd(node), node->name, flag);
// Depth first search
if (!dirtree_notdotdot(node)) return 0;
- if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode))
+ if ((flags & FLAG_R) && !node->again && S_ISDIR(node->st.st_mode))
return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0);
fd = dirtree_parentfd(node);
if (!dirtree_notdotdot(try)) return 0;
// If returning from COMEAGAIN, jump straight to -p logic at end.
- if (S_ISDIR(try->st.st_mode) && try->data == -1) {
+ if (S_ISDIR(try->st.st_mode) && try->again) {
fdout = try->extra;
err = 0;
} else {
return 0;
// Don't count hard links twice
- if (!(toys.optflags & FLAG_l) && node->data != -1)
+ if (!(toys.optflags & FLAG_l) && !node->again)
if (seen_inode(&TT.inodes, &node->st)) return 0;
// Collect child info before printing directory size
if (S_ISDIR(node->st.st_mode)) {
- if (node->data != -1) {
+ if (!node->again) {
TT.depth++;
return DIRTREE_COMEAGAIN | (DIRTREE_SYMFOLLOW*!!(toys.optflags & FLAG_L));
} else TT.depth--;
// This is either the posix section 2(b) prompt or the section 3 prompt.
if (!(flags & FLAG_f)
&& (!S_ISLNK(try->st.st_mode) && faccessat(fd, try->name, W_OK, 0))) or++;
- if (!(dir && try->data == -1) && ((or && isatty(0)) || (flags & FLAG_i))) {
+ if (!(dir && try->again) && ((or && isatty(0)) || (flags & FLAG_i))) {
char *s = dirtree_path(try, 0);
fprintf(stderr, "rm %s%s", or ? "ro " : "", dir ? "dir " : "");
or = yesno(s, 0);
if (toys.optflags & FLAG_f) wfchmodat(fd, try->name, 0600);
else goto skip;
}
- if (try->data != -1) return DIRTREE_COMEAGAIN;
+ if (!try->again) return DIRTREE_COMEAGAIN;
using = AT_REMOVEDIR;
if (try->symlink) goto skip;
if (flags & FLAG_i) {