[Toybox] [PATCH] cp: fix copying xattrs on directories.

enh enh at google.com
Tue Feb 19 17:16:27 PST 2019


Tested manually:

  mkdir x
  setfattr -n user.key -v value x
  ./toybox cp -r --preserve=a x y
  getfattr -d y

I didn't want to be the first to add a test that uses setfattr/getfattr,
but if you say it's okay I'll send another patch with that.

Fixes: #112
---
 toys/posix/cp.c | 57 ++++++++++++++++++++++++++++---------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 5e1a0163..5aee8bdd 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -276,30 +276,6 @@ static int cp_node(struct dirtree *try)
           err = 0;
         }

-        // We only copy xattrs for files because there's no flistxattrat()
-        if (TT.pflags&(_CP_xattr|_CP_context)) {
-          ssize_t listlen = flistxattr(fdin, 0, 0), len;
-          char *name, *value, *list;
-
-          if (listlen>0) {
-            list = xmalloc(listlen);
-            flistxattr(fdin, list, listlen);
-            list[listlen-1] = 0; // I do not trust this API.
-            for (name = list; name-list < listlen; name += strlen(name)+1) {
-              if (!(TT.pflags&_CP_xattr) && strncmp(name, "security.", 9))
-                continue;
-              if ((len = fgetxattr(fdin, name, 0, 0))>0) {
-                value = xmalloc(len);
-                if (len == fgetxattr(fdin, name, value, len))
-                  if (fsetxattr(fdout, name, value, len, 0))
-                    perror_msg("%s setxattr(%s=%s)", catch, name, value);
-                free(value);
-              }
-            }
-            free(list);
-          }
-        }
-
         close(fdin);
       }
     } while (err && (flags & (FLAG_f|FLAG_n)) && !unlinkat(cfd, catch, 0));
@@ -336,6 +312,39 @@ static int cp_node(struct dirtree *try)
       else futimens(fdout, times);
     }

+    // POSIX extended attributes
+    if (TT.pflags&(_CP_xattr|_CP_context)) {
+      int fdin = openat(tfd, try->name, O_RDONLY);
+
+      if (fdin == -1) {
+        perror_msg("openat %s", try->name);
+      } else {
+        ssize_t listlen = flistxattr(fdin, 0, 0);
+
+        if (listlen>0) {
+          char *list = xmalloc(listlen), *name, *value;
+
+          flistxattr(fdin, list, listlen);
+          list[listlen-1] = 0; // I do not trust this API.
+          for (name = list; name-list < listlen; name += strlen(name)+1) {
+            ssize_t len;
+
+            if (!(TT.pflags&_CP_xattr) && strncmp(name, "security.", 9))
+              continue;
+            if ((len = fgetxattr(fdin, name, 0, 0))>0) {
+              value = xmalloc(len);
+              if (len == fgetxattr(fdin, name, value, len))
+                if (fsetxattr(fdout, name, value, len, 0))
+                  perror_msg("%s setxattr(%s=%s)", catch, name, value);
+              free(value);
+            }
+          }
+          free(list);
+        }
+        close(fdin);
+      }
+    }
+
     // mode comes last because other syscalls can strip suid bit
     if (fdout != AT_FDCWD) {
       if (TT.pflags & _CP_mode) fchmod(fdout, try->st.st_mode);
-- 
2.21.0.rc0.258.g878e2cd30e-goog
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-cp-fix-copying-xattrs-on-directories.patch
Type: text/x-patch
Size: 3295 bytes
Desc: not available
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20190219/29a2a3e4/attachment.bin>


More information about the Toybox mailing list