]> git.proxmox.com Git - mirror_zfs.git/blame - cmd/zstreamdump/zstreamdump.c
zstreamdump dumps core printing truncated nvlist
[mirror_zfs.git] / cmd / zstreamdump / zstreamdump.c
CommitLineData
b79fc3fe
MM
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Portions Copyright 2012 Martin Matuska <martin@matuska.org>
27 */
28
cfec5b17 29/*
2aa34383 30 * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
cfec5b17
MG
31 */
32
33#include <ctype.h>
b79fc3fe
MM
34#include <libnvpair.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <strings.h>
38#include <unistd.h>
37f8a883 39#include <stddef.h>
b79fc3fe
MM
40
41#include <sys/dmu.h>
42#include <sys/zfs_ioctl.h>
2aa34383 43#include <sys/zio.h>
b79fc3fe
MM
44#include <zfs_fletcher.h>
45
cfec5b17
MG
46/*
47 * If dump mode is enabled, the number of bytes to print per line
48 */
49#define BYTES_PER_LINE 16
50/*
51 * If dump mode is enabled, the number of bytes to group together, separated
52 * by newlines or spaces
53 */
54#define DUMP_GROUPING 4
55
b79fc3fe
MM
56uint64_t total_write_size = 0;
57uint64_t total_stream_len = 0;
58FILE *send_stream = 0;
59boolean_t do_byteswap = B_FALSE;
60boolean_t do_cksum = B_TRUE;
b79fc3fe
MM
61
62static void
63usage(void)
64{
cfec5b17 65 (void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
b79fc3fe
MM
66 (void) fprintf(stderr, "\t -v -- verbose\n");
67 (void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
cfec5b17
MG
68 (void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
69 "implies verbose\n");
b79fc3fe
MM
70 exit(1);
71}
72
f1512ee6
MA
73static void *
74safe_malloc(size_t size)
75{
76 void *rv = malloc(size);
77 if (rv == NULL) {
37f8a883
MA
78 (void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n",
79 size);
f1512ee6
MA
80 abort();
81 }
82 return (rv);
83}
84
b79fc3fe
MM
85/*
86 * ssread - send stream read.
87 *
88 * Read while computing incremental checksum
89 */
b79fc3fe
MM
90static size_t
91ssread(void *buf, size_t len, zio_cksum_t *cksum)
92{
93 size_t outlen;
94
95 if ((outlen = fread(buf, len, 1, send_stream)) == 0)
96 return (0);
97
37f8a883 98 if (do_cksum) {
b79fc3fe
MM
99 if (do_byteswap)
100 fletcher_4_incremental_byteswap(buf, len, cksum);
101 else
102 fletcher_4_incremental_native(buf, len, cksum);
103 }
104 total_stream_len += len;
105 return (outlen);
106}
107
37f8a883
MA
108static size_t
109read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
110{
111 ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
112 ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
113 size_t r = ssread(drr, sizeof (*drr) - sizeof (zio_cksum_t), cksum);
114 if (r == 0)
115 return (0);
116 zio_cksum_t saved_cksum = *cksum;
117 r = ssread(&drr->drr_u.drr_checksum.drr_checksum,
118 sizeof (zio_cksum_t), cksum);
119 if (r == 0)
120 return (0);
121 if (!ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.drr_checksum.drr_checksum) &&
122 !ZIO_CHECKSUM_EQUAL(saved_cksum,
123 drr->drr_u.drr_checksum.drr_checksum)) {
124 fprintf(stderr, "invalid checksum\n");
125 (void) printf("Incorrect checksum in record header.\n");
126 (void) printf("Expected checksum = %llx/%llx/%llx/%llx\n",
127 (longlong_t)saved_cksum.zc_word[0],
128 (longlong_t)saved_cksum.zc_word[1],
129 (longlong_t)saved_cksum.zc_word[2],
130 (longlong_t)saved_cksum.zc_word[3]);
47dfff3b 131 return (0);
37f8a883
MA
132 }
133 return (sizeof (*drr));
134}
135
cfec5b17
MG
136/*
137 * Print part of a block in ASCII characters
138 */
139static void
140print_ascii_block(char *subbuf, int length)
141{
142 int i;
143
144 for (i = 0; i < length; i++) {
145 char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
146 if (i != 0 && i % DUMP_GROUPING == 0) {
147 (void) printf(" ");
148 }
149 (void) printf("%c", char_print);
150 }
151 (void) printf("\n");
152}
153
154/*
155 * print_block - Dump the contents of a modified block to STDOUT
156 *
157 * Assume that buf has capacity evenly divisible by BYTES_PER_LINE
158 */
159static void
160print_block(char *buf, int length)
161{
162 int i;
163 /*
164 * Start printing ASCII characters at a constant offset, after
165 * the hex prints. Leave 3 characters per byte on a line (2 digit
166 * hex number plus 1 space) plus spaces between characters and
37f8a883 167 * groupings.
cfec5b17
MG
168 */
169 int ascii_start = BYTES_PER_LINE * 3 +
170 BYTES_PER_LINE / DUMP_GROUPING + 2;
171
172 for (i = 0; i < length; i += BYTES_PER_LINE) {
173 int j;
174 int this_line_length = MIN(BYTES_PER_LINE, length - i);
175 int print_offset = 0;
176
177 for (j = 0; j < this_line_length; j++) {
178 int buf_offset = i + j;
179
180 /*
181 * Separate every DUMP_GROUPING bytes by a space.
182 */
183 if (buf_offset % DUMP_GROUPING == 0) {
184 print_offset += printf(" ");
185 }
186
187 /*
188 * Print the two-digit hex value for this byte.
189 */
190 unsigned char hex_print = buf[buf_offset];
191 print_offset += printf("%02x ", hex_print);
192 }
193
194 (void) printf("%*s", ascii_start - print_offset, " ");
195
196 print_ascii_block(buf + i, this_line_length);
197 }
198}
199
b5256303
TC
200/*
201 * Print an array of bytes to stdout as hexidecimal characters. str must
202 * have buf_len * 2 + 1 bytes of space.
203 */
204static void
205sprintf_bytes(char *str, uint8_t *buf, uint_t buf_len)
206{
207 int i, n;
208
209 for (i = 0; i < buf_len; i++) {
210 n = sprintf(str, "%02x", buf[i] & 0xff);
211 str += n;
212 }
213
214 str[0] = '\0';
215}
216
b79fc3fe
MM
217int
218main(int argc, char *argv[])
219{
f1512ee6 220 char *buf = safe_malloc(SPA_MAXBLOCKSIZE);
9b67f605 221 uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
b5256303
TC
222 char salt[ZIO_DATA_SALT_LEN * 2 + 1];
223 char iv[ZIO_DATA_IV_LEN * 2 + 1];
224 char mac[ZIO_DATA_MAC_LEN * 2 + 1];
9b67f605 225 uint64_t total_records = 0;
b5256303 226 uint64_t payload_size;
b79fc3fe
MM
227 dmu_replay_record_t thedrr;
228 dmu_replay_record_t *drr = &thedrr;
229 struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
230 struct drr_end *drre = &thedrr.drr_u.drr_end;
231 struct drr_object *drro = &thedrr.drr_u.drr_object;
232 struct drr_freeobjects *drrfo = &thedrr.drr_u.drr_freeobjects;
233 struct drr_write *drrw = &thedrr.drr_u.drr_write;
234 struct drr_write_byref *drrwbr = &thedrr.drr_u.drr_write_byref;
235 struct drr_free *drrf = &thedrr.drr_u.drr_free;
236 struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
9b67f605 237 struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
b5256303 238 struct drr_object_range *drror = &thedrr.drr_u.drr_object_range;
37f8a883 239 struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
b79fc3fe
MM
240 char c;
241 boolean_t verbose = B_FALSE;
37f8a883 242 boolean_t very_verbose = B_FALSE;
b79fc3fe 243 boolean_t first = B_TRUE;
cfec5b17
MG
244 /*
245 * dump flag controls whether the contents of any modified data blocks
246 * are printed to the console during processing of the stream. Warning:
247 * for large streams, this can obviously lead to massive prints.
248 */
249 boolean_t dump = B_FALSE;
b79fc3fe
MM
250 int err;
251 zio_cksum_t zc = { { 0 } };
252 zio_cksum_t pcksum = { { 0 } };
253
cfec5b17 254 while ((c = getopt(argc, argv, ":vCd")) != -1) {
b79fc3fe
MM
255 switch (c) {
256 case 'C':
257 do_cksum = B_FALSE;
258 break;
259 case 'v':
37f8a883
MA
260 if (verbose)
261 very_verbose = B_TRUE;
b79fc3fe
MM
262 verbose = B_TRUE;
263 break;
cfec5b17
MG
264 case 'd':
265 dump = B_TRUE;
266 verbose = B_TRUE;
37f8a883 267 very_verbose = B_TRUE;
cfec5b17 268 break;
b79fc3fe
MM
269 case ':':
270 (void) fprintf(stderr,
271 "missing argument for '%c' option\n", optopt);
272 usage();
273 break;
274 case '?':
275 (void) fprintf(stderr, "invalid option '%c'\n",
276 optopt);
277 usage();
2aa34383 278 break;
b79fc3fe
MM
279 }
280 }
281
282 if (isatty(STDIN_FILENO)) {
283 (void) fprintf(stderr,
284 "Error: Backup stream can not be read "
285 "from a terminal.\n"
286 "You must redirect standard input.\n");
287 exit(1);
288 }
289
616fa7c0 290 fletcher_4_init();
b79fc3fe 291 send_stream = stdin;
37f8a883 292 while (read_hdr(drr, &zc)) {
b79fc3fe 293
cfec5b17
MG
294 /*
295 * If this is the first DMU record being processed, check for
296 * the magic bytes and figure out the endian-ness based on them.
297 */
b79fc3fe
MM
298 if (first) {
299 if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
300 do_byteswap = B_TRUE;
301 if (do_cksum) {
302 ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0);
303 /*
304 * recalculate header checksum now
305 * that we know it needs to be
306 * byteswapped.
307 */
308 fletcher_4_incremental_byteswap(drr,
309 sizeof (dmu_replay_record_t), &zc);
310 }
311 } else if (drrb->drr_magic != DMU_BACKUP_MAGIC) {
312 (void) fprintf(stderr, "Invalid stream "
313 "(bad magic number)\n");
314 exit(1);
315 }
316 first = B_FALSE;
317 }
318 if (do_byteswap) {
319 drr->drr_type = BSWAP_32(drr->drr_type);
320 drr->drr_payloadlen =
321 BSWAP_32(drr->drr_payloadlen);
322 }
323
324 /*
325 * At this point, the leading fields of the replay record
326 * (drr_type and drr_payloadlen) have been byte-swapped if
327 * necessary, but the rest of the data structure (the
328 * union of type-specific structures) is still in its
329 * original state.
330 */
331 if (drr->drr_type >= DRR_NUMTYPES) {
332 (void) printf("INVALID record found: type 0x%x\n",
333 drr->drr_type);
334 (void) printf("Aborting.\n");
335 exit(1);
336 }
337
338 drr_record_count[drr->drr_type]++;
9b67f605 339 total_records++;
b79fc3fe
MM
340
341 switch (drr->drr_type) {
342 case DRR_BEGIN:
343 if (do_byteswap) {
344 drrb->drr_magic = BSWAP_64(drrb->drr_magic);
345 drrb->drr_versioninfo =
346 BSWAP_64(drrb->drr_versioninfo);
347 drrb->drr_creation_time =
348 BSWAP_64(drrb->drr_creation_time);
349 drrb->drr_type = BSWAP_32(drrb->drr_type);
350 drrb->drr_flags = BSWAP_32(drrb->drr_flags);
351 drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
352 drrb->drr_fromguid =
353 BSWAP_64(drrb->drr_fromguid);
354 }
355
356 (void) printf("BEGIN record\n");
357 (void) printf("\thdrtype = %lld\n",
358 DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo));
359 (void) printf("\tfeatures = %llx\n",
360 DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo));
361 (void) printf("\tmagic = %llx\n",
362 (u_longlong_t)drrb->drr_magic);
363 (void) printf("\tcreation_time = %llx\n",
364 (u_longlong_t)drrb->drr_creation_time);
365 (void) printf("\ttype = %u\n", drrb->drr_type);
366 (void) printf("\tflags = 0x%x\n", drrb->drr_flags);
367 (void) printf("\ttoguid = %llx\n",
368 (u_longlong_t)drrb->drr_toguid);
369 (void) printf("\tfromguid = %llx\n",
370 (u_longlong_t)drrb->drr_fromguid);
371 (void) printf("\ttoname = %s\n", drrb->drr_toname);
372 if (verbose)
373 (void) printf("\n");
374
47dfff3b 375 if (drr->drr_payloadlen != 0) {
b79fc3fe
MM
376 nvlist_t *nv;
377 int sz = drr->drr_payloadlen;
378
f1512ee6 379 if (sz > SPA_MAXBLOCKSIZE) {
b79fc3fe 380 free(buf);
f1512ee6 381 buf = safe_malloc(sz);
b79fc3fe
MM
382 }
383 (void) ssread(buf, sz, &zc);
384 if (ferror(send_stream))
385 perror("fread");
386 err = nvlist_unpack(buf, sz, &nv, 0);
e0b7ff46 387 if (err) {
b79fc3fe 388 perror(strerror(err));
e0b7ff46 389 } else {
390 nvlist_print(stdout, nv);
391 nvlist_free(nv);
392 }
b79fc3fe
MM
393 }
394 break;
395
396 case DRR_END:
397 if (do_byteswap) {
398 drre->drr_checksum.zc_word[0] =
399 BSWAP_64(drre->drr_checksum.zc_word[0]);
400 drre->drr_checksum.zc_word[1] =
401 BSWAP_64(drre->drr_checksum.zc_word[1]);
402 drre->drr_checksum.zc_word[2] =
403 BSWAP_64(drre->drr_checksum.zc_word[2]);
404 drre->drr_checksum.zc_word[3] =
405 BSWAP_64(drre->drr_checksum.zc_word[3]);
406 }
407 /*
408 * We compare against the *previous* checksum
409 * value, because the stored checksum is of
410 * everything before the DRR_END record.
411 */
412 if (do_cksum && !ZIO_CHECKSUM_EQUAL(drre->drr_checksum,
413 pcksum)) {
414 (void) printf("Expected checksum differs from "
415 "checksum in stream.\n");
416 (void) printf("Expected checksum = "
417 "%llx/%llx/%llx/%llx\n",
418 (long long unsigned int)pcksum.zc_word[0],
419 (long long unsigned int)pcksum.zc_word[1],
420 (long long unsigned int)pcksum.zc_word[2],
421 (long long unsigned int)pcksum.zc_word[3]);
422 }
423 (void) printf("END checksum = %llx/%llx/%llx/%llx\n",
424 (long long unsigned int)
425 drre->drr_checksum.zc_word[0],
426 (long long unsigned int)
427 drre->drr_checksum.zc_word[1],
428 (long long unsigned int)
429 drre->drr_checksum.zc_word[2],
430 (long long unsigned int)
431 drre->drr_checksum.zc_word[3]);
432
433 ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0);
434 break;
435
436 case DRR_OBJECT:
437 if (do_byteswap) {
438 drro->drr_object = BSWAP_64(drro->drr_object);
439 drro->drr_type = BSWAP_32(drro->drr_type);
440 drro->drr_bonustype =
441 BSWAP_32(drro->drr_bonustype);
442 drro->drr_blksz = BSWAP_32(drro->drr_blksz);
443 drro->drr_bonuslen =
444 BSWAP_32(drro->drr_bonuslen);
b5256303
TC
445 drro->drr_raw_bonuslen =
446 BSWAP_32(drro->drr_raw_bonuslen);
b79fc3fe 447 drro->drr_toguid = BSWAP_64(drro->drr_toguid);
ae76f45c
TC
448 drro->drr_maxblkid =
449 BSWAP_64(drro->drr_maxblkid);
b79fc3fe 450 }
b5256303
TC
451
452 payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
453
b79fc3fe
MM
454 if (verbose) {
455 (void) printf("OBJECT object = %llu type = %u "
73aac4aa 456 "bonustype = %u blksz = %u bonuslen = %u "
b5256303 457 "dn_slots = %u raw_bonuslen = %u "
ae76f45c
TC
458 "flags = %u maxblkid = %llu "
459 "indblkshift = %u nlevels = %u "
b5256303 460 "nblkptr = %u\n",
b79fc3fe
MM
461 (u_longlong_t)drro->drr_object,
462 drro->drr_type,
463 drro->drr_bonustype,
464 drro->drr_blksz,
73aac4aa 465 drro->drr_bonuslen,
b5256303
TC
466 drro->drr_dn_slots,
467 drro->drr_raw_bonuslen,
468 drro->drr_flags,
ae76f45c 469 (u_longlong_t)drro->drr_maxblkid,
b5256303
TC
470 drro->drr_indblkshift,
471 drro->drr_nlevels,
472 drro->drr_nblkptr);
b79fc3fe
MM
473 }
474 if (drro->drr_bonuslen > 0) {
b5256303
TC
475 (void) ssread(buf, payload_size, &zc);
476 if (dump)
477 print_block(buf, payload_size);
b79fc3fe
MM
478 }
479 break;
480
481 case DRR_FREEOBJECTS:
482 if (do_byteswap) {
483 drrfo->drr_firstobj =
484 BSWAP_64(drrfo->drr_firstobj);
485 drrfo->drr_numobjs =
486 BSWAP_64(drrfo->drr_numobjs);
487 drrfo->drr_toguid = BSWAP_64(drrfo->drr_toguid);
488 }
489 if (verbose) {
490 (void) printf("FREEOBJECTS firstobj = %llu "
491 "numobjs = %llu\n",
492 (u_longlong_t)drrfo->drr_firstobj,
493 (u_longlong_t)drrfo->drr_numobjs);
494 }
495 break;
496
497 case DRR_WRITE:
498 if (do_byteswap) {
499 drrw->drr_object = BSWAP_64(drrw->drr_object);
500 drrw->drr_type = BSWAP_32(drrw->drr_type);
501 drrw->drr_offset = BSWAP_64(drrw->drr_offset);
2aa34383
DK
502 drrw->drr_logical_size =
503 BSWAP_64(drrw->drr_logical_size);
b79fc3fe
MM
504 drrw->drr_toguid = BSWAP_64(drrw->drr_toguid);
505 drrw->drr_key.ddk_prop =
506 BSWAP_64(drrw->drr_key.ddk_prop);
2aa34383
DK
507 drrw->drr_compressed_size =
508 BSWAP_64(drrw->drr_compressed_size);
b79fc3fe 509 }
2aa34383 510
b5256303 511 payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
2aa34383 512
cfec5b17
MG
513 /*
514 * If this is verbose and/or dump output,
515 * print info on the modified block
516 */
b79fc3fe 517 if (verbose) {
b5256303
TC
518 sprintf_bytes(salt, drrw->drr_salt,
519 ZIO_DATA_SALT_LEN);
520 sprintf_bytes(iv, drrw->drr_iv,
521 ZIO_DATA_IV_LEN);
522 sprintf_bytes(mac, drrw->drr_mac,
523 ZIO_DATA_MAC_LEN);
524
b79fc3fe 525 (void) printf("WRITE object = %llu type = %u "
2aa34383 526 "checksum type = %u compression type = %u\n"
b5256303
TC
527 " flags = %u offset = %llu "
528 "logical_size = %llu "
2aa34383 529 "compressed_size = %llu "
b5256303
TC
530 "payload_size = %llu props = %llx "
531 "salt = %s iv = %s mac = %s\n",
b79fc3fe
MM
532 (u_longlong_t)drrw->drr_object,
533 drrw->drr_type,
534 drrw->drr_checksumtype,
2aa34383 535 drrw->drr_compressiontype,
b5256303 536 drrw->drr_flags,
b79fc3fe 537 (u_longlong_t)drrw->drr_offset,
2aa34383
DK
538 (u_longlong_t)drrw->drr_logical_size,
539 (u_longlong_t)drrw->drr_compressed_size,
540 (u_longlong_t)payload_size,
b5256303
TC
541 (u_longlong_t)drrw->drr_key.ddk_prop,
542 salt,
543 iv,
544 mac);
b79fc3fe 545 }
2aa34383 546
cfec5b17
MG
547 /*
548 * Read the contents of the block in from STDIN to buf
549 */
2aa34383 550 (void) ssread(buf, payload_size, &zc);
cfec5b17
MG
551 /*
552 * If in dump mode
553 */
554 if (dump) {
2aa34383 555 print_block(buf, payload_size);
cfec5b17 556 }
2aa34383 557 total_write_size += payload_size;
b79fc3fe
MM
558 break;
559
560 case DRR_WRITE_BYREF:
561 if (do_byteswap) {
562 drrwbr->drr_object =
563 BSWAP_64(drrwbr->drr_object);
564 drrwbr->drr_offset =
565 BSWAP_64(drrwbr->drr_offset);
566 drrwbr->drr_length =
567 BSWAP_64(drrwbr->drr_length);
568 drrwbr->drr_toguid =
569 BSWAP_64(drrwbr->drr_toguid);
570 drrwbr->drr_refguid =
571 BSWAP_64(drrwbr->drr_refguid);
572 drrwbr->drr_refobject =
573 BSWAP_64(drrwbr->drr_refobject);
574 drrwbr->drr_refoffset =
575 BSWAP_64(drrwbr->drr_refoffset);
576 drrwbr->drr_key.ddk_prop =
577 BSWAP_64(drrwbr->drr_key.ddk_prop);
578 }
579 if (verbose) {
580 (void) printf("WRITE_BYREF object = %llu "
581 "checksum type = %u props = %llx\n"
37f8a883 582 " offset = %llu length = %llu\n"
b79fc3fe 583 "toguid = %llx refguid = %llx\n"
37f8a883 584 " refobject = %llu refoffset = %llu\n",
b79fc3fe
MM
585 (u_longlong_t)drrwbr->drr_object,
586 drrwbr->drr_checksumtype,
587 (u_longlong_t)drrwbr->drr_key.ddk_prop,
588 (u_longlong_t)drrwbr->drr_offset,
589 (u_longlong_t)drrwbr->drr_length,
590 (u_longlong_t)drrwbr->drr_toguid,
591 (u_longlong_t)drrwbr->drr_refguid,
592 (u_longlong_t)drrwbr->drr_refobject,
593 (u_longlong_t)drrwbr->drr_refoffset);
594 }
595 break;
596
597 case DRR_FREE:
598 if (do_byteswap) {
599 drrf->drr_object = BSWAP_64(drrf->drr_object);
600 drrf->drr_offset = BSWAP_64(drrf->drr_offset);
601 drrf->drr_length = BSWAP_64(drrf->drr_length);
602 }
603 if (verbose) {
604 (void) printf("FREE object = %llu "
605 "offset = %llu length = %lld\n",
606 (u_longlong_t)drrf->drr_object,
607 (u_longlong_t)drrf->drr_offset,
608 (longlong_t)drrf->drr_length);
609 }
610 break;
611 case DRR_SPILL:
612 if (do_byteswap) {
613 drrs->drr_object = BSWAP_64(drrs->drr_object);
614 drrs->drr_length = BSWAP_64(drrs->drr_length);
b5256303
TC
615 drrs->drr_compressed_size =
616 BSWAP_64(drrs->drr_compressed_size);
617 drrs->drr_type = BSWAP_32(drrs->drr_type);
b79fc3fe 618 }
b0ee5946
TC
619
620 payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
621
b79fc3fe 622 if (verbose) {
b5256303
TC
623 sprintf_bytes(salt, drrs->drr_salt,
624 ZIO_DATA_SALT_LEN);
625 sprintf_bytes(iv, drrs->drr_iv,
626 ZIO_DATA_IV_LEN);
627 sprintf_bytes(mac, drrs->drr_mac,
628 ZIO_DATA_MAC_LEN);
629
b79fc3fe 630 (void) printf("SPILL block for object = %llu "
b5256303
TC
631 "length = %llu flags = %u "
632 "compression type = %u "
633 "compressed_size = %llu "
b0ee5946 634 "payload_size = %llu "
b5256303
TC
635 "salt = %s iv = %s mac = %s\n",
636 (u_longlong_t)drrs->drr_object,
637 (u_longlong_t)drrs->drr_length,
638 drrs->drr_flags,
639 drrs->drr_compressiontype,
640 (u_longlong_t)drrs->drr_compressed_size,
b0ee5946 641 (u_longlong_t)payload_size,
b5256303
TC
642 salt,
643 iv,
644 mac);
b79fc3fe 645 }
b0ee5946 646 (void) ssread(buf, payload_size, &zc);
cfec5b17 647 if (dump) {
b0ee5946 648 print_block(buf, payload_size);
cfec5b17 649 }
b79fc3fe 650 break;
9b67f605
MA
651 case DRR_WRITE_EMBEDDED:
652 if (do_byteswap) {
653 drrwe->drr_object =
654 BSWAP_64(drrwe->drr_object);
655 drrwe->drr_offset =
656 BSWAP_64(drrwe->drr_offset);
657 drrwe->drr_length =
658 BSWAP_64(drrwe->drr_length);
659 drrwe->drr_toguid =
660 BSWAP_64(drrwe->drr_toguid);
661 drrwe->drr_lsize =
662 BSWAP_32(drrwe->drr_lsize);
663 drrwe->drr_psize =
664 BSWAP_32(drrwe->drr_psize);
665 }
666 if (verbose) {
667 (void) printf("WRITE_EMBEDDED object = %llu "
668 "offset = %llu length = %llu\n"
37f8a883 669 " toguid = %llx comp = %u etype = %u "
9b67f605
MA
670 "lsize = %u psize = %u\n",
671 (u_longlong_t)drrwe->drr_object,
672 (u_longlong_t)drrwe->drr_offset,
673 (u_longlong_t)drrwe->drr_length,
674 (u_longlong_t)drrwe->drr_toguid,
675 drrwe->drr_compression,
676 drrwe->drr_etype,
677 drrwe->drr_lsize,
678 drrwe->drr_psize);
679 }
680 (void) ssread(buf,
681 P2ROUNDUP(drrwe->drr_psize, 8), &zc);
682 break;
b5256303
TC
683 case DRR_OBJECT_RANGE:
684 if (do_byteswap) {
685 drror->drr_firstobj =
686 BSWAP_64(drror->drr_firstobj);
687 drror->drr_numslots =
688 BSWAP_64(drror->drr_numslots);
689 drror->drr_toguid = BSWAP_64(drror->drr_toguid);
690 }
691 if (verbose) {
692 sprintf_bytes(salt, drror->drr_salt,
693 ZIO_DATA_SALT_LEN);
694 sprintf_bytes(iv, drror->drr_iv,
695 ZIO_DATA_IV_LEN);
696 sprintf_bytes(mac, drror->drr_mac,
697 ZIO_DATA_MAC_LEN);
698
699 (void) printf("OBJECT_RANGE firstobj = %llu "
700 "numslots = %llu flags = %u "
701 "salt = %s iv = %s mac = %s\n",
702 (u_longlong_t)drror->drr_firstobj,
703 (u_longlong_t)drror->drr_numslots,
704 drror->drr_flags,
705 salt,
706 iv,
707 mac);
708 }
709 break;
b79fc3fe
MM
710 case DRR_NUMTYPES:
711 /* should never be reached */
712 exit(1);
713 }
37f8a883
MA
714 if (drr->drr_type != DRR_BEGIN && very_verbose) {
715 (void) printf(" checksum = %llx/%llx/%llx/%llx\n",
716 (longlong_t)drrc->drr_checksum.zc_word[0],
717 (longlong_t)drrc->drr_checksum.zc_word[1],
718 (longlong_t)drrc->drr_checksum.zc_word[2],
719 (longlong_t)drrc->drr_checksum.zc_word[3]);
720 }
b79fc3fe
MM
721 pcksum = zc;
722 }
723 free(buf);
616fa7c0 724 fletcher_4_fini();
b79fc3fe
MM
725
726 /* Print final summary */
727
728 (void) printf("SUMMARY:\n");
729 (void) printf("\tTotal DRR_BEGIN records = %lld\n",
730 (u_longlong_t)drr_record_count[DRR_BEGIN]);
731 (void) printf("\tTotal DRR_END records = %lld\n",
732 (u_longlong_t)drr_record_count[DRR_END]);
733 (void) printf("\tTotal DRR_OBJECT records = %lld\n",
734 (u_longlong_t)drr_record_count[DRR_OBJECT]);
735 (void) printf("\tTotal DRR_FREEOBJECTS records = %lld\n",
736 (u_longlong_t)drr_record_count[DRR_FREEOBJECTS]);
737 (void) printf("\tTotal DRR_WRITE records = %lld\n",
738 (u_longlong_t)drr_record_count[DRR_WRITE]);
9b67f605
MA
739 (void) printf("\tTotal DRR_WRITE_BYREF records = %lld\n",
740 (u_longlong_t)drr_record_count[DRR_WRITE_BYREF]);
741 (void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld\n",
742 (u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED]);
b79fc3fe
MM
743 (void) printf("\tTotal DRR_FREE records = %lld\n",
744 (u_longlong_t)drr_record_count[DRR_FREE]);
745 (void) printf("\tTotal DRR_SPILL records = %lld\n",
746 (u_longlong_t)drr_record_count[DRR_SPILL]);
747 (void) printf("\tTotal records = %lld\n",
9b67f605 748 (u_longlong_t)total_records);
b79fc3fe
MM
749 (void) printf("\tTotal write size = %lld (0x%llx)\n",
750 (u_longlong_t)total_write_size, (u_longlong_t)total_write_size);
751 (void) printf("\tTotal stream length = %lld (0x%llx)\n",
752 (u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len);
753 return (0);
754}