Path: blob/main/sys/contrib/openzfs/cmd/zstream/zstream_dump.c
48383 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* 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.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2010 Sun Microsystems, Inc. All rights reserved.24* Use is subject to license terms.25*26* Portions Copyright 2012 Martin Matuska <[email protected]>27*/2829/*30* Copyright (c) 2013, 2015 by Delphix. All rights reserved.31*/3233#include <ctype.h>34#include <libnvpair.h>35#include <stdio.h>36#include <stdlib.h>37#include <string.h>38#include <unistd.h>39#include <stddef.h>4041#include <sys/dmu.h>42#include <sys/zfs_ioctl.h>43#include <sys/zio.h>44#include <zfs_fletcher.h>45#include "zstream.h"4647/*48* If dump mode is enabled, the number of bytes to print per line49*/50#define BYTES_PER_LINE 1651/*52* If dump mode is enabled, the number of bytes to group together, separated53* by newlines or spaces54*/55#define DUMP_GROUPING 45657static uint64_t total_stream_len = 0;58static FILE *send_stream = 0;59static boolean_t do_byteswap = B_FALSE;60static boolean_t do_cksum = B_TRUE;6162void *63safe_malloc(size_t size)64{65void *rv = malloc(size);66if (rv == NULL) {67(void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n",68size);69abort();70}71return (rv);72}7374/*75* ssread - send stream read.76*77* Read while computing incremental checksum78*/79static size_t80ssread(void *buf, size_t len, zio_cksum_t *cksum)81{82size_t outlen;8384if ((outlen = fread(buf, len, 1, send_stream)) == 0)85return (0);8687if (do_cksum) {88if (do_byteswap)89fletcher_4_incremental_byteswap(buf, len, cksum);90else91fletcher_4_incremental_native(buf, len, cksum);92}93total_stream_len += len;94return (outlen);95}9697static size_t98read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)99{100ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),101==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));102size_t r = ssread(drr, sizeof (*drr) - sizeof (zio_cksum_t), cksum);103if (r == 0)104return (0);105zio_cksum_t saved_cksum = *cksum;106r = ssread(&drr->drr_u.drr_checksum.drr_checksum,107sizeof (zio_cksum_t), cksum);108if (r == 0)109return (0);110if (do_cksum &&111!ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.drr_checksum.drr_checksum) &&112!ZIO_CHECKSUM_EQUAL(saved_cksum,113drr->drr_u.drr_checksum.drr_checksum)) {114fprintf(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]);121return (0);122}123return (sizeof (*drr));124}125126/*127* Print part of a block in ASCII characters128*/129static void130print_ascii_block(char *subbuf, int length)131{132int i;133134for (i = 0; i < length; i++) {135char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';136if (i != 0 && i % DUMP_GROUPING == 0) {137(void) printf(" ");138}139(void) printf("%c", char_print);140}141(void) printf("\n");142}143144/*145* print_block - Dump the contents of a modified block to STDOUT146*147* Assume that buf has capacity evenly divisible by BYTES_PER_LINE148*/149static void150print_block(char *buf, int length)151{152int i;153/*154* Start printing ASCII characters at a constant offset, after155* the hex prints. Leave 3 characters per byte on a line (2 digit156* hex number plus 1 space) plus spaces between characters and157* groupings.158*/159int ascii_start = BYTES_PER_LINE * 3 +160BYTES_PER_LINE / DUMP_GROUPING + 2;161162for (i = 0; i < length; i += BYTES_PER_LINE) {163int j;164int this_line_length = MIN(BYTES_PER_LINE, length - i);165int print_offset = 0;166167for (j = 0; j < this_line_length; j++) {168int buf_offset = i + j;169170/*171* Separate every DUMP_GROUPING bytes by a space.172*/173if (buf_offset % DUMP_GROUPING == 0) {174print_offset += printf(" ");175}176177/*178* Print the two-digit hex value for this byte.179*/180unsigned char hex_print = buf[buf_offset];181print_offset += printf("%02x ", hex_print);182}183184(void) printf("%*s", ascii_start - print_offset, " ");185186print_ascii_block(buf + i, this_line_length);187}188}189190/*191* Print an array of bytes to stdout as hexadecimal characters. str must192* have buf_len * 2 + 1 bytes of space.193*/194static void195sprintf_bytes(char *str, uint8_t *buf, uint_t buf_len)196{197int i, n;198199for (i = 0; i < buf_len; i++) {200n = sprintf(str, "%02x", buf[i] & 0xff);201str += n;202}203204str[0] = '\0';205}206207int208zstream_do_dump(int argc, char *argv[])209{210char *buf = safe_malloc(SPA_MAXBLOCKSIZE);211uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };212uint64_t total_payload_size = 0;213uint64_t total_overhead_size = 0;214uint64_t drr_byte_count[DRR_NUMTYPES] = { 0 };215char salt[ZIO_DATA_SALT_LEN * 2 + 1];216char iv[ZIO_DATA_IV_LEN * 2 + 1];217char mac[ZIO_DATA_MAC_LEN * 2 + 1];218uint64_t total_records = 0;219uint64_t payload_size;220dmu_replay_record_t thedrr;221dmu_replay_record_t *drr = &thedrr;222struct drr_begin *drrb = &thedrr.drr_u.drr_begin;223struct drr_end *drre = &thedrr.drr_u.drr_end;224struct drr_object *drro = &thedrr.drr_u.drr_object;225struct drr_freeobjects *drrfo = &thedrr.drr_u.drr_freeobjects;226struct drr_write *drrw = &thedrr.drr_u.drr_write;227struct drr_write_byref *drrwbr = &thedrr.drr_u.drr_write_byref;228struct drr_free *drrf = &thedrr.drr_u.drr_free;229struct drr_spill *drrs = &thedrr.drr_u.drr_spill;230struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;231struct drr_object_range *drror = &thedrr.drr_u.drr_object_range;232struct drr_redact *drrr = &thedrr.drr_u.drr_redact;233struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;234int c;235boolean_t verbose = B_FALSE;236boolean_t very_verbose = B_FALSE;237boolean_t first = B_TRUE;238/*239* dump flag controls whether the contents of any modified data blocks240* are printed to the console during processing of the stream. Warning:241* for large streams, this can obviously lead to massive prints.242*/243boolean_t dump = B_FALSE;244int err;245zio_cksum_t zc = { { 0 } };246zio_cksum_t pcksum = { { 0 } };247248while ((c = getopt(argc, argv, ":vCd")) != -1) {249switch (c) {250case 'C':251do_cksum = B_FALSE;252break;253case 'v':254if (verbose)255very_verbose = B_TRUE;256verbose = B_TRUE;257break;258case 'd':259dump = B_TRUE;260verbose = B_TRUE;261very_verbose = B_TRUE;262break;263case ':':264(void) fprintf(stderr,265"missing argument for '%c' option\n", optopt);266zstream_usage();267break;268case '?':269(void) fprintf(stderr, "invalid option '%c'\n",270optopt);271zstream_usage();272break;273}274}275276if (argc > optind) {277const char *filename = argv[optind];278send_stream = fopen(filename, "r");279if (send_stream == NULL) {280(void) fprintf(stderr,281"Error while opening file '%s': %s\n",282filename, strerror(errno));283exit(1);284}285} else {286if (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");293exit(1);294}295send_stream = stdin;296}297298fletcher_4_init();299while (read_hdr(drr, &zc)) {300uint64_t featureflags = 0;301302/*303* If this is the first DMU record being processed, check for304* the magic bytes and figure out the endian-ness based on them.305*/306if (first) {307if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {308do_byteswap = B_TRUE;309if (do_cksum) {310ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0);311/*312* recalculate header checksum now313* that we know it needs to be314* byteswapped.315*/316fletcher_4_incremental_byteswap(drr,317sizeof (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");322exit(1);323}324first = B_FALSE;325}326if (do_byteswap) {327drr->drr_type = BSWAP_32(drr->drr_type);328drr->drr_payloadlen =329BSWAP_32(drr->drr_payloadlen);330}331332/*333* At this point, the leading fields of the replay record334* (drr_type and drr_payloadlen) have been byte-swapped if335* necessary, but the rest of the data structure (the336* union of type-specific structures) is still in its337* original state.338*/339if (drr->drr_type >= DRR_NUMTYPES) {340(void) printf("INVALID record found: type 0x%x\n",341drr->drr_type);342(void) printf("Aborting.\n");343exit(1);344}345346drr_record_count[drr->drr_type]++;347total_overhead_size += sizeof (*drr);348total_records++;349payload_size = 0;350351switch (drr->drr_type) {352case DRR_BEGIN:353if (do_byteswap) {354drrb->drr_magic = BSWAP_64(drrb->drr_magic);355drrb->drr_versioninfo =356BSWAP_64(drrb->drr_versioninfo);357drrb->drr_creation_time =358BSWAP_64(drrb->drr_creation_time);359drrb->drr_type = BSWAP_32(drrb->drr_type);360drrb->drr_flags = BSWAP_32(drrb->drr_flags);361drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);362drrb->drr_fromguid =363BSWAP_64(drrb->drr_fromguid);364}365366(void) printf("BEGIN record\n");367(void) printf("\thdrtype = %lld\n",368DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo));369(void) printf("\tfeatures = %llx\n",370DMU_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);382(void) printf("\tpayloadlen = %u\n",383drr->drr_payloadlen);384if (verbose)385(void) printf("\n");386387if (drr->drr_payloadlen != 0) {388nvlist_t *nv;389int sz = drr->drr_payloadlen;390391if (sz > SPA_MAXBLOCKSIZE) {392free(buf);393buf = safe_malloc(sz);394}395(void) ssread(buf, sz, &zc);396if (ferror(send_stream))397perror("fread");398err = nvlist_unpack(buf, sz, &nv, 0);399if (err) {400perror(strerror(err));401} else {402nvlist_print(stdout, nv);403nvlist_free(nv);404}405payload_size = sz;406}407break;408409case DRR_END:410if (do_byteswap) {411drre->drr_checksum.zc_word[0] =412BSWAP_64(drre->drr_checksum.zc_word[0]);413drre->drr_checksum.zc_word[1] =414BSWAP_64(drre->drr_checksum.zc_word[1]);415drre->drr_checksum.zc_word[2] =416BSWAP_64(drre->drr_checksum.zc_word[2]);417drre->drr_checksum.zc_word[3] =418BSWAP_64(drre->drr_checksum.zc_word[3]);419}420/*421* We compare against the *previous* checksum422* value, because the stored checksum is of423* everything before the DRR_END record.424*/425if (do_cksum && !ZIO_CHECKSUM_EQUAL(drre->drr_checksum,426pcksum)) {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)438drre->drr_checksum.zc_word[0],439(long long unsigned int)440drre->drr_checksum.zc_word[1],441(long long unsigned int)442drre->drr_checksum.zc_word[2],443(long long unsigned int)444drre->drr_checksum.zc_word[3]);445446ZIO_SET_CHECKSUM(&zc, 0, 0, 0, 0);447break;448449case DRR_OBJECT:450if (do_byteswap) {451drro->drr_object = BSWAP_64(drro->drr_object);452drro->drr_type = BSWAP_32(drro->drr_type);453drro->drr_bonustype =454BSWAP_32(drro->drr_bonustype);455drro->drr_blksz = BSWAP_32(drro->drr_blksz);456drro->drr_bonuslen =457BSWAP_32(drro->drr_bonuslen);458drro->drr_raw_bonuslen =459BSWAP_32(drro->drr_raw_bonuslen);460drro->drr_toguid = BSWAP_64(drro->drr_toguid);461drro->drr_maxblkid =462BSWAP_64(drro->drr_maxblkid);463}464465featureflags =466DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);467468if (featureflags & DMU_BACKUP_FEATURE_RAW &&469drro->drr_bonuslen > drro->drr_raw_bonuslen) {470(void) fprintf(stderr,471"Warning: Object %llu has bonuslen = "472"%u > raw_bonuslen = %u\n\n",473(u_longlong_t)drro->drr_object,474drro->drr_bonuslen, drro->drr_raw_bonuslen);475}476477payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);478479if (verbose) {480(void) printf("OBJECT object = %llu type = %u "481"bonustype = %u blksz = %u bonuslen = %u "482"dn_slots = %u raw_bonuslen = %u "483"flags = %u maxblkid = %llu "484"indblkshift = %u nlevels = %u "485"nblkptr = %u\n",486(u_longlong_t)drro->drr_object,487drro->drr_type,488drro->drr_bonustype,489drro->drr_blksz,490drro->drr_bonuslen,491drro->drr_dn_slots,492drro->drr_raw_bonuslen,493drro->drr_flags,494(u_longlong_t)drro->drr_maxblkid,495drro->drr_indblkshift,496drro->drr_nlevels,497drro->drr_nblkptr);498}499if (drro->drr_bonuslen > 0) {500(void) ssread(buf, payload_size, &zc);501if (dump)502print_block(buf, payload_size);503}504break;505506case DRR_FREEOBJECTS:507if (do_byteswap) {508drrfo->drr_firstobj =509BSWAP_64(drrfo->drr_firstobj);510drrfo->drr_numobjs =511BSWAP_64(drrfo->drr_numobjs);512drrfo->drr_toguid = BSWAP_64(drrfo->drr_toguid);513}514if (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}520break;521522case DRR_WRITE:523if (do_byteswap) {524drrw->drr_object = BSWAP_64(drrw->drr_object);525drrw->drr_type = BSWAP_32(drrw->drr_type);526drrw->drr_offset = BSWAP_64(drrw->drr_offset);527drrw->drr_logical_size =528BSWAP_64(drrw->drr_logical_size);529drrw->drr_toguid = BSWAP_64(drrw->drr_toguid);530drrw->drr_key.ddk_prop =531BSWAP_64(drrw->drr_key.ddk_prop);532drrw->drr_compressed_size =533BSWAP_64(drrw->drr_compressed_size);534}535536payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);537538/*539* If this is verbose and/or dump output,540* print info on the modified block541*/542if (verbose) {543sprintf_bytes(salt, drrw->drr_salt,544ZIO_DATA_SALT_LEN);545sprintf_bytes(iv, drrw->drr_iv,546ZIO_DATA_IV_LEN);547sprintf_bytes(mac, drrw->drr_mac,548ZIO_DATA_MAC_LEN);549550(void) printf("WRITE object = %llu type = %u "551"checksum type = %u compression type = %u "552"flags = %u offset = %llu "553"logical_size = %llu "554"compressed_size = %llu "555"payload_size = %llu props = %llx "556"salt = %s iv = %s mac = %s\n",557(u_longlong_t)drrw->drr_object,558drrw->drr_type,559drrw->drr_checksumtype,560drrw->drr_compressiontype,561drrw->drr_flags,562(u_longlong_t)drrw->drr_offset,563(u_longlong_t)drrw->drr_logical_size,564(u_longlong_t)drrw->drr_compressed_size,565(u_longlong_t)payload_size,566(u_longlong_t)drrw->drr_key.ddk_prop,567salt,568iv,569mac);570}571572/*573* Read the contents of the block in from STDIN to buf574*/575(void) ssread(buf, payload_size, &zc);576/*577* If in dump mode578*/579if (dump) {580print_block(buf, payload_size);581}582break;583584case DRR_WRITE_BYREF:585if (do_byteswap) {586drrwbr->drr_object =587BSWAP_64(drrwbr->drr_object);588drrwbr->drr_offset =589BSWAP_64(drrwbr->drr_offset);590drrwbr->drr_length =591BSWAP_64(drrwbr->drr_length);592drrwbr->drr_toguid =593BSWAP_64(drrwbr->drr_toguid);594drrwbr->drr_refguid =595BSWAP_64(drrwbr->drr_refguid);596drrwbr->drr_refobject =597BSWAP_64(drrwbr->drr_refobject);598drrwbr->drr_refoffset =599BSWAP_64(drrwbr->drr_refoffset);600drrwbr->drr_key.ddk_prop =601BSWAP_64(drrwbr->drr_key.ddk_prop);602}603if (verbose) {604(void) printf("WRITE_BYREF object = %llu "605"checksum type = %u props = %llx "606"offset = %llu length = %llu "607"toguid = %llx refguid = %llx "608"refobject = %llu refoffset = %llu\n",609(u_longlong_t)drrwbr->drr_object,610drrwbr->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}619break;620621case DRR_FREE:622if (do_byteswap) {623drrf->drr_object = BSWAP_64(drrf->drr_object);624drrf->drr_offset = BSWAP_64(drrf->drr_offset);625drrf->drr_length = BSWAP_64(drrf->drr_length);626}627if (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}634break;635case DRR_SPILL:636if (do_byteswap) {637drrs->drr_object = BSWAP_64(drrs->drr_object);638drrs->drr_length = BSWAP_64(drrs->drr_length);639drrs->drr_compressed_size =640BSWAP_64(drrs->drr_compressed_size);641drrs->drr_type = BSWAP_32(drrs->drr_type);642}643644payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);645646if (verbose) {647sprintf_bytes(salt, drrs->drr_salt,648ZIO_DATA_SALT_LEN);649sprintf_bytes(iv, drrs->drr_iv,650ZIO_DATA_IV_LEN);651sprintf_bytes(mac, drrs->drr_mac,652ZIO_DATA_MAC_LEN);653654(void) printf("SPILL block for object = %llu "655"length = %llu flags = %u "656"compression type = %u "657"compressed_size = %llu "658"payload_size = %llu "659"salt = %s iv = %s mac = %s\n",660(u_longlong_t)drrs->drr_object,661(u_longlong_t)drrs->drr_length,662drrs->drr_flags,663drrs->drr_compressiontype,664(u_longlong_t)drrs->drr_compressed_size,665(u_longlong_t)payload_size,666salt,667iv,668mac);669}670(void) ssread(buf, payload_size, &zc);671if (dump) {672print_block(buf, payload_size);673}674break;675case DRR_WRITE_EMBEDDED:676if (do_byteswap) {677drrwe->drr_object =678BSWAP_64(drrwe->drr_object);679drrwe->drr_offset =680BSWAP_64(drrwe->drr_offset);681drrwe->drr_length =682BSWAP_64(drrwe->drr_length);683drrwe->drr_toguid =684BSWAP_64(drrwe->drr_toguid);685drrwe->drr_lsize =686BSWAP_32(drrwe->drr_lsize);687drrwe->drr_psize =688BSWAP_32(drrwe->drr_psize);689}690if (verbose) {691(void) printf("WRITE_EMBEDDED object = %llu "692"offset = %llu length = %llu "693"toguid = %llx comp = %u etype = %u "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,699drrwe->drr_compression,700drrwe->drr_etype,701drrwe->drr_lsize,702drrwe->drr_psize);703}704(void) ssread(buf,705P2ROUNDUP(drrwe->drr_psize, 8), &zc);706if (dump) {707print_block(buf,708P2ROUNDUP(drrwe->drr_psize, 8));709}710payload_size = P2ROUNDUP(drrwe->drr_psize, 8);711break;712case DRR_OBJECT_RANGE:713if (do_byteswap) {714drror->drr_firstobj =715BSWAP_64(drror->drr_firstobj);716drror->drr_numslots =717BSWAP_64(drror->drr_numslots);718drror->drr_toguid = BSWAP_64(drror->drr_toguid);719}720if (verbose) {721sprintf_bytes(salt, drror->drr_salt,722ZIO_DATA_SALT_LEN);723sprintf_bytes(iv, drror->drr_iv,724ZIO_DATA_IV_LEN);725sprintf_bytes(mac, drror->drr_mac,726ZIO_DATA_MAC_LEN);727728(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,733drror->drr_flags,734salt,735iv,736mac);737}738break;739case DRR_REDACT:740if (do_byteswap) {741drrr->drr_object = BSWAP_64(drrr->drr_object);742drrr->drr_offset = BSWAP_64(drrr->drr_offset);743drrr->drr_length = BSWAP_64(drrr->drr_length);744drrr->drr_toguid = BSWAP_64(drrr->drr_toguid);745}746if (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}753break;754case DRR_NUMTYPES:755/* should never be reached */756exit(1);757}758if (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}765pcksum = zc;766drr_byte_count[drr->drr_type] += payload_size;767total_payload_size += payload_size;768}769free(buf);770fletcher_4_fini();771772/* Print final summary */773774(void) printf("SUMMARY:\n");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]);802(void) printf("\tTotal records = %lld\n",803(u_longlong_t)total_records);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);809(void) printf("\tTotal stream length = %lld (0x%llx)\n",810(u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len);811return (0);812}813814815