Apparently this is a thing people like to do, and they use shell while loops to do it (because cpio only reads one input file at a time from stdin).
To make this work, we need to (a) exit with a failure status rather than success if we hit EOF (we should never normally hit EOF because we should read a TRAILER!!! first), and (b) skip to the end of the TRAILER!!! record rather than just exiting immediately (so that the _next_ cpio to run can start reading stdin at the start of a record, rather than partway through the TRAILER!!! record that caused this cpio to stop). (The error message change in x8u is for the usual "it's harder to debug if two different failure cases in the code output the exact same error message", in this case "bad header".) --- tests/cpio.test | 13 +++++++++++++ toys/posix/cpio.c | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-)
From 90fe1bd354037bc3c6dc02a361c059ffb684cad6 Mon Sep 17 00:00:00 2001 From: Elliott Hughes <[email protected]> Date: Tue, 13 Apr 2021 16:42:05 -0700 Subject: [PATCH] cpio: support reading concatenated cpio files. Apparently this is a thing people like to do, and they use shell while loops to do it (because cpio only reads one input file at a time from stdin). To make this work, we need to (a) exit with a failure status rather than success if we hit EOF (we should never normally hit EOF because we should read a TRAILER!!! first), and (b) skip to the end of the TRAILER!!! record rather than just exiting immediately (so that the _next_ cpio to run can start reading stdin at the start of a record, rather than partway through the TRAILER!!! record that caused this cpio to stop). (The error message change in x8u is for the usual "it's harder to debug if two different failure cases in the code output the exact same error message", in this case "bad header".) --- tests/cpio.test | 13 +++++++++++++ toys/posix/cpio.c | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/cpio.test b/tests/cpio.test index 7e2955a1..660c9185 100755 --- a/tests/cpio.test +++ b/tests/cpio.test @@ -59,3 +59,16 @@ 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 + +# People use cpio in a while loop to make it read concatenated cpio files, +# and they expect it to treat an empty file as an error. +testing "premature EOF" "cpio -ivt 2>/dev/null || echo fail" "fail\n" "" "" +# ...and they also need the cpio instance that reads "TRAILER!!!" to read to +# the end of that record so that the next instance starts at the beginning of +# the next concatenated cpio file. +touch foo +ls -1 foo foo | cpio -o -H newc > foo.cpio +testing "TRAILER!!! read to end of record" \ + "cat foo.cpio foo.cpio | cpio -ivt 2>/dev/null | grep -o foo" \ + "foo\nfoo\n" "" "" +rm foo foo.cpio diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c index b60e19b4..8187a4c2 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; } @@ -117,10 +117,11 @@ void cpio_main(void) int test = FLAG(t), err = 0; // Read header and name. - if (!(size =readall(afd, toybuf, 110))) break; + if (!(size =readall(afd, toybuf, 110))) error_exit("premature EOF"); if (size != 110 || memcmp(toybuf, "070701", 6)) error_exit("bad header"); tofree = name = strpad(afd, x8u(toybuf+94), 110); if (!strcmp("TRAILER!!!", name)) { + readall(afd, toybuf, 348); if (CFG_TOYBOX_FREE) free(tofree); break; } -- 2.31.1.295.g9ea45b61b8-goog
_______________________________________________ Toybox mailing list [email protected] http://lists.landley.net/listinfo.cgi/toybox-landley.net
