svn commit: r260142 - head/cddl/contrib/opensolaris/cmd/zstreamdump

Xin LI delphij at FreeBSD.org
Tue Dec 31 21:37:25 UTC 2013


Author: delphij
Date: Tue Dec 31 21:37:24 2013
New Revision: 260142
URL: http://svnweb.freebsd.org/changeset/base/260142

Log:
  MFV r258972:
  
  4373 add block contents print to zstreamdump
  
  illumos/illumos-gate at 994fb6b8a9d07a8021d77d79f46e30637bca3ad3
  
  MFC after:	2 weeks

Modified:
  head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.1
  head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.c
Directory Properties:
  head/cddl/contrib/opensolaris/   (props changed)

Modified: head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.1
==============================================================================
--- head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.1	Tue Dec 31 21:24:00 2013	(r260141)
+++ head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.1	Tue Dec 31 21:37:24 2013	(r260142)
@@ -18,10 +18,11 @@
 .\" information: Portions Copyright [yyyy] [name of copyright owner]
 .\"
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright (c) 2013, Delphix. All Rights Reserved.
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 26, 2011
+.Dd December 31, 2013
 .Dt ZSTREAMDUMP 8
 .Os
 .Sh NAME
@@ -30,6 +31,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl C
+.Op Fl d
 .Op Fl v
 .Sh DESCRIPTION
 The
@@ -43,6 +45,8 @@ The following options are supported:
 .Bl -tag -width indent
 .It Fl C
 Suppress the validation of checksums.
+.It Fl d
+Dump contents of blocks modified, implies verbose.
 .It Fl v
 Verbose. Dump all headers, not only begin and end headers.
 .El

Modified: head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.c
==============================================================================
--- head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.c	Tue Dec 31 21:24:00 2013	(r260141)
+++ head/cddl/contrib/opensolaris/cmd/zstreamdump/zstreamdump.c	Tue Dec 31 21:37:24 2013	(r260142)
@@ -24,6 +24,11 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
+
+#include <ctype.h>
 #include <libnvpair.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,6 +39,16 @@
 #include <sys/zfs_ioctl.h>
 #include <zfs_fletcher.h>
 
+/*
+ * If dump mode is enabled, the number of bytes to print per line
+ */
+#define	BYTES_PER_LINE	16
+/*
+ * If dump mode is enabled, the number of bytes to group together, separated
+ * by newlines or spaces
+ */
+#define	DUMP_GROUPING	4
+
 uint64_t drr_record_count[DRR_NUMTYPES];
 uint64_t total_write_size = 0;
 uint64_t total_stream_len = 0;
