Forráskód Böngészése

cpio: Don't lchown() if -t is specified

When using -t to inspect an archive, cpio would try to set the owner of
any symlink in the archive, even though the symlink wasn't created by
the command previously.

This would lead to two results, either the command fails with a "No such
file or directory" message when trying to lchown() the symlink path, or
an existing file, with the name of the symlink, is lchown()-ed.

Guard the lchown() function call with a "if (!FLAG(t))" block, and add
regression test for this.
Yi-Yo Chiang via Toybox 3 éve
szülő
commit
c366525850
2 módosított fájl, 25 hozzáadás és 4 törlés
  1. 19 0
      tests/cpio.test
  2. 6 4
      toys/posix/cpio.c

+ 19 - 0
tests/cpio.test

@@ -63,3 +63,22 @@ testing "skip NUL" "for i in a b; do dd if=/dev/zero bs=512 count=1 2>/dev/null;
 rm -rf a a.cpio
 
 testing "error on empty file" "cpio -i 2>/dev/null || echo err" "err\n" "" ""
+
+mkdir a
+touch a/file
+ln -s a/symlink a/symlink
+mkdir a/dir
+find a | cpio -o -H newc >a.cpio
+if [ "$(id -u)" -eq 0 ]; then
+  # We chown between user "root" and the last user in /etc/passwd,
+  # and group "root" and the last group in /etc/group.
+  USR="$(sed -n '$s/:.*//p' /etc/passwd)"
+  GRP="$(sed -n '$s/:.*//p' /etc/group)"
+  # Or if that fails, we assume we're on Android...
+  : "${USR:=shell}"
+  : "${GRP:=shell}"
+  chown -h "${USR}:${GRP}" a/file a/symlink a/dir
+fi
+skipnot [ $(id -u) -eq 0 ]
+testing "-t preserve ownership" "cpio -t <a.cpio >/dev/null && stat -c '%U:%G' a/file a/symlink a/dir" "${USR}:${GRP}\n${USR}:${GRP}\n${USR}:${GRP}\n" "" ""
+rm -rf a a.cpio

+ 6 - 4
toys/posix/cpio.c

@@ -166,11 +166,13 @@ void cpio_main(void)
       if (!test) err = mkdir(name, mode) && !FLAG(u);
     } else if (S_ISLNK(mode)) {
       data = strpad(afd, size, 0);
-      if (!test) err = symlink(data, name);
+      if (!test) {
+        err = symlink(data, name);
+        // Can't get a filehandle to a symlink, so do special chown
+        if (!err && !geteuid() && !FLAG(no_preserve_owner))
+          err = lchown(name, uid, gid);
+      }
       free(data);
-      // Can't get a filehandle to a symlink, so do special chown
-      if (!err && !geteuid() && !FLAG(no_preserve_owner))
-        err = lchown(name, uid, gid);
     } else if (S_ISREG(mode)) {
       int fd = test ? 0 : open(name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, mode);