diff options
-rwxr-xr-x | tests/cpio.test | 19 | ||||
-rw-r--r-- | toys/posix/cpio.c | 10 |
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); |