PERFORCE change 222732 for review
Brooks Davis
brooks at FreeBSD.org
Fri Mar 8 23:46:48 UTC 2013
http://p4web.freebsd.org/@@222732?ac=10
Change 222732 by brooks at brooks_zenith on 2013/03/08 23:46:06
Refactor to remove globals from the extract and verify code.
Add some default output on success.
Affected files ...
.. //depot/projects/ctsrd/beribsd/src/ctsrd/writefile/writefile.c#2 edit
Differences ...
==== //depot/projects/ctsrd/beribsd/src/ctsrd/writefile/writefile.c#2 (text+ko) ====
@@ -46,23 +46,35 @@
enum eav_error {
EAV_SUCCESS = 0,
- EAV_MEM,
- EAV_MD5,
- EAV_COMP_UNKNOWN,
- EAV_COMP_UNSUPPORTED,
- EAV_COMP_BZ
+ EAV_ERR_MEM,
+ EAV_ERR_DIGEST,
+ EAV_ERR_DIGEST_UNKNOWN,
+ EAV_ERR_COMP,
+ EAV_ERR_COMP_UNKNOWN,
+ EAV_ERR_COMP_UNSUPPORTED
+};
+
+enum eav_digest {
+ EAV_DIGEST_NONE = 0,
+ EAV_DIGEST_MD5
+};
+
+enum eav_compression {
+ EAV_COMP_NONE = 0,
+ EAV_COMP_BZIP2,
+ EAV_COMP_GZIP,
+ EAV_COMP_XZ,
+
+ EAV_COMP_UNKNOWN
};
static void usage(int) __dead2;
-int verify;
-char *md5sum;
-
static void
usage(int error)
{
fprintf(stderr,
-"writefile [-hTvz] [-b <blocksize>] [-i <iseek>] [-l length] [-m md5]\n"
+"writefile [-hqTvz] [-b <blocksize>] [-i <iseek>] [-l length] [-m md5]\n"
" [-o <oseek>] <in file> <out file>\n");
exit(error);
}
@@ -87,6 +99,41 @@
return(len);
}
+static enum eav_compression
+eav_taste(const unsigned char *buf, off_t len)
+{
+
+ /*
+ * BZIP header from wikipedia:
+ * .magic:16 = 'BZ' signature/magic number
+ * .version:8 = 'h' for Bzip2
+ * ('H'uffman coding),
+ * '0' for Bzip1 (deprecated)
+ * .hundred_k_blocksize:8 = '1'..'9'
+ * block-size 100 kB-900 kB
+ * .compressed_magic:48 =
+ * 0x314159265359 (BCD (pi))
+ */
+ if( len > 10 && buf[0] == 'B' && buf[1] == 'Z' &&
+ buf[4] == 0x31 && buf[5] == 0x41 && buf[6] == 0x59 &&
+ buf[7] == 0x26 && buf[8] == 0x53 && buf[9] == 0x59) {
+ if (buf[2] == 'h')
+ return (EAV_COMP_BZIP2);
+ else
+ /* Could be bzip 1, but that is unsupported */
+ return (EAV_COMP_UNKNOWN);
+ } else if (len > 2 && buf[0] == 0x1f && buf[1] == 0x8b) {
+ /* gzip per RFC1952 */
+ return (EAV_COMP_GZIP);
+ } else if (len > 6 && buf[0] == 0xfd && buf[1] == '7' &&
+ buf[2] == 'z' && buf[3] == 'X' &&
+ buf[4] == 'Z' && buf[5] == 0x00) {
+ /* XZ per Wikipedia */
+ return (EAV_COMP_XZ);
+ } else
+ return (EAV_COMP_UNKNOWN);
+}
+
static const char *
eav_strerror(enum eav_error error)
{
@@ -94,16 +141,18 @@
switch (error) {
case EAV_SUCCESS:
return "Success";
- case EAV_MEM:
+ case EAV_ERR_MEM:
return "malloc error";
- case EAV_MD5:
- return "MD5 checksum mismatch";
- case EAV_COMP_UNKNOWN:
+ case EAV_ERR_DIGEST:
+ return "checksum mismatch";
+ case EAV_ERR_DIGEST_UNKNOWN:
+ return "unknown digest";
+ case EAV_ERR_COMP:
+ return "decompression error";
+ case EAV_ERR_COMP_UNKNOWN:
return "Unknown compression type";
- case EAV_COMP_UNSUPPORTED:
+ case EAV_ERR_COMP_UNSUPPORTED:
return "Unsupported compression type";
- case EAV_COMP_BZ:
- return "bzip2 error";
default:
return "Unknown error";
}
@@ -111,7 +160,9 @@
static enum eav_error
extract_and_verify(unsigned char *ibuf, size_t ilen,
- unsigned char **obufp, size_t *olenp, size_t blocksize, int decompress)
+ unsigned char **obufp, size_t *olenp, size_t blocksize,
+ enum eav_compression ctype,
+ enum eav_digest dtype, const unsigned char *digest)
{
int ret;
char *obuf = NULL;
@@ -120,44 +171,37 @@
MD5_CTX md5ctx;
char i_md5sum[33];
- if (decompress || md5sum != NULL) {
- if (md5sum != NULL)
+ switch (ctype) {
+ case EAV_COMP_NONE:
+ case EAV_COMP_BZIP2:
+ break;
+ case EAV_COMP_GZIP:
+ case EAV_COMP_XZ:
+ return (EAV_ERR_COMP_UNSUPPORTED);
+ default:
+ return (EAV_ERR_COMP_UNKNOWN);
+ }
+
+ switch (dtype) {
+ case EAV_DIGEST_NONE:
+ case EAV_DIGEST_MD5:
+ break;
+ default:
+ return (EAV_ERR_DIGEST_UNKNOWN);
+ }
+
+ if (dtype || ctype) {
+ if (dtype == EAV_DIGEST_MD5)
MD5Init(&md5ctx);
- if (decompress) {
- /*
- * BZIP header from wikipedia:
- * .magic:16 = 'BZ' signature/magic number
- * .version:8 = 'h' for Bzip2
- * ('H'uffman coding),
- * '0' for Bzip1 (deprecated)
- * .hundred_k_blocksize:8 = '1'..'9'
- * block-size 100 kB-900 kB
- * .compressed_magic:48 =
- * 0x314159265359 (BCD (pi))
- */
- if(ibuf[0] == 'B' && ibuf[1] == 'Z' &&
- ibuf[4] == 0x31 && ibuf[5] == 0x41 &&
- ibuf[6] == 0x59 && ibuf[7] == 0x26 &&
- ibuf[8] == 0x53 && ibuf[9] == 0x59) {
- if (ibuf[2] != 'h')
- return (EAV_COMP_UNSUPPORTED);
- } else if (ibuf[0] == 0x1f && ibuf[1] == 0x8b) {
- /* gzip per RFC1952 */
- return (EAV_COMP_UNSUPPORTED);
- } else if (ibuf[0] == 0xfd && ibuf[1] == '7' &&
- ibuf[2] == 'z' && ibuf[3] == 'X' &&
- ibuf[4] == 'Z' && ibuf[5] == 0x00) {
- /* XZ per Wikipedia */
- return (EAV_COMP_UNSUPPORTED);
- } else
- return (EAV_COMP_UNKNOWN);
-
+ if (ctype) {
+ /* XXX: assume bzip2 for now */
olen = 1024 * 1024;
if ((obuf = malloc(olen)) == NULL)
- return (EAV_MEM);
+ return (EAV_ERR_MEM);
- /* XXX: assume bzip2 for now */
+ total_in = 0;
+ prev_total_in = 0;
bzs.bzalloc = NULL;
bzs.bzfree = NULL;
@@ -166,17 +210,15 @@
bzs.avail_in = MIN(ilen, 1024 * 1024);
bzs.next_out = obuf;
bzs.avail_out = olen;
- total_in = 0;
- prev_total_in = 0;
if (BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK)
- return (EAV_COMP_BZ);
+ return (EAV_ERR_COMP);
while ((ret = BZ2_bzDecompress(&bzs)) !=
BZ_STREAM_END) {
if (ret != BZ_OK) {
free(obuf);
BZ2_bzDecompressEnd(&bzs);
- return (EAV_COMP_BZ);
+ return (EAV_ERR_COMP);
}
total_in = ((size_t)bzs.total_in_hi32 << 32) +
@@ -184,8 +226,9 @@
total_out = ((size_t)bzs.total_out_hi32 << 32) +
bzs.total_out_lo32;
- MD5Update(&md5ctx, ibuf + prev_total_in,
- total_in - prev_total_in);
+ if (dtype == EAV_DIGEST_MD5)
+ MD5Update(&md5ctx, ibuf + prev_total_in,
+ total_in - prev_total_in);
prev_total_in = total_in;
if (bzs.avail_in == 0)
@@ -197,12 +240,10 @@
if ((obuf = reallocf(obuf, olen))
== NULL) {
BZ2_bzDecompressEnd(&bzs);
- return (EAV_COMP_BZ);
+ return (EAV_ERR_COMP);
}
- bzs.next_out =
- obuf + total_out;
- bzs.avail_out =
- olen - total_out;
+ bzs.next_out = obuf + total_out;
+ bzs.avail_out = olen - total_out;
}
}
BZ2_bzDecompressEnd(&bzs);
@@ -212,9 +253,9 @@
bzs.total_out_lo32;
/* Push the last read block in the MD5 machine */
- MD5Update(&md5ctx, ibuf + prev_total_in,
- total_in - prev_total_in);
- prev_total_in = total_in;
+ if (dtype == EAV_DIGEST_MD5)
+ MD5Update(&md5ctx, ibuf + prev_total_in,
+ total_in - prev_total_in);
/* Round up to blocksize and zero pad */
olen = roundup2(total_out, blocksize);
@@ -222,17 +263,21 @@
memset(obuf + total_out, '\0',
olen - total_out);
/* XXX: realloc to shorten allocation? */
- } else if (md5sum != NULL)
- MD5Update(&md5ctx, ibuf, ilen);
+ } else if (dtype) {
+ if (dtype == EAV_DIGEST_MD5)
+ MD5Update(&md5ctx, ibuf, ilen);
+ }
- if (md5sum != NULL) {
- MD5End(&md5ctx, i_md5sum);
- if (strcmp(md5sum, i_md5sum) != 0)
- return (EAV_MD5);
+ if (dtype) {
+ if (dtype == EAV_DIGEST_MD5) {
+ MD5End(&md5ctx, i_md5sum);
+ if (strcmp(digest, i_md5sum) != 0)
+ return (EAV_ERR_DIGEST);
+ }
}
}
- if (!decompress) {
+ if (ctype == EAV_COMP_NONE) {
*obufp = ibuf;
*olenp = ilen;
} else {
@@ -263,14 +308,17 @@
int
main(int argc, char *argv[])
{
- char ch, *cp;
+ char ch, *cp, *digest = NULL;
unsigned char *ibuf, *obuf = NULL, *vbuf;
size_t blocksize = 0;
off_t iseek = 0, oseek = 0, olen = -1, wlen = -1;
- int decompress = 0, ifd, notruncate = 0, ofd, ret;
+ int decompress = 0, ifd, notruncate = 0, ofd, quiet = 0, ret,
+ verify_write = 0;
+ enum eav_compression ctype;
+ enum eav_digest dtype = EAV_DIGEST_NONE;
struct stat isb, osb;
- while ((ch = getopt(argc, argv, "b:hi:l:m:o:Tvz")) != -1) {
+ while ((ch = getopt(argc, argv, "b:hi:l:m:o:qTvz")) != -1) {
switch (ch) {
case 'b':
if ((blocksize = parse_offset(optarg)) < 1)
@@ -287,10 +335,15 @@
warnx("Invalid length %s", optarg);
break;
case 'm':
- md5sum = optarg;
- if (strlen(optarg) != 32)
+ if (dtype != EAV_DIGEST_NONE) {
+ warnx("Too many digest options");
+ usage(1j);
+ }
+ dtype = EAV_DIGEST_MD5;
+ digest = optarg;
+ if (strlen(digest) != 32)
warnx("invalid md5 checksum");
- for (cp = md5sum; *cp != '\0'; cp++) {
+ for (cp = digest; *cp != '\0'; cp++) {
if (!isxdigit(*cp))
warnx("invalid md5 checksum");
*cp = tolower(*cp);
@@ -300,11 +353,14 @@
if ((oseek = parse_offset(optarg)) < 1)
warnx("Invalid output seek %s", optarg);
break;
+ case 'q':
+ quiet = 1;
+ break;
case 'T':
notruncate = 1;
break;
case 'v':
- verify = 1;
+ verify_write = 1;
break;
case 'z':
decompress = 1;
@@ -335,11 +391,23 @@
blocksize = 1;
}
+ if (decompress)
+ ctype = eav_taste(ibuf, isb.st_size);
+ else
+ ctype = EAV_COMP_NONE;
+
if ((ret = extract_and_verify(ibuf, isb.st_size, &obuf, &olen,
- blocksize, decompress)) != EAV_SUCCESS)
+ blocksize, ctype, dtype, digest)) != EAV_SUCCESS)
errx(1, "failed to extract and verify %s: %s", argv[0],
eav_strerror(ret));
+ if (!quiet) {
+ if (dtype)
+ printf("verified %jd input bytes\n", isb.st_size);
+ if (ctype && ctype != EAV_COMP_UNKNOWN)
+ printf("extracted %jd bytes\n", olen);
+ }
+
if (wlen == -1)
wlen = olen - iseek;
else if (wlen > olen - iseek) {
@@ -366,8 +434,11 @@
/* Explict close to force final writes to flash etc. */
close(ofd);
+ if (!quiet)
+ printf("wrote %jd bytes\n", wlen);
+
/* XXX: won't work if you can't map olen + oseek even with small olen */
- if (verify) {
+ if (verify_write) {
if ((ofd = open(argv[1], O_RDONLY)) == -1)
err(1, "open(%s)", argv[1]);
if ((vbuf = mmap(NULL, wlen + oseek, PROT_READ, MAP_PRIVATE,
@@ -375,6 +446,8 @@
err(1, "mmap(%s)", argv[1]);
if (memcmp(obuf + iseek, vbuf + oseek, wlen) != 0)
err(1, "output file does not match input!");
+ if (!quiet)
+ printf("verified %jd written bytes\n", wlen);
}
if (obuf != ibuf)
More information about the p4-projects
mailing list