aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2021-04-16 01:39:08 -0500
committerRob Landley <rob@landley.net>2021-04-16 01:39:08 -0500
commitdafb9211c77788d7ea124aca18205e924d1ac48a (patch)
tree7e24566b090cae6334adfcf2148092323e2bd53b
parent31eb5b82db0f1ec4a7d444fe2d53e2327f1cdd02 (diff)
downloadtoybox-dafb9211c77788d7ea124aca18205e924d1ac48a.tar.gz
cpio: continue past TRAILER!!! (like kernel does) but error on empty archive.
-rwxr-xr-xtests/cpio.test3
-rw-r--r--toys/posix/cpio.c20
2 files changed, 14 insertions, 9 deletions
diff --git a/tests/cpio.test b/tests/cpio.test
index 7e2955a1..3955800f 100755
--- a/tests/cpio.test
+++ b/tests/cpio.test
@@ -59,3 +59,6 @@ testing "-id keeps existing files" "echo new >a/b && cpio -id <a.cpio 2>/dev/nul
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
+
+testing "error on empty file" \
+ "setsid cpio -i < /dev/null 2>/dev/null || echo err" "err\n" "" ""
diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
index b60e19b4..d90be7f3 100644
--- a/toys/posix/cpio.c
+++ b/toys/posix/cpio.c
@@ -72,7 +72,7 @@ static unsigned x8u(char *hex)
// Because scanf gratuitously treats %*X differently than printf does.
sprintf(pattern, "%%%dX%%n", inpos);
sscanf(hex, pattern, &val, &outpos);
- if (inpos != outpos) error_exit("bad header");
+ if (inpos != outpos) error_exit("bad hex");
return val;
}
@@ -80,7 +80,7 @@ static unsigned x8u(char *hex)
void cpio_main(void)
{
// Subtle bit: FLAG_o is 1 so we can just use it to select stdin/stdout.
- int pipe, afd = FLAG(o);
+ int pipe, afd = FLAG(o), empty = 1;
pid_t pid = 0;
// In passthrough mode, parent stays in original dir and generates archive
@@ -111,18 +111,21 @@ void cpio_main(void)
// read cpio archive
- if (FLAG(i) || FLAG(t)) for (;;) {
+ if (FLAG(i) || FLAG(t)) for (;; empty = 0) {
char *name, *tofree, *data;
unsigned size, mode, uid, gid, timestamp;
int test = FLAG(t), err = 0;
// Read header and name.
- if (!(size =readall(afd, toybuf, 110))) break;
+ if (!(size = readall(afd, toybuf, 110))) {
+ if (empty) error_exit("empty archive");
+ else break;
+ }
if (size != 110 || memcmp(toybuf, "070701", 6)) error_exit("bad header");
tofree = name = strpad(afd, x8u(toybuf+94), 110);
if (!strcmp("TRAILER!!!", name)) {
- if (CFG_TOYBOX_FREE) free(tofree);
- break;
+ free(tofree);
+ continue;
}
// If you want to extract absolute paths, "cd /" and run cpio.
@@ -283,9 +286,8 @@ void cpio_main(void)
}
if (CFG_TOYBOX_FREE) free(name);
- memset(toybuf, 0, sizeof(toybuf));
- xwrite(afd, toybuf,
- sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
+ // nlink=1, namesize=11, with padding
+ dprintf(afd, "070701%040X%056X%08XTRAILER!!!%c%c%c%c", 1, 11, 0, 0, 0, 0,0);
}
if (TT.F) xclose(afd);