OSDN Git Service

Don't add cpio TRAILER!!! entry by default, add new --trailer option if you
[android-x86/external-toybox.git] / toys / posix / cpio.c
index 64d597b..90c8107 100644 (file)
@@ -1,6 +1,6 @@
 /* cpio.c - a basic cpio
  *
- * Written 2013 AD by Isaac Dunham; this code is placed under the 
+ * Written 2013 AD by Isaac Dunham; this code is placed under the
  * same license as toybox or as CC0, at your option.
  *
  * Portions Copyright 2015 by Frontier Silicon Ltd.
  * rdevmajor rdevminor namesize check
  * This is the equiavlent of mode -H newc when using GNU CPIO.
 
-USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
 
 config CPIO
   bool "cpio"
   default y
   help
-    usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner] [ignored: -mdu -H newc]
+    usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]
+           [ignored: -mdu -H newc]
 
     copy files into and out of a "newc" format cpio archive
 
@@ -32,7 +33,8 @@ config CPIO
     -o create archive (stdin=list of files, stdout=archive)
     -t test files (list only, stdin=archive, stdout=list of files)
     -v verbose (list files during create/extract)
-    --no-preserve-owner (don't set ownership during extract) 
+    --no-preserve-owner (don't set ownership during extract)
+    --trailer Add legacy trailer (prevents concatenation).
 */
 
 #define FOR_cpio
@@ -60,7 +62,7 @@ static char *strpad(int fd, unsigned len, unsigned align)
 }
 
 //convert hex to uint; mostly to allow using bits of non-terminated strings
-unsigned x8u(char *hex)
+static unsigned x8u(char *hex)
 {
   unsigned val, inpos = 8, outpos;
   char pattern[6];
@@ -112,7 +114,8 @@ void cpio_main(void)
     int test = toys.optflags & FLAG_t, err = 0;
 
     // Read header and name.
-    xreadall(afd, toybuf, 110);
+    if (!(size =readall(afd, toybuf, 110))) break;
+    if (size != 110 || memcmp(toybuf, "070701", 6)) error_exit("bad header");
     tofree = name = strpad(afd, x8u(toybuf+94), 110);
     if (!strcmp("TRAILER!!!", name)) {
       if (CFG_TOYBOX_FREE) free(tofree);
@@ -146,7 +149,8 @@ void cpio_main(void)
       if (!test) err = symlink(data, name);
       free(data);
       // Can't get a filehandle to a symlink, so do special chown
-      if (!err && !geteuid() && !(toys.optflags & FLAG_no_preserve_owner)) err = lchown(name, uid, gid);
+      if (!err && !geteuid() && !(toys.optflags & FLAG_no_preserve_owner))
+        err = lchown(name, uid, gid);
     } else if (S_ISREG(mode)) {
       int fd = test ? 0 : open(name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, mode);
 
@@ -178,7 +182,7 @@ void cpio_main(void)
         close(fd);
       }
     } else if (!test)
-      err = mknod(name, mode, makedev(x8u(toybuf+78), x8u(toybuf+86)));
+      err = mknod(name, mode, dev_makedev(x8u(toybuf+78), x8u(toybuf+86)));
 
     // Set ownership and timestamp.
     if (!test && !err) {
@@ -186,11 +190,13 @@ void cpio_main(void)
       // by name to chown/utime, but how do we know it's the same item?
       // Check that we at least have the right type of entity open, and do
       // NOT restore dropped suid bit in this case.
-      if (!S_ISREG(mode) && !S_ISLNK(mode) && !geteuid() && !(toys.optflags & FLAG_no_preserve_owner)) {
+      if (!S_ISREG(mode) && !S_ISLNK(mode) && !geteuid()
+          && !(toys.optflags & FLAG_no_preserve_owner))
+      {
         int fd = open(name, O_RDONLY|O_NOFOLLOW);
         struct stat st;
 
-        if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == (mode&S_IFMT)) 
+        if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == (mode&S_IFMT))
           err = fchown(fd, uid, gid);
         else err = 1;
 
@@ -207,7 +213,7 @@ void cpio_main(void)
       }
     }
 
-    if (err) perror_msg("'%s'", name);
+    if (err) perror_msg_raw(name);
     free(tofree);
 
   // Output cpio archive
@@ -226,10 +232,10 @@ 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) 
+      if (lstat(name, &st) || (S_ISREG(st.st_mode)
           && st.st_size && (fd = open(name, O_RDONLY))<0))
       {
-        perror_msg("%s", name);
+        perror_msg_raw(name);
         continue;
       }
 
@@ -239,14 +245,15 @@ void cpio_main(void)
         llen = sprintf(toybuf,
           "070701%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
           (int)st.st_ino, st.st_mode, st.st_uid, st.st_gid, (int)st.st_nlink,
-          (int)st.st_mtime, (int)st.st_size, major(st.st_dev),
-          minor(st.st_dev), major(st.st_rdev), minor(st.st_rdev), nlen, 0);
+          (int)st.st_mtime, (int)st.st_size, dev_major(st.st_dev),
+          dev_minor(st.st_dev), dev_major(st.st_rdev), dev_minor(st.st_rdev),
+          nlen, 0);
         xwrite(afd, toybuf, llen);
         xwrite(afd, name, nlen);
 
         // NUL Pad header up to 4 multiple bytes.
         llen = (llen + nlen) & 3;
-        if (llen) xwrite(afd, &zero, 4-llen); 
+        if (llen) xwrite(afd, &zero, 4-llen);
 
         // Write out body for symlink or regular file
         llen = st.st_size;
@@ -269,9 +276,11 @@ void cpio_main(void)
     }
     free(name);
 
-    memset(toybuf, 0, sizeof(toybuf));
-    xwrite(afd, toybuf,
-      sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
+    if (FLAG_trailer) {
+      memset(toybuf, 0, sizeof(toybuf));
+      xwrite(afd, toybuf,
+        sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
+    }
   }
   if (TT.archive) xclose(afd);