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