Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Mar 2013 23:46:47 GMT
From:      Brooks Davis <brooks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 222732 for review
Message-ID:  <201303082346.r28NklFm057001@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@222732?ac=10

Change 222732 by brooks@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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303082346.r28NklFm057001>