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

Reply via email to