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

Reply via email to