495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * CDDL HEADER START
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * The contents of this file are subject to the terms of the
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * Common Development and Distribution License (the "License").
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * You may not use this file except in compliance with the License.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * See the License for the specific language governing permissions
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * and limitations under the License.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * When distributing Covered Code, include this CDDL HEADER in each
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * If applicable, add the following below this CDDL HEADER, with the
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * fields enclosed by brackets "[]" replaced with your own identifying
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * information: Portions Copyright [yyyy] [name of copyright owner]
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * CDDL HEADER END
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * Use is subject to license terms.
c3d26abc9ee97b4f60233556aadeb57e0bd30bb9Matthew Ahrens * Copyright (c) 2014 Integros [integros.com]
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * If dump mode is enabled, the number of bytes to print per line
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * If dump mode is enabled, the number of bytes to group together, separated
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * by newlines or spaces
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman (void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman (void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman "implies verbose\n");
b515258426fed6c7311fd3f1dea697cfbd4085c6Matthew Ahrens (void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * ssread - send stream read.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * Read while computing incremental checksum
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt if ((outlen = fread(buf, len, 1, send_stream)) == 0)
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt return (0);
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrensread_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens size_t r = ssread(drr, sizeof (*drr) - sizeof (zio_cksum_t), cksum);
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens r = ssread(&drr->drr_u.drr_checksum.drr_checksum,
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens if (!ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.drr_checksum.drr_checksum) &&
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens (void) printf("Incorrect checksum in record header.\n");
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens (void) printf("Expected checksum = %llx/%llx/%llx/%llx\n",
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens return (sizeof (*drr));
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Print part of a block in ASCII characters
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman for (i = 0; i < length; i++) {
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman if (i != 0 && i % DUMP_GROUPING == 0) {
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * print_block - Dump the contents of a modified block to STDOUT
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Assume that buf has capacity evenly divisible by BYTES_PER_LINE
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Start printing ASCII characters at a constant offset, after
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * the hex prints. Leave 3 characters per byte on a line (2 digit
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * hex number plus 1 space) plus spaces between characters and
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman int this_line_length = MIN(BYTES_PER_LINE, length - i);
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman for (j = 0; j < this_line_length; j++) {
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Separate every DUMP_GROUPING bytes by a space.
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Print the two-digit hex value for this byte.
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman (void) printf("%*s", ascii_start - print_offset, " ");
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt struct drr_object *drro = &thedrr.drr_u.drr_object;
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt struct drr_freeobjects *drrfo = &thedrr.drr_u.drr_freeobjects;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt struct drr_write_byref *drrwbr = &thedrr.drr_u.drr_write_byref;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * dump flag controls whether the contents of any modified data blocks
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * are printed to the console during processing of the stream. Warning:
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * for large streams, this can obviously lead to massive prints.
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman while ((c = getopt(argc, argv, ":vCd")) != -1) {
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt switch (c) {
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "Error: Backup stream can not be read "
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "from a terminal.\n"
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "You must redirect standard input.\n");
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * If this is the first DMU record being processed, check for
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * the magic bytes and figure out the endian-ness based on them.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * recalculate header checksum now
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * that we know it needs to be
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * byteswapped.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "(bad magic number)\n");
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * At this point, the leading fields of the replay record
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * (drr_type and drr_payloadlen) have been byte-swapped if
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * necessary, but the rest of the data structure (the
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * union of type-specific structures) is still in its
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * original state.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tflags = 0x%x\n", drrb->drr_flags);
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\ttoname = %s\n", drrb->drr_toname);
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * We compare against the *previous* checksum
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * value, because the stored checksum is of
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt * everything before the DRR_END record.
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt if (do_cksum && !ZIO_CHECKSUM_EQUAL(drre->drr_checksum,
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "checksum in stream.\n");
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "%llx/%llx/%llx/%llx\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("END checksum = %llx/%llx/%llx/%llx\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "bonustype = %u blksz = %u bonuslen = %u\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "numobjs = %llu\n",
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel uint64_t payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * If this is verbose and/or dump output,
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * print info on the modified block
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel "checksum type = %u compression type = %u\n"
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel " offset = %llu logical_size = %llu "
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel "compressed_size = %llu "
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel "payload_size = %llu "
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt "props = %llx\n",
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * Read the contents of the block in from STDIN to buf
994fb6b8a9d07a8021d77d79f46e30637bca3ad3Max Grossman * If in dump mode
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt "checksum type = %u props = %llx\n"
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens " offset = %llu length = %llu\n"
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt "toguid = %llx refguid = %llx\n"
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens " refobject = %llu refoffset = %llu\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt "offset = %llu length = %lld\n",
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_object = BSWAP_64(drrs->drr_object);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_length = BSWAP_64(drrs->drr_length);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (void) printf("SPILL block for object = %llu "
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens (void) printf("WRITE_EMBEDDED object = %llu "
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens "offset = %llu length = %llu\n"
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens " toguid = %llx comp = %u etype = %u "
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens "lsize = %u psize = %u\n",
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens if (drr->drr_type != DRR_BEGIN && very_verbose) {
98110f08fa182032082d98be2ddb9391fcd62bf1Matthew Ahrens (void) printf(" checksum = %llx/%llx/%llx/%llx\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt /* Print final summary */
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal DRR_BEGIN records = %lld\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal DRR_OBJECT records = %lld\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal DRR_FREEOBJECTS records = %lld\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal DRR_WRITE records = %lld\n",
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens (void) printf("\tTotal DRR_WRITE_BYREF records = %lld\n",
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens (u_longlong_t)drr_record_count[DRR_WRITE_BYREF]);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens (void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld\n",
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens (u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED]);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (void) printf("\tTotal DRR_SPILL records = %lld\n",
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (u_longlong_t)drr_record_count[DRR_SPILL]);
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal write size = %lld (0x%llx)\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (u_longlong_t)total_write_size, (u_longlong_t)total_write_size);
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (void) printf("\tTotal stream length = %lld (0x%llx)\n",
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt (u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len);
495db6fbcd9e8ab893e91f6f5627df6e0cec63cfLori Alt return (0);