/* 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
-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
}
//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];
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);
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);
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) {
// 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;
}
}
- if (err) perror_msg("'%s'", name);
+ if (err) perror_msg_raw(name);
free(tofree);
// Output cpio archive
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;
}
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;
}
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);