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