No infinite loop on EOF; archive devices; allow -it
getline(&name, &size, fd) will return -1 at EOF without setting
name to 0. Thus, the old check resulted in an infinite loop
re-archiving the file.
Non-regular files are archived as size 0; whether we can open them
is irrelevant.
The test most exactly expressing the logic would be
if (lstat(...) || ((S_ISREG(...)) && (open(...)<0))
//skip this file verbosely
But GCC thinks fd may be used uninitialized here, which is
technically half-correct; in the case of a non-regular file,
fd would be passed to write_cpio_member uninitialized, and then ignored.
So instead, we ignore a failed open() on non-regular files.
SUSv2 says to use -it not -t; don't prevent it.
--
Resending this because I forgot to attach the patch (doh!).
I discovered that there were a few bugs in the new archive creation code.
Besides the two this fixes, the padding is very much wrong.
I have not (yet) fixed that.
The comment got stuck in there because the check has gotten deleted
once, so it seems to not be obvious what it's doing.
I've started a test, but...it needs some more work.
A quick check is:
echo -e "/dev/null\n/dev/console"| cpio -o | cpio -it
which should output:
/dev/null
/dev/console
(the cpio you're testing must be in $PATH)
HTH,
Isaac Dunham
diff --git a/toys/pending/cpio.c b/toys/pending/cpio.c
index 11ad4ea..4cfa181 100644
--- a/toys/pending/cpio.c
+++ b/toys/pending/cpio.c
@@ -9,7 +9,7 @@
* (Yes, that's SUSv2, the newer standards removed it around the time RPM
* and initramfs started heavily using this archive format. Go figure.)
-USE_CPIO(NEWTOY(cpio, "H:di|o|t|uF:[!iot][!dot][!uot]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "H:di|o|t|uF:[!io][!dot][!uot]", TOYFLAG_BIN))
config CPIO
bool "cpio"
@@ -112,9 +112,11 @@ void loopfiles_stdin(void)
int len, fd;
len = getline(&name, &size, stdin);
- if (!name) break;
+ if (!name || !(len+1)) break;
if (name[len-1] == '\n') name[--len] = 0;
- if (lstat(name, &st) || (fd = open(name, O_RDONLY))<0)
+ //always archive special files, since they will not be read
+ if (lstat(name, &st) ||
+ (((fd = open(name, O_RDONLY))<0) && (S_ISREG(st.st_mode))))
perror_msg("%s", name);
else {
write_cpio_member(fd, name, st);
_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net