@@ -45,9 +60,11 @@ boolean_t do_cksum = B_TRUE;
 static void
 usage(void)
 {
-	(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] < file\n");
+	(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
 	(void) fprintf(stderr, "\t -v -- verbose\n");
 	(void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
+	(void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
+	    "implies verbose\n");
 	exit(1);
 }
 
@@ -75,6 +92,70 @@ ssread(void *buf, size_t len, zio_cksum_
 	return (outlen);
 }
 
+/*
+ * Print part of a block in ASCII characters
+ */
+static void
+print_ascii_block(char *subbuf, int length)
+{
+	int i;
+
+	for (i = 0; i < length; i++) {
+		char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
+		if (i != 0 && i % DUMP_GROUPING == 0) {
+			(void) printf(" ");
+		}
+		(void) printf("%c", char_print);
+	}
+	(void) printf("\n");
+}
+
+/*
+ * print_block - Dump the contents of a modified block to STDOUT
+ *
+ * Assume that buf has capacity evenly divisible by BYTES_PER_LINE
+ */
+static void
+print_block(char *buf, int length)
+{
+	int i;
+	/*
+	 * Start printing ASCII characters at a constant offset, after
+	 * the hex prints. Leave 3 characters per byte on a line (2 digit
+	 * hex number plus 1 space) plus spaces between characters and
+	 * groupings
+	 */
+	int ascii_start = BYTES_PER_LINE * 3 +
+	    BYTES_PER_LINE / DUMP_GROUPING + 2;
+
+	for (i = 0; i < length; i += BYTES_PER_LINE) {
+		int j;
+		int this_line_length = MIN(BYTES_PER_LINE, length - i);
+		int print_offset = 0;
+
+		for (j = 0; j < this_line_length; j++) {
+			int buf_offset = i + j;
+
+			/*
+			 * Separate every DUMP_GROUPING bytes by a space.
+			 */
+			if (buf_offset % DUMP_GROUPING == 0) {
+				print_offset += printf(" ");
+			}
+
+			/*
+			 * Print the two-digit hex value for this byte.
+			 */
+			unsigned char hex_print = buf[buf_offset];
+			print_offset += printf("%02x ", hex_print);
+		}
+
+		(void) printf("%*s", ascii_start - print_offset, " ");
+
+		print_ascii_block(buf + i, this_line_length);
+	}
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -92,11 +173,17 @@ main(int argc, char *argv[])
 	char c;
 	boolean_t verbose = B_FALSE;
 	boolean_t first = B_TRUE;
+	/*
+	 * dump flag controls whether the contents of any modified data blocks
+	 * are printed to the console during processing of the stream. Warning:
+	 * for large streams, this can obviously lead to massive prints.
+	 */
+	boolean_t dump = B_FALSE;
 	int err;
 	zio_cksum_t zc = { 0 };
 	zio_cksum_t pcksum = { 0 };
 
-	while ((c = getopt(argc, argv, ":vC")) != -1) {
+	while ((c = getopt(argc, argv, ":vCd")) != -1) {
 		switch (c) {
 		case 'C':
 			do_cksum = B_FALSE;
@@ -104,6 +191,10 @@ main(int argc, char *argv[])
 		case 'v':
 			verbose = B_TRUE;
 			break;
+		case 'd':
+			dump = B_TRUE;
+			verbose = B_TRUE;
+			break;
 		case ':':
 			(void) fprintf(stderr,
 			    "missing argument for '%c' option\n", optopt);
@@ -128,6 +219,10 @@ main(int argc, char *argv[])
 	pcksum = zc;
 	while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
 
+		/*
+		 * If this is the first DMU record being processed, check for
+		 * the magic bytes and figure out the endian-ness based on them.
+		 */
 		if (first) {
 			if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
 				do_byteswap = B_TRUE;
@@ -209,7 +304,7 @@ main(int argc, char *argv[])
 				nvlist_t *nv;
 				int sz = drr->drr_payloadlen;
 
-				if (sz > 1<<20) {
+				if (sz > INITIAL_BUFLEN) {
 					free(buf);
 					buf = malloc(sz);
 				}
@@ -283,6 +378,10 @@ main(int argc, char *argv[])
 			if (drro->drr_bonuslen > 0) {
 				(void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen,
 				    8), &zc);
+				if (dump) {
+					print_block(buf,
+					    P2ROUNDUP(drro->drr_bonuslen, 8));
+				}
 			}
 			break;
 
@@ -312,6 +411,10 @@ main(int argc, char *argv[])
 				drrw->drr_key.ddk_prop =
 				    BSWAP_64(drrw->drr_key.ddk_prop);
 			}
+			/*
+			 * If this is verbose and/or dump output,
+			 * print info on the modified block
+			 */
 			if (verbose) {
 				(void) printf("WRITE object = %llu type = %u "
 				    "checksum type = %u\n"
@@ -324,7 +427,16 @@ main(int argc, char *argv[])
 				    (u_longlong_t)drrw->drr_length,
 				    (u_longlong_t)drrw->drr_key.ddk_prop);
 			}
+			/*
+			 * Read the contents of the block in from STDIN to buf
+			 */
 			(void) ssread(buf, drrw->drr_length, &zc);
+			/*
+			 * If in dump mode
+			 */
+			if (dump) {
+				print_block(buf, drrw->drr_length);
+			}
 			total_write_size += drrw->drr_length;
 			break;
 
@@ -390,6 +502,9 @@ main(int argc, char *argv[])
 				    drrs->drr_length);
 			}
 			(void) ssread(buf, drrs->drr_length, &zc);
+			if (dump) {
+				print_block(buf, drrs->drr_length);
+			}
 			break;
 		}
 		pcksum = zc;


More information about the svn-src-head mailing list