[Toybox] dirtree: add DIRTREE_NOSTAT flag

Mark Salyzyn salyzyn at android.com
Wed Oct 26 13:12:55 PDT 2016


>From the AOSP gerrit fixing internal bug 32399196
( https://android-review.googlesource.com/#/c/295731 )

Change subject: dirtree: add DIRTREE_NOSTAT flag

Prevents a superfluous attribute request. Flag returned on callbacks,
subsequent recursive callbacks have a responsibility to issue:

fstatat(dirtree_parentfd(dirtree), dirtree->name, &dirtree->st,
        AT_SYMLINK_NOFOLLOW);

to fill in stat details on file name entries of interests. This
allows for precise control over which file(s) get stat() information.

Test: manual in combination with 'ps: only stat() /proc/<pid>'
      looking for selinux getattr violations for /proc/iomem
      or /proc/sysrq-trigger.
Change-Id: I1aa5f2104b7ddd5587ee9608012530aab46a0f66
---
 lib/dirtree.c | 20 +++++++++++---------
 lib/lib.h     |  3 +++
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/lib/dirtree.c b/lib/dirtree.c
index 8f235ed..81559d6 100644
--- a/lib/dirtree.c
+++ b/lib/dirtree.c
@@ -31,21 +31,23 @@ struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, int flags)
   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->dirfd : AT_FDCWD;
-
-    if (fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW)))
-      goto error;
-    if (S_ISLNK(st.st_mode)) {
-      if (0>(linklen = readlinkat(fd, name, libbuf, 4095))) goto error;
-      libbuf[linklen++]=0;
+    if (!(flags & DIRTREE_NOSTAT)) {
+      // open code this because haven't got node to call dirtree_parentfd() on yet
+      int fd = parent ? parent->dirfd : AT_FDCWD;
+
+      if (fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW)))
+        goto error;
+      if (S_ISLNK(st.st_mode)) {
+        if (0>(linklen = readlinkat(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));
+    if (!(flags & DIRTREE_NOSTAT)) memcpy(&(dt->st), &st, sizeof(struct stat));
     strcpy(dt->name, name);
 
     if (linklen) dt->symlink = memcpy(len+(char *)dt, libbuf, linklen);
diff --git a/lib/lib.h b/lib/lib.h
index 2afe558..06393fb 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -73,6 +73,9 @@ void get_optflags(void);
 #define DIRTREE_SHUTUP      16
 // Breadth first traversal, conserves filehandles at the expense of memory
 #define DIRTREE_BREADTH     32
+// Do not stat the files. st and symlink on a recurse pass will be all zero.
+// Callback can fill in these fields afterwards, likely after filename checking.
+#define DIRTREE_NOSTAT      64
 // Don't look at any more files in this directory.
 #define DIRTREE_ABORT      256
 



More information about the Toybox mailing list