Mercurial > hg > toybox
changeset 1223:a7d5b93111a5 draft
Next round of cpio cleanup.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 15 Mar 2014 15:41:09 -0500 |
parents | bb9d19136eeb |
children | 3aba6950b886 |
files | toys/pending/cpio.c |
diffstat | 1 files changed, 37 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/toys/pending/cpio.c Thu Mar 13 19:55:59 2014 -0500 +++ b/toys/pending/cpio.c Sat Mar 15 15:41:09 2014 -0500 @@ -39,6 +39,8 @@ GLOBALS( char *archive; char *fmt; + + int outfd; ) // 110 bytes @@ -61,40 +63,42 @@ void write_cpio_member(int fd, char *name, struct stat buf) { - char ahdr[sizeof(struct newc_header) + 1]; - struct newc_header *hdr = (struct newc_header *)ahdr; - size_t out = 0; - unsigned int n = 0x00000000, nlen = strlen(name) + 1; + unsigned nlen = strlen(name)+1, error = 0, zero = 0; + ssize_t llen; + + if (!S_ISREG(buf.st_mode) && !S_ISLNK(buf.st_mode)) buf.st_size = 0; + else if (buf.st_size >> 32) { + perror_msg("skipping >2G file '%s'", name); + return; + } + + llen = sprintf(toybuf, + "070701%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X", + (int)(buf.st_ino), buf.st_mode, buf.st_uid, buf.st_gid, (int)buf.st_nlink, + (int)(buf.st_mtime), (int)(buf.st_size), major(buf.st_dev), + minor(buf.st_dev), major(buf.st_rdev), minor(buf.st_rdev), nlen, 0); + xwrite(TT.outfd, toybuf, llen); + xwrite(TT.outfd, name, nlen); - memset(hdr, '0', sizeof(struct newc_header)); - if (S_ISDIR(buf.st_mode) || S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) - || S_ISFIFO(buf.st_mode) || S_ISSOCK(buf.st_mode)) - buf.st_size = 0; - snprintf((char *)(hdr), sizeof(struct newc_header)+1, - "070701%08X%08X" "%08X%08X" - "%08X%08X%08X" - "%08X%08X" "%08X%08X%08X00000000", - (unsigned int)(buf.st_ino), buf.st_mode, buf.st_uid, buf.st_gid, - buf.st_nlink, (uint32_t)(buf.st_mtime), (uint32_t)(buf.st_size), - major(buf.st_dev), minor(buf.st_dev), - major(buf.st_rdev), minor(buf.st_rdev), nlen); - write(1, hdr, sizeof(struct newc_header)); - write(1, name, nlen); - if ((nlen + 2) & 3) write(1, &n, 4 - ((nlen + 2) & 3)); + // NUL Pad header up to 4 multiple bytes. + llen = (llen + nlen) & 3; + if (llen) xwrite(TT.outfd, &zero, 4-llen); + + // Write out body for symlink or regular file + llen = buf.st_size; if (S_ISLNK(buf.st_mode)) { - ssize_t llen = readlink(name, toybuf, sizeof(toybuf) - 1); - if (llen > 0) { - toybuf[llen] = '\0'; - write(1, toybuf, buf.st_size); - } - } else if (buf.st_size) { - for (; (lseek(fd, 0, SEEK_CUR) < (uint32_t)(buf.st_size));) { - out = read(fd, toybuf, sizeof(toybuf)); - if (out > 0) write(1, toybuf, out); - if (errno || out < sizeof(toybuf)) break; - } + if (readlink(name, toybuf, sizeof(toybuf)-1) == llen) + xwrite(TT.outfd, toybuf, llen); + else perror_msg("readlink '%s'", name); + } else while (llen) { + nlen = llen > sizeof(toybuf) ? sizeof(toybuf) : llen; + // If read fails, write anyway (we already wrote size in the header). + if (nlen != readall(fd, toybuf, nlen)) + if (!error++) perror_msg("bad read from file '%s'", name); + xwrite(TT.outfd, toybuf, nlen); } - if (buf.st_size & 3) write(1, &n, 4 - (buf.st_size & 3)); + llen = buf.st_size & 3; + if (nlen) write(TT.outfd, &zero, 4-llen); } // Iterate through a list of files read from stdin. No users need rw. @@ -225,6 +229,8 @@ void cpio_main(void) { + TT.outfd = 1; + if (TT.archive) { if (toys.optflags & (FLAG_i|FLAG_t)) { xclose(0);