diff options
-rwxr-xr-x | tests/cpio.test | 18 | ||||
-rw-r--r-- | toys/posix/cpio.c | 9 |
2 files changed, 23 insertions, 4 deletions
diff --git a/tests/cpio.test b/tests/cpio.test index 6ab3665a..7e2955a1 100755 --- a/tests/cpio.test +++ b/tests/cpio.test @@ -42,4 +42,20 @@ touch a; chmod a-rwx a; ln -s a/cant b toyonly testing "archives unreadable empty files" "cpio -o -H newc|cpio -it" "b\na\n" "" "b\na\n" chmod u+rw a; rm -f a b - +mkdir a +echo "old" >a/b +echo "a/b" | cpio -o -H newc >a.cpio +rm -rf a +testing "-i doesn't create leading directories" "cpio -i <a.cpio 2>/dev/null; [ -e a ] || echo yes" "yes\n" "" "" +rm -rf a +testing "-id creates leading directories" "cpio -id <a.cpio && cat a/b" "old\n" "" "" +rm -rf a a.cpio + +mkdir a +echo "old" >a/b +find a | cpio -o -H newc >a.cpio +testing "-i keeps existing files" "echo new >a/b && cpio -i <a.cpio 2>/dev/null; cat a/b" "new\n" "" "" +testing "-id keeps existing files" "echo new >a/b && cpio -id <a.cpio 2>/dev/null; cat a/b" "new\n" "" "" +testing "-iu replaces existing files; no error" "echo new >a/b && cpio -iu <a.cpio && cat a/b" "old\n" "" "" +testing "-idu replaces existing files; no error" "echo new >a/b && cpio -idu <a.cpio && cat a/b" "old\n" "" "" +rm -rf a a.cpio diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c index 04700ddb..b60e19b4 100644 --- a/toys/posix/cpio.c +++ b/toys/posix/cpio.c @@ -22,7 +22,7 @@ config CPIO default y help usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner] - [ignored: -mdu -H newc] + [ignored: -m -H newc] Copy files into and out of a "newc" format cpio archive. @@ -32,6 +32,7 @@ config CPIO -o Create archive (stdin=list of files, stdout=archive) -t Test files (list only, stdin=archive, stdout=list of files) -d Create directories if needed + -u unlink existing files when extracting -v Verbose --no-preserve-owner (don't set ownership during extract) */ @@ -137,6 +138,8 @@ void cpio_main(void) // (This output is unaffected by --quiet.) if (FLAG(t) || FLAG(v)) puts(name); + if (FLAG(u) && !test) if (unlink(name) && errno == EISDIR) rmdir(name); + if (!test && FLAG(d) && strrchr(name, '/') && mkpath(name)) { perror_msg("mkpath '%s'", name); test++; @@ -146,7 +149,7 @@ void cpio_main(void) // properly aligned with next file. if (S_ISDIR(mode)) { - if (!test) err = mkdir(name, mode); + if (!test) err = mkdir(name, mode) && !FLAG(u); } else if (S_ISLNK(mode)) { data = strpad(afd, size, 0); if (!test) err = symlink(data, name); @@ -155,7 +158,7 @@ void cpio_main(void) 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_TRUNC|O_NOFOLLOW, mode); + int fd = test ? 0 : open(name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, mode); // If write fails, we still need to read/discard data to continue with // archive. Since doing so overwrites errno, report error now |