[Toybox] [PATCH] cpio: archive unreadable empty files; cpio.test

Isaac Dunham ibid.ag at gmail.com
Sat May 31 08:59:42 PDT 2014


cpio: archive more files
While writing tests for cpio, I found that cpio tries to open empty
files if they're regular files, and fails to archive them if unreadable.
This can be easily avoided, and is not the usual behavior.

--
As was discussed previously, the ideal approach to testing cpio is
checking that archives from one implemention work with another.
But that's not simple to handle with the toybox test system, except for
extracting shipped archives.

Short of that, these tests are likely to catch the bigger file format bugs:
wrong name or file padding, wrong header length.
The first two are equivalent to what I used to catch the bugs I found.

I note that the file format allows an unlimited quantity of trailing
garbage, so we have to truncate the output to do proper output 
tests; there's also a _ton_ of calculations to be made for a full
test.
The bigger details in format writing are these:
Is the terminator (TARGET!!!) in the right place?
Is the magic right?
Is the name length properly stored (include the null terminator)?
I have also included tests for these.

Besides that, I did a test for whether we archived as much as possible
(dangling symlinks and empty-but-unreadable files).
This came up as a FAIL on our cpio (but not busybox cpio), so the patch
is attached.
All other tests pass.

HTH,
Isaac Dunham
-------------- next part --------------
diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
index 958931e..668f2ee 100644
--- a/toys/posix/cpio.c
+++ b/toys/posix/cpio.c
@@ -202,8 +202,8 @@ void cpio_main(void)
       if (len<1) break;
       if (name[len-1] == '\n') name[--len] = 0;
       nlen = len+1;
-      if (lstat(name, &st)
-          || (S_ISREG(st.st_mode) && (fd = open(name, O_RDONLY))<0))
+      if (lstat(name, &st) || (S_ISREG(st.st_mode) 
+          && st.st_size && (fd = open(name, O_RDONLY))<0))
       {
         perror_msg("%s", name);
         continue;
-------------- next part --------------
#!/bin/bash

[ -f testing.sh ] && . testing.sh

# We need to test name and file padding.
# This means all possible values of strlen(name)+1 % 4,
# plus file sizes of at least 0-4.

touch a bb ccc dddd
testing "cpio name padding" "cpio -o -H newc|cpio -it" "a\nbb\nccc\ndddd\n" "" "a\nbb\nccc\ndddd\n"
rm a bb ccc dddd

touch a
printf '1' >b
printf '22' >c
printf '333' >d
testing "cpio file padding" "cpio -o -H newc|cpio -it" "a\nb\nc\nd\n" "" "a\nb\nc\nd\n"
rm a b c d

touch a
printf '1' >bb
printf '22' >ccc
printf '333' >dddd
# With the proper padding, header length, and file length, 
# the relevant bit should be here:
# 110*5 + 4*3 + 2 + 6*3 = 550 + 12 + 20 = 582
# files are padded to n*4, names are padded to 2 + n*4 due to the header length
testing "cpio archive length" "cpio -o -H newc|dd ibs=2 skip=291 count=5" "TRAILER!!!" "" "a\nbb\nccc\ndddd\n"
testing "cpio archive magic" "cpio -o -H newc|dd ibs=2 count=3" "070701" "" "a\n"
# check name length (8 bytes before the empty "crc")
testing "cpio name length" "cpio -o -H newc|dd ibs=2 skip=47 count=4" "00000002" "" "a\n"
rm a bb ccc dddd

# archive dangling symlinks and empty files even if we cannot open them
touch a; chmod a-rwx a; ln -s a/cant b
testing "cpio archives unreadable empty files" "cpio -o -H newc|cpio -it" "a\nb\n" "" "a\nb\n"
chmod u+rw a; rm -f a b




More information about the Toybox mailing list