aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtests/cpio.test19
-rw-r--r--toys/posix/cpio.c10
2 files changed, 25 insertions, 4 deletions
diff --git a/tests/cpio.test b/tests/cpio.test
index 34794841..183dadde 100755
--- a/tests/cpio.test
+++ b/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
diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
index 07c294f0..35b74b3b 100644
--- a/toys/posix/cpio.c
+++ b/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);