changeset 1404:ffc7f606ce5b draft

Move DIRTREE_COMEAGAIN second callback up to when the filehandle is still open, and add dir->again variable to distinguish second call instead of checking for -1 filehandle.
author Rob Landley <rob@landley.net>
date Sat, 26 Jul 2014 13:30:40 -0500
parents 411cf82cdf77
children 43c98def61cc
files lib/dirtree.c lib/lib.h toys/other/lsattr.c toys/other/switch_root.c toys/posix/chgrp.c toys/posix/cp.c toys/posix/du.c toys/posix/rm.c
diffstat 8 files changed, 21 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/lib/dirtree.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/lib/dirtree.c	Sat Jul 26 13:30:40 2014 -0500
@@ -116,8 +116,7 @@
   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);
     }
   }
 
@@ -133,8 +132,8 @@
 // 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;
@@ -146,7 +145,7 @@
     free(path);
     close(node->data);
 
-    return;
+    return flags;
   }
 
   // according to the fddir() man page, the filehandle in the DIR * can still
@@ -154,7 +153,7 @@
 
   // 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;
@@ -164,9 +163,13 @@
     }
   }
 
+  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.
--- a/lib/lib.h	Sat Jul 26 13:27:07 2014 -0500
+++ b/lib/lib.h	Sat Jul 26 13:30:40 2014 -0500
@@ -60,7 +60,8 @@
   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[];
 };
 
@@ -70,8 +71,8 @@
 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
--- a/toys/other/lsattr.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/other/lsattr.c	Sat Jul 26 13:30:40 2014 -0500
@@ -140,7 +140,7 @@
 {
   char *fpath = NULL;
   
-  if (root->data == -1) {
+  if (root->again) {
     xputc('\n');
     return 0;
   }
--- a/toys/other/switch_root.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/other/switch_root.c	Sat Jul 26 13:30:40 2014 -0500
@@ -32,7 +32,7 @@
   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);
--- a/toys/posix/chgrp.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/posix/chgrp.c	Sat Jul 26 13:30:40 2014 -0500
@@ -44,7 +44,7 @@
 
   // 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);
--- a/toys/posix/cp.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/posix/cp.c	Sat Jul 26 13:30:40 2014 -0500
@@ -84,7 +84,7 @@
   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 {
--- a/toys/posix/du.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/posix/du.c	Sat Jul 26 13:30:40 2014 -0500
@@ -111,12 +111,12 @@
     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--;
--- a/toys/posix/rm.c	Sat Jul 26 13:27:07 2014 -0500
+++ b/toys/posix/rm.c	Sat Jul 26 13:30:40 2014 -0500
@@ -37,7 +37,7 @@
   // 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);
@@ -52,7 +52,7 @@
       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) {