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