1495db6fbSLori Alt /* 2495db6fbSLori Alt * CDDL HEADER START 3495db6fbSLori Alt * 4495db6fbSLori Alt * The contents of this file are subject to the terms of the 5495db6fbSLori Alt * Common Development and Distribution License (the "License"). 6495db6fbSLori Alt * You may not use this file except in compliance with the License. 7495db6fbSLori Alt * 8495db6fbSLori Alt * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9495db6fbSLori Alt * or http://www.opensolaris.org/os/licensing. 10495db6fbSLori Alt * See the License for the specific language governing permissions 11495db6fbSLori Alt * and limitations under the License. 12495db6fbSLori Alt * 13495db6fbSLori Alt * When distributing Covered Code, include this CDDL HEADER in each 14495db6fbSLori Alt * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15495db6fbSLori Alt * If applicable, add the following below this CDDL HEADER, with the 16495db6fbSLori Alt * fields enclosed by brackets "[]" replaced with your own identifying 17495db6fbSLori Alt * information: Portions Copyright [yyyy] [name of copyright owner] 18495db6fbSLori Alt * 19495db6fbSLori Alt * CDDL HEADER END 20495db6fbSLori Alt */ 21495db6fbSLori Alt 22495db6fbSLori Alt /* 230a586ceaSMark Shellenbaum * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24495db6fbSLori Alt * Use is subject to license terms. 25495db6fbSLori Alt */ 26495db6fbSLori Alt 27*994fb6b8SMax Grossman /* 28*994fb6b8SMax Grossman * Copyright (c) 2013 by Delphix. All rights reserved. 29*994fb6b8SMax Grossman */ 30*994fb6b8SMax Grossman 31*994fb6b8SMax Grossman #include <ctype.h> 32495db6fbSLori Alt #include <libnvpair.h> 33495db6fbSLori Alt #include <stdio.h> 34495db6fbSLori Alt #include <stdlib.h> 35495db6fbSLori Alt #include <strings.h> 36495db6fbSLori Alt #include <unistd.h> 37495db6fbSLori Alt 38495db6fbSLori Alt #include <sys/dmu.h> 39495db6fbSLori Alt #include <sys/zfs_ioctl.h> 40495db6fbSLori Alt #include <zfs_fletcher.h> 41495db6fbSLori Alt 42*994fb6b8SMax Grossman /* 43*994fb6b8SMax Grossman * If dump mode is enabled, the number of bytes to print per line 44*994fb6b8SMax Grossman */ 45*994fb6b8SMax Grossman #define BYTES_PER_LINE 16 46*994fb6b8SMax Grossman /* 47*994fb6b8SMax Grossman * If dump mode is enabled, the number of bytes to group together, separated 48*994fb6b8SMax Grossman * by newlines or spaces 49*994fb6b8SMax Grossman */ 50*994fb6b8SMax Grossman #define DUMP_GROUPING 4 51*994fb6b8SMax Grossman 52495db6fbSLori Alt uint64_t drr_record_count[DRR_NUMTYPES]; 53495db6fbSLori Alt uint64_t total_write_size = 0; 54495db6fbSLori Alt uint64_t total_stream_len = 0; 55495db6fbSLori Alt FILE *send_stream = 0; 56495db6fbSLori Alt boolean_t do_byteswap = B_FALSE; 57495db6fbSLori Alt boolean_t do_cksum = B_TRUE; 58495db6fbSLori Alt #define INITIAL_BUFLEN (1<<20) 59495db6fbSLori Alt 60495db6fbSLori Alt static void 61495db6fbSLori Alt usage(void) 62495db6fbSLori Alt { 63*994fb6b8SMax Grossman (void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n"); 64495db6fbSLori Alt (void) fprintf(stderr, "\t -v -- verbose\n"); 65495db6fbSLori Alt (void) fprintf(stderr, "\t -C -- suppress checksum verification\n"); 66*994fb6b8SMax Grossman (void) fprintf(stderr, "\t -d -- dump contents of blocks modified, " 67*994fb6b8SMax Grossman "implies verbose\n"); 68495db6fbSLori Alt exit(1); 69495db6fbSLori Alt } 70495db6fbSLori Alt 71495db6fbSLori Alt /* 72495db6fbSLori Alt * ssread - send stream read. 73495db6fbSLori Alt * 74495db6fbSLori Alt * Read while computing incremental checksum 75495db6fbSLori Alt */ 76495db6fbSLori Alt 77495db6fbSLori Alt static size_t 78495db6fbSLori Alt ssread(void *buf, size_t len, zio_cksum_t *cksum) 79495db6fbSLori Alt { 80495db6fbSLori Alt size_t outlen; 81495db6fbSLori Alt 82495db6fbSLori Alt if ((outlen = fread(buf, len, 1, send_stream)) == 0) 83495db6fbSLori Alt return (0); 84495db6fbSLori Alt 85495db6fbSLori Alt if (do_cksum && cksum) { 86495db6fbSLori Alt if (do_byteswap) 87495db6fbSLori Alt fletcher_4_incremental_byteswap(buf, len, cksum); 88495db6fbSLori Alt else 89495db6fbSLori Alt fletcher_4_incremental_native(buf, len, cksum); 90495db6fbSLori Alt } 91495db6fbSLori Alt total_stream_len += len; 92495db6fbSLori Alt return (outlen); 93495db6fbSLori Alt } 94495db6fbSLori Alt 95*994fb6b8SMax Grossman /* 96*994fb6b8SMax Grossman * Print part of a block in ASCII characters 97*994fb6b8SMax Grossman */ 98*994fb6b8SMax Grossman static void 99*994fb6b8SMax Grossman print_ascii_block(char *subbuf, int length) 100*994fb6b8SMax Grossman { 101*994fb6b8SMax Grossman int i; 102*994fb6b8SMax Grossman 103*994fb6b8SMax Grossman for (i = 0; i < length; i++) { 104*994fb6b8SMax Grossman char char_print = isprint(subbuf[i]) ? subbuf[i] : '.'; 105*994fb6b8SMax Grossman if (i != 0 && i % DUMP_GROUPING == 0) { 106*994fb6b8SMax Grossman (void) printf(" "); 107*994fb6b8SMax Grossman } 108*994fb6b8SMax Grossman (void) printf("%c", char_print); 109*994fb6b8SMax Grossman } 110*994fb6b8SMax Grossman (void) printf("\n"); 111*994fb6b8SMax Grossman } 112*994fb6b8SMax Grossman 113*994fb6b8SMax Grossman /* 114*994fb6b8SMax Grossman * print_block - Dump the contents of a modified block to STDOUT 115*994fb6b8SMax Grossman * 116*994fb6b8SMax Grossman * Assume that buf has capacity evenly divisible by BYTES_PER_LINE 117*994fb6b8SMax Grossman */ 118*994fb6b8SMax Grossman static void 119*994fb6b8SMax Grossman print_block(char *buf, int length) 120*994fb6b8SMax Grossman { 121*994fb6b8SMax Grossman int i; 122*994fb6b8SMax Grossman /* 123*994fb6b8SMax Grossman * Start printing ASCII characters at a constant offset, after 124*994fb6b8SMax Grossman * the hex prints. Leave 3 characters per byte on a line (2 digit 125*994fb6b8SMax Grossman * hex number plus 1 space) plus spaces between characters and 126*994fb6b8SMax Grossman * groupings 127*994fb6b8SMax Grossman */ 128*994fb6b8SMax Grossman int ascii_start = BYTES_PER_LINE * 3 + 129*994fb6b8SMax Grossman BYTES_PER_LINE / DUMP_GROUPING + 2; 130*994fb6b8SMax Grossman 131*994fb6b8SMax Grossman for (i = 0; i < length; i += BYTES_PER_LINE) { 132*994fb6b8SMax Grossman int j; 133*994fb6b8SMax Grossman int this_line_length = MIN(BYTES_PER_LINE, length - i); 134*994fb6b8SMax Grossman int print_offset = 0; 135*994fb6b8SMax Grossman 136*994fb6b8SMax Grossman for (j = 0; j < this_line_length; j++) { 137*994fb6b8SMax Grossman int buf_offset = i + j; 138*994fb6b8SMax Grossman 139*994fb6b8SMax Grossman /* 140*994fb6b8SMax Grossman * Separate every DUMP_GROUPING bytes by a space. 141*994fb6b8SMax Grossman */ 142*994fb6b8SMax Grossman if (buf_offset % DUMP_GROUPING == 0) { 143*994fb6b8SMax Grossman print_offset += printf(" "); 144*994fb6b8SMax Grossman } 145*994fb6b8SMax Grossman 146*994fb6b8SMax Grossman /* 147*994fb6b8SMax Grossman * Print the two-digit hex value for this byte. 148*994fb6b8SMax Grossman */ 149*994fb6b8SMax Grossman unsigned char hex_print = buf[buf_offset]; 150*994fb6b8SMax Grossman print_offset += printf("%02x ", hex_print); 151*994fb6b8SMax Grossman } 152*994fb6b8SMax Grossman 153*994fb6b8SMax Grossman (void) printf("%*s", ascii_start - print_offset, " "); 154*994fb6b8SMax Grossman 155*994fb6b8SMax Grossman print_ascii_block(buf + i, this_line_length); 156*994fb6b8SMax Grossman } 157*994fb6b8SMax Grossman } 158*994fb6b8SMax Grossman 159495db6fbSLori Alt int 160495db6fbSLori Alt main(int argc, char *argv[]) 161495db6fbSLori Alt { 162495db6fbSLori Alt char *buf = malloc(INITIAL_BUFLEN); 163495db6fbSLori Alt dmu_replay_record_t thedrr; 164495db6fbSLori Alt dmu_replay_record_t *drr = &thedrr; 165495db6fbSLori Alt struct drr_begin *drrb = &thedrr.drr_u.drr_begin; 166495db6fbSLori Alt struct drr_end *drre = &thedrr.drr_u.drr_end; 167495db6fbSLori Alt struct drr_object *drro = &thedrr.drr_u.drr_object; 168495db6fbSLori Alt struct drr_freeobjects *drrfo = &thedrr.drr_u.drr_freeobjects; 169495db6fbSLori Alt struct drr_write *drrw = &thedrr.drr_u.drr_write; 1709e69d7d0SLori Alt struct drr_write_byref *drrwbr = &thedrr.drr_u.drr_write_byref; 171495db6fbSLori Alt struct drr_free *drrf = &thedrr.drr_u.drr_free; 1720a586ceaSMark Shellenbaum struct drr_spill *drrs = &thedrr.drr_u.drr_spill; 173495db6fbSLori Alt char c; 174495db6fbSLori Alt boolean_t verbose = B_FALSE; 175495db6fbSLori Alt boolean_t first = B_TRUE; 176*994fb6b8SMax Grossman /* 177*994fb6b8SMax Grossman * dump flag controls whether the contents of any modified data blocks 178*994fb6b8SMax Grossman * are printed to the console during processing of the stream. Warning: 179*994fb6b8SMax Grossman * for large streams, this can obviously lead to massive prints. 180*994fb6b8SMax Grossman */ 181*994fb6b8SMax Grossman boolean_t dump = B_FALSE; 1828e714474SLori Alt int err; 183495db6fbSLori Alt zio_cksum_t zc = { 0 }; 184495db6fbSLori Alt zio_cksum_t pcksum = { 0 }; 185495db6fbSLori Alt 186*994fb6b8SMax Grossman while ((c = getopt(argc, argv, ":vCd")) != -1) { 187495db6fbSLori Alt switch (c) { 188495db6fbSLori Alt case 'C': 189495db6fbSLori Alt do_cksum = B_FALSE; 190495db6fbSLori Alt break; 191495db6fbSLori Alt case 'v': 192495db6fbSLori Alt verbose = B_TRUE; 193495db6fbSLori Alt break; 194*994fb6b8SMax Grossman case 'd': 195*994fb6b8SMax Grossman dump = B_TRUE; 196*994fb6b8SMax Grossman verbose = B_TRUE; 197*994fb6b8SMax Grossman break; 198495db6fbSLori Alt case ':': 199495db6fbSLori Alt (void) fprintf(stderr, 200495db6fbSLori Alt "missing argument for '%c' option\n", optopt); 201495db6fbSLori Alt usage(); 202495db6fbSLori Alt break; 203495db6fbSLori Alt case '?': 204495db6fbSLori Alt (void) fprintf(stderr, "invalid option '%c'\n", 205495db6fbSLori Alt optopt); 206495db6fbSLori Alt usage(); 207495db6fbSLori Alt } 208495db6fbSLori Alt } 209495db6fbSLori Alt 210495db6fbSLori Alt if (isatty(STDIN_FILENO)) { 211495db6fbSLori Alt (void) fprintf(stderr, 212495db6fbSLori Alt "Error: Backup stream can not be read " 213495db6fbSLori Alt "from a terminal.\n" 214495db6fbSLori Alt "You must redirect standard input.\n"); 215495db6fbSLori Alt exit(1); 216495db6fbSLori Alt } 217495db6fbSLori Alt 218495db6fbSLori Alt send_stream = stdin; 219495db6fbSLori Alt pcksum = zc; 220495db6fbSLori Alt while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) { 221495db6fbSLori Alt 222*994fb6b8SMax Grossman /* 223*994fb6b8SMax Grossman * If this is the first DMU record being processed, check for 224*994fb6b8SMax Grossman * the magic bytes and figure out the endian-ness based on them. 225*994fb6b8SMax Grossman */ 226495db6fbSLori Alt if (first) { 227495db6fbSLori Alt if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) { 228495db6fbSLori Alt do_byteswap = B_TRUE; 229495db6fbSLori Alt if (do_cksum) { 230495db6fbSLori Alt ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0); 231495db6fbSLori Alt /* 232495db6fbSLori Alt * recalculate header checksum now 233495db6fbSLori Alt * that we know it needs to be 234495db6fbSLori Alt * byteswapped. 235495db6fbSLori Alt */ 236495db6fbSLori Alt fletcher_4_incremental_byteswap(drr, 237495db6fbSLori Alt sizeof (dmu_replay_record_t), &zc); 238495db6fbSLori Alt } 239495db6fbSLori Alt } else if (drrb->drr_magic != DMU_BACKUP_MAGIC) { 240495db6fbSLori Alt (void) fprintf(stderr, "Invalid stream " 241495db6fbSLori Alt "(bad magic number)\n"); 242495db6fbSLori Alt exit(1); 243495db6fbSLori Alt } 244495db6fbSLori Alt first = B_FALSE; 245495db6fbSLori Alt } 246495db6fbSLori Alt if (do_byteswap) { 247495db6fbSLori Alt drr->drr_type = BSWAP_32(drr->drr_type); 248495db6fbSLori Alt drr->drr_payloadlen = 249495db6fbSLori Alt BSWAP_32(drr->drr_payloadlen); 250495db6fbSLori Alt } 251495db6fbSLori Alt 252495db6fbSLori Alt /* 253495db6fbSLori Alt * At this point, the leading fields of the replay record 254495db6fbSLori Alt * (drr_type and drr_payloadlen) have been byte-swapped if 255495db6fbSLori Alt * necessary, but the rest of the data structure (the 256495db6fbSLori Alt * union of type-specific structures) is still in its 257495db6fbSLori Alt * original state. 258495db6fbSLori Alt */ 259495db6fbSLori Alt if (drr->drr_type >= DRR_NUMTYPES) { 260495db6fbSLori Alt (void) printf("INVALID record found: type 0x%x\n", 261495db6fbSLori Alt drr->drr_type); 262495db6fbSLori Alt (void) printf("Aborting.\n"); 263495db6fbSLori Alt exit(1); 264495db6fbSLori Alt } 265495db6fbSLori Alt 266495db6fbSLori Alt drr_record_count[drr->drr_type]++; 267495db6fbSLori Alt 268495db6fbSLori Alt switch (drr->drr_type) { 269495db6fbSLori Alt case DRR_BEGIN: 270495db6fbSLori Alt if (do_byteswap) { 271495db6fbSLori Alt drrb->drr_magic = BSWAP_64(drrb->drr_magic); 2729e69d7d0SLori Alt drrb->drr_versioninfo = 2739e69d7d0SLori Alt BSWAP_64(drrb->drr_versioninfo); 274495db6fbSLori Alt drrb->drr_creation_time = 275495db6fbSLori Alt BSWAP_64(drrb->drr_creation_time); 276495db6fbSLori Alt drrb->drr_type = BSWAP_32(drrb->drr_type); 277495db6fbSLori Alt drrb->drr_flags = BSWAP_32(drrb->drr_flags); 278495db6fbSLori Alt drrb->drr_toguid = BSWAP_64(drrb->drr_toguid); 279495db6fbSLori Alt drrb->drr_fromguid = 280495db6fbSLori Alt BSWAP_64(drrb->drr_fromguid); 281495db6fbSLori Alt } 282495db6fbSLori Alt 283495db6fbSLori Alt (void) printf("BEGIN record\n"); 2849e69d7d0SLori Alt (void) printf("\thdrtype = %lld\n", 2859e69d7d0SLori Alt DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo)); 2869e69d7d0SLori Alt (void) printf("\tfeatures = %llx\n", 2879e69d7d0SLori Alt DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo)); 288495db6fbSLori Alt (void) printf("\tmagic = %llx\n", 289495db6fbSLori Alt (u_longlong_t)drrb->drr_magic); 290495db6fbSLori Alt (void) printf("\tcreation_time = %llx\n", 291495db6fbSLori Alt (u_longlong_t)drrb->drr_creation_time); 292495db6fbSLori Alt (void) printf("\ttype = %u\n", drrb->drr_type); 293495db6fbSLori Alt (void) printf("\tflags = 0x%x\n", drrb->drr_flags); 294495db6fbSLori Alt (void) printf("\ttoguid = %llx\n", 295495db6fbSLori Alt (u_longlong_t)drrb->drr_toguid); 296495db6fbSLori Alt (void) printf("\tfromguid = %llx\n", 297495db6fbSLori Alt (u_longlong_t)drrb->drr_fromguid); 298495db6fbSLori Alt (void) printf("\ttoname = %s\n", drrb->drr_toname); 299495db6fbSLori Alt if (verbose) 300495db6fbSLori Alt (void) printf("\n"); 301495db6fbSLori Alt 3029e69d7d0SLori Alt if ((DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == 3039e69d7d0SLori Alt DMU_COMPOUNDSTREAM) && drr->drr_payloadlen != 0) { 304495db6fbSLori Alt nvlist_t *nv; 305495db6fbSLori Alt int sz = drr->drr_payloadlen; 306495db6fbSLori Alt 307*994fb6b8SMax Grossman if (sz > INITIAL_BUFLEN) { 308495db6fbSLori Alt free(buf); 309495db6fbSLori Alt buf = malloc(sz); 310495db6fbSLori Alt } 311495db6fbSLori Alt (void) ssread(buf, sz, &zc); 312495db6fbSLori Alt if (ferror(send_stream)) 313495db6fbSLori Alt perror("fread"); 314495db6fbSLori Alt err = nvlist_unpack(buf, sz, &nv, 0); 315495db6fbSLori Alt if (err) 316495db6fbSLori Alt perror(strerror(err)); 317495db6fbSLori Alt nvlist_print(stdout, nv); 318495db6fbSLori Alt nvlist_free(nv); 319495db6fbSLori Alt } 320495db6fbSLori Alt break; 321495db6fbSLori Alt 322495db6fbSLori Alt case DRR_END: 323495db6fbSLori Alt if (do_byteswap) { 324495db6fbSLori Alt drre->drr_checksum.zc_word[0] = 325495db6fbSLori Alt BSWAP_64(drre->drr_checksum.zc_word[0]); 326495db6fbSLori Alt drre->drr_checksum.zc_word[1] = 327495db6fbSLori Alt BSWAP_64(drre->drr_checksum.zc_word[1]); 328495db6fbSLori Alt drre->drr_checksum.zc_word[2] = 329495db6fbSLori Alt BSWAP_64(drre->drr_checksum.zc_word[2]); 330495db6fbSLori Alt drre->drr_checksum.zc_word[3] = 331495db6fbSLori Alt BSWAP_64(drre->drr_checksum.zc_word[3]); 332495db6fbSLori Alt } 333495db6fbSLori Alt /* 334495db6fbSLori Alt * We compare against the *previous* checksum 335495db6fbSLori Alt * value, because the stored checksum is of 336495db6fbSLori Alt * everything before the DRR_END record. 337495db6fbSLori Alt */ 338495db6fbSLori Alt if (do_cksum && !ZIO_CHECKSUM_EQUAL(drre->drr_checksum, 339495db6fbSLori Alt pcksum)) { 340495db6fbSLori Alt (void) printf("Expected checksum differs from " 341495db6fbSLori Alt "checksum in stream.\n"); 342495db6fbSLori Alt (void) printf("Expected checksum = " 343495db6fbSLori Alt "%llx/%llx/%llx/%llx\n", 344495db6fbSLori Alt pcksum.zc_word[0], 345495db6fbSLori Alt pcksum.zc_word[1], 346495db6fbSLori Alt pcksum.zc_word[2], 347495db6fbSLori Alt pcksum.zc_word[3]); 348495db6fbSLori Alt } 349495db6fbSLori Alt (void) printf("END checksum = %llx/%llx/%llx/%llx\n", 350495db6fbSLori Alt drre->drr_checksum.zc_word[0], 351495db6fbSLori Alt drre->drr_checksum.zc_word[1], 352495db6fbSLori Alt drre->drr_checksum.zc_word[2], 353495db6fbSLori Alt drre->drr_checksum.zc_word[3]); 354495db6fbSLori Alt 355495db6fbSLori Alt ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0); 356495db6fbSLori Alt break; 357495db6fbSLori Alt 358495db6fbSLori Alt case DRR_OBJECT: 359495db6fbSLori Alt if (do_byteswap) { 360495db6fbSLori Alt drro->drr_object = BSWAP_64(drro->drr_object); 361495db6fbSLori Alt drro->drr_type = BSWAP_32(drro->drr_type); 362495db6fbSLori Alt drro->drr_bonustype = 363495db6fbSLori Alt BSWAP_32(drro->drr_bonustype); 364495db6fbSLori Alt drro->drr_blksz = BSWAP_32(drro->drr_blksz); 365495db6fbSLori Alt drro->drr_bonuslen = 366495db6fbSLori Alt BSWAP_32(drro->drr_bonuslen); 3679e69d7d0SLori Alt drro->drr_toguid = BSWAP_64(drro->drr_toguid); 368495db6fbSLori Alt } 369495db6fbSLori Alt if (verbose) { 370495db6fbSLori Alt (void) printf("OBJECT object = %llu type = %u " 371495db6fbSLori Alt "bonustype = %u blksz = %u bonuslen = %u\n", 372495db6fbSLori Alt (u_longlong_t)drro->drr_object, 373495db6fbSLori Alt drro->drr_type, 374495db6fbSLori Alt drro->drr_bonustype, 375495db6fbSLori Alt drro->drr_blksz, 376495db6fbSLori Alt drro->drr_bonuslen); 377495db6fbSLori Alt } 378495db6fbSLori Alt if (drro->drr_bonuslen > 0) { 379495db6fbSLori Alt (void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen, 380495db6fbSLori Alt 8), &zc); 381*994fb6b8SMax Grossman if (dump) { 382*994fb6b8SMax Grossman print_block(buf, 383*994fb6b8SMax Grossman P2ROUNDUP(drro->drr_bonuslen, 8)); 384*994fb6b8SMax Grossman } 385495db6fbSLori Alt } 386495db6fbSLori Alt break; 387495db6fbSLori Alt 388495db6fbSLori Alt case DRR_FREEOBJECTS: 389495db6fbSLori Alt if (do_byteswap) { 390495db6fbSLori Alt drrfo->drr_firstobj = 391495db6fbSLori Alt BSWAP_64(drrfo->drr_firstobj); 392495db6fbSLori Alt drrfo->drr_numobjs = 393495db6fbSLori Alt BSWAP_64(drrfo->drr_numobjs); 3949e69d7d0SLori Alt drrfo->drr_toguid = BSWAP_64(drrfo->drr_toguid); 395495db6fbSLori Alt } 396495db6fbSLori Alt if (verbose) { 397495db6fbSLori Alt (void) printf("FREEOBJECTS firstobj = %llu " 398495db6fbSLori Alt "numobjs = %llu\n", 399495db6fbSLori Alt (u_longlong_t)drrfo->drr_firstobj, 400495db6fbSLori Alt (u_longlong_t)drrfo->drr_numobjs); 401495db6fbSLori Alt } 402495db6fbSLori Alt break; 403495db6fbSLori Alt 404495db6fbSLori Alt case DRR_WRITE: 405495db6fbSLori Alt if (do_byteswap) { 406495db6fbSLori Alt drrw->drr_object = BSWAP_64(drrw->drr_object); 407495db6fbSLori Alt drrw->drr_type = BSWAP_32(drrw->drr_type); 408495db6fbSLori Alt drrw->drr_offset = BSWAP_64(drrw->drr_offset); 409495db6fbSLori Alt drrw->drr_length = BSWAP_64(drrw->drr_length); 4109e69d7d0SLori Alt drrw->drr_toguid = BSWAP_64(drrw->drr_toguid); 4118e714474SLori Alt drrw->drr_key.ddk_prop = 4128e714474SLori Alt BSWAP_64(drrw->drr_key.ddk_prop); 413495db6fbSLori Alt } 414*994fb6b8SMax Grossman /* 415*994fb6b8SMax Grossman * If this is verbose and/or dump output, 416*994fb6b8SMax Grossman * print info on the modified block 417*994fb6b8SMax Grossman */ 418495db6fbSLori Alt if (verbose) { 419495db6fbSLori Alt (void) printf("WRITE object = %llu type = %u " 4208e714474SLori Alt "checksum type = %u\n" 4218e714474SLori Alt "offset = %llu length = %llu " 4228e714474SLori Alt "props = %llx\n", 423495db6fbSLori Alt (u_longlong_t)drrw->drr_object, 424495db6fbSLori Alt drrw->drr_type, 4258e714474SLori Alt drrw->drr_checksumtype, 426495db6fbSLori Alt (u_longlong_t)drrw->drr_offset, 4278e714474SLori Alt (u_longlong_t)drrw->drr_length, 4288e714474SLori Alt (u_longlong_t)drrw->drr_key.ddk_prop); 429495db6fbSLori Alt } 430*994fb6b8SMax Grossman /* 431*994fb6b8SMax Grossman * Read the contents of the block in from STDIN to buf 432*994fb6b8SMax Grossman */ 433495db6fbSLori Alt (void) ssread(buf, drrw->drr_length, &zc); 434*994fb6b8SMax Grossman /* 435*994fb6b8SMax Grossman * If in dump mode 436*994fb6b8SMax Grossman */ 437*994fb6b8SMax Grossman if (dump) { 438*994fb6b8SMax Grossman print_block(buf, drrw->drr_length); 439*994fb6b8SMax Grossman } 440495db6fbSLori Alt total_write_size += drrw->drr_length; 441495db6fbSLori Alt break; 442495db6fbSLori Alt 4439e69d7d0SLori Alt case DRR_WRITE_BYREF: 4449e69d7d0SLori Alt if (do_byteswap) { 4459e69d7d0SLori Alt drrwbr->drr_object = 4469e69d7d0SLori Alt BSWAP_64(drrwbr->drr_object); 4479e69d7d0SLori Alt drrwbr->drr_offset = 4489e69d7d0SLori Alt BSWAP_64(drrwbr->drr_offset); 4499e69d7d0SLori Alt drrwbr->drr_length = 4509e69d7d0SLori Alt BSWAP_64(drrwbr->drr_length); 4519e69d7d0SLori Alt drrwbr->drr_toguid = 4529e69d7d0SLori Alt BSWAP_64(drrwbr->drr_toguid); 4539e69d7d0SLori Alt drrwbr->drr_refguid = 4549e69d7d0SLori Alt BSWAP_64(drrwbr->drr_refguid); 4559e69d7d0SLori Alt drrwbr->drr_refobject = 4569e69d7d0SLori Alt BSWAP_64(drrwbr->drr_refobject); 4579e69d7d0SLori Alt drrwbr->drr_refoffset = 4589e69d7d0SLori Alt BSWAP_64(drrwbr->drr_refoffset); 4598e714474SLori Alt drrwbr->drr_key.ddk_prop = 4608e714474SLori Alt BSWAP_64(drrwbr->drr_key.ddk_prop); 4619e69d7d0SLori Alt } 4629e69d7d0SLori Alt if (verbose) { 4639e69d7d0SLori Alt (void) printf("WRITE_BYREF object = %llu " 4648e714474SLori Alt "checksum type = %u props = %llx\n" 4659e69d7d0SLori Alt "offset = %llu length = %llu\n" 4669e69d7d0SLori Alt "toguid = %llx refguid = %llx\n" 4679e69d7d0SLori Alt "refobject = %llu refoffset = %llu\n", 4689e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_object, 4698e714474SLori Alt drrwbr->drr_checksumtype, 4708e714474SLori Alt (u_longlong_t)drrwbr->drr_key.ddk_prop, 4719e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_offset, 4729e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_length, 4739e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_toguid, 4749e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_refguid, 4759e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_refobject, 4769e69d7d0SLori Alt (u_longlong_t)drrwbr->drr_refoffset); 4779e69d7d0SLori Alt } 4789e69d7d0SLori Alt break; 4799e69d7d0SLori Alt 480495db6fbSLori Alt case DRR_FREE: 481495db6fbSLori Alt if (do_byteswap) { 482495db6fbSLori Alt drrf->drr_object = BSWAP_64(drrf->drr_object); 483495db6fbSLori Alt drrf->drr_offset = BSWAP_64(drrf->drr_offset); 484495db6fbSLori Alt drrf->drr_length = BSWAP_64(drrf->drr_length); 485495db6fbSLori Alt } 486495db6fbSLori Alt if (verbose) { 487495db6fbSLori Alt (void) printf("FREE object = %llu " 488495db6fbSLori Alt "offset = %llu length = %lld\n", 489495db6fbSLori Alt (u_longlong_t)drrf->drr_object, 490495db6fbSLori Alt (u_longlong_t)drrf->drr_offset, 491495db6fbSLori Alt (longlong_t)drrf->drr_length); 492495db6fbSLori Alt } 493495db6fbSLori Alt break; 4940a586ceaSMark Shellenbaum case DRR_SPILL: 4950a586ceaSMark Shellenbaum if (do_byteswap) { 4960a586ceaSMark Shellenbaum drrs->drr_object = BSWAP_64(drrs->drr_object); 4970a586ceaSMark Shellenbaum drrs->drr_length = BSWAP_64(drrs->drr_length); 4980a586ceaSMark Shellenbaum } 4990a586ceaSMark Shellenbaum if (verbose) { 5000a586ceaSMark Shellenbaum (void) printf("SPILL block for object = %llu " 5010a586ceaSMark Shellenbaum "length = %llu\n", drrs->drr_object, 5020a586ceaSMark Shellenbaum drrs->drr_length); 5030a586ceaSMark Shellenbaum } 5040a586ceaSMark Shellenbaum (void) ssread(buf, drrs->drr_length, &zc); 505*994fb6b8SMax Grossman if (dump) { 506*994fb6b8SMax Grossman print_block(buf, drrs->drr_length); 507*994fb6b8SMax Grossman } 5080a586ceaSMark Shellenbaum break; 509495db6fbSLori Alt } 510495db6fbSLori Alt pcksum = zc; 511495db6fbSLori Alt } 512495db6fbSLori Alt free(buf); 513495db6fbSLori Alt 514495db6fbSLori Alt /* Print final summary */ 515495db6fbSLori Alt 516495db6fbSLori Alt (void) printf("SUMMARY:\n"); 517495db6fbSLori Alt (void) printf("\tTotal DRR_BEGIN records = %lld\n", 518495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_BEGIN]); 519495db6fbSLori Alt (void) printf("\tTotal DRR_END records = %lld\n", 520495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_END]); 521495db6fbSLori Alt (void) printf("\tTotal DRR_OBJECT records = %lld\n", 522495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_OBJECT]); 523495db6fbSLori Alt (void) printf("\tTotal DRR_FREEOBJECTS records = %lld\n", 524495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_FREEOBJECTS]); 525495db6fbSLori Alt (void) printf("\tTotal DRR_WRITE records = %lld\n", 526495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_WRITE]); 527495db6fbSLori Alt (void) printf("\tTotal DRR_FREE records = %lld\n", 528495db6fbSLori Alt (u_longlong_t)drr_record_count[DRR_FREE]); 5290a586ceaSMark Shellenbaum (void) printf("\tTotal DRR_SPILL records = %lld\n", 5300a586ceaSMark Shellenbaum (u_longlong_t)drr_record_count[DRR_SPILL]); 531495db6fbSLori Alt (void) printf("\tTotal records = %lld\n", 532495db6fbSLori Alt (u_longlong_t)(drr_record_count[DRR_BEGIN] + 533495db6fbSLori Alt drr_record_count[DRR_OBJECT] + 534495db6fbSLori Alt drr_record_count[DRR_FREEOBJECTS] + 535495db6fbSLori Alt drr_record_count[DRR_WRITE] + 536495db6fbSLori Alt drr_record_count[DRR_FREE] + 5370a586ceaSMark Shellenbaum drr_record_count[DRR_SPILL] + 538495db6fbSLori Alt drr_record_count[DRR_END])); 539495db6fbSLori Alt (void) printf("\tTotal write size = %lld (0x%llx)\n", 540495db6fbSLori Alt (u_longlong_t)total_write_size, (u_longlong_t)total_write_size); 541495db6fbSLori Alt (void) printf("\tTotal stream length = %lld (0x%llx)\n", 542495db6fbSLori Alt (u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len); 543495db6fbSLori Alt return (0); 544495db6fbSLori Alt } 545