1*716fd348SMartin Matuska /* 2*716fd348SMartin Matuska * This file and its contents are supplied under the terms of the 3*716fd348SMartin Matuska * Common Development and Distribution License ("CDDL"), version 1.0. 4*716fd348SMartin Matuska * You may only use this file in accordance with the terms of version 5*716fd348SMartin Matuska * 1.0 of the CDDL. 6*716fd348SMartin Matuska * 7*716fd348SMartin Matuska * A full copy of the text of the CDDL should have accompanied this 8*716fd348SMartin Matuska * source. A copy of the CDDL is also available via the Internet at 9*716fd348SMartin Matuska * http://www.illumos.org/license/CDDL. 10*716fd348SMartin Matuska */ 11*716fd348SMartin Matuska 12*716fd348SMartin Matuska /* 13*716fd348SMartin Matuska * Copyright (c) 2018 by Delphix. All rights reserved. 14*716fd348SMartin Matuska */ 15*716fd348SMartin Matuska 16*716fd348SMartin Matuska #include <stdio.h> 17*716fd348SMartin Matuska #include <fcntl.h> 18*716fd348SMartin Matuska #include <unistd.h> 19*716fd348SMartin Matuska #include <stdlib.h> 20*716fd348SMartin Matuska #include <string.h> 21*716fd348SMartin Matuska #include <assert.h> 22*716fd348SMartin Matuska #include <sys/param.h> 23*716fd348SMartin Matuska #include <sys/types.h> 24*716fd348SMartin Matuska #include <sys/stat.h> 25*716fd348SMartin Matuska #include <errno.h> 26*716fd348SMartin Matuska 27*716fd348SMartin Matuska static void 28*716fd348SMartin Matuska usage(char *msg, int exit_value) 29*716fd348SMartin Matuska { 30*716fd348SMartin Matuska (void) fprintf(stderr, "get_diff file redacted_file\n"); 31*716fd348SMartin Matuska (void) fprintf(stderr, "%s\n", msg); 32*716fd348SMartin Matuska exit(exit_value); 33*716fd348SMartin Matuska } 34*716fd348SMartin Matuska 35*716fd348SMartin Matuska /* 36*716fd348SMartin Matuska * This utility compares two files, an original and its redacted counterpart 37*716fd348SMartin Matuska * (in that order). It compares the files 512 bytes at a time, printing out 38*716fd348SMartin Matuska * any ranges (as offset and length) where the redacted file does not match 39*716fd348SMartin Matuska * the original. This output is used to verify that the expected ranges of 40*716fd348SMartin Matuska * a redacted file do not contain the original data. 41*716fd348SMartin Matuska */ 42*716fd348SMartin Matuska int 43*716fd348SMartin Matuska main(int argc, char *argv[]) 44*716fd348SMartin Matuska { 45*716fd348SMartin Matuska off_t diff_off = 0, diff_len = 0, off = 0; 46*716fd348SMartin Matuska int fd1, fd2; 47*716fd348SMartin Matuska char *fname1, *fname2; 48*716fd348SMartin Matuska char buf1[DEV_BSIZE], buf2[DEV_BSIZE]; 49*716fd348SMartin Matuska ssize_t bytes; 50*716fd348SMartin Matuska 51*716fd348SMartin Matuska if (argc != 3) 52*716fd348SMartin Matuska usage("Incorrect number of arguments.", 1); 53*716fd348SMartin Matuska 54*716fd348SMartin Matuska if ((fname1 = argv[1]) == NULL) 55*716fd348SMartin Matuska usage("Filename missing.", 1); 56*716fd348SMartin Matuska if ((fd1 = open(fname1, O_LARGEFILE | O_RDONLY)) < 0) { 57*716fd348SMartin Matuska perror("open1 failed"); 58*716fd348SMartin Matuska exit(1); 59*716fd348SMartin Matuska } 60*716fd348SMartin Matuska 61*716fd348SMartin Matuska if ((fname2 = argv[2]) == NULL) 62*716fd348SMartin Matuska usage("Redacted filename missing.", 1); 63*716fd348SMartin Matuska if ((fd2 = open(fname2, O_LARGEFILE | O_RDONLY)) < 0) { 64*716fd348SMartin Matuska perror("open2 failed"); 65*716fd348SMartin Matuska exit(1); 66*716fd348SMartin Matuska } 67*716fd348SMartin Matuska 68*716fd348SMartin Matuska while ((bytes = pread(fd1, buf1, DEV_BSIZE, off)) > 0) { 69*716fd348SMartin Matuska if (pread(fd2, buf2, DEV_BSIZE, off) < 0) { 70*716fd348SMartin Matuska if (errno == EIO) { 71*716fd348SMartin Matuska /* 72*716fd348SMartin Matuska * A read in a redacted section of a file will 73*716fd348SMartin Matuska * fail with EIO. If we get EIO, continue on 74*716fd348SMartin Matuska * but ensure that a comparison of buf1 and 75*716fd348SMartin Matuska * buf2 will fail, indicating a redacted block. 76*716fd348SMartin Matuska */ 77*716fd348SMartin Matuska buf2[0] = ~buf1[0]; 78*716fd348SMartin Matuska } else { 79*716fd348SMartin Matuska perror("pread failed"); 80*716fd348SMartin Matuska exit(1); 81*716fd348SMartin Matuska } 82*716fd348SMartin Matuska } 83*716fd348SMartin Matuska if (memcmp(buf1, buf2, bytes) == 0) { 84*716fd348SMartin Matuska if (diff_len != 0) { 85*716fd348SMartin Matuska (void) fprintf(stdout, "%lld,%lld\n", 86*716fd348SMartin Matuska (long long)diff_off, (long long)diff_len); 87*716fd348SMartin Matuska assert(off == diff_off + diff_len); 88*716fd348SMartin Matuska diff_len = 0; 89*716fd348SMartin Matuska } 90*716fd348SMartin Matuska diff_off = 0; 91*716fd348SMartin Matuska } else { 92*716fd348SMartin Matuska if (diff_len == 0) 93*716fd348SMartin Matuska diff_off = off; 94*716fd348SMartin Matuska assert(off == diff_off + diff_len); 95*716fd348SMartin Matuska diff_len += bytes; 96*716fd348SMartin Matuska } 97*716fd348SMartin Matuska off += bytes; 98*716fd348SMartin Matuska } 99*716fd348SMartin Matuska 100*716fd348SMartin Matuska if (diff_len != 0 && diff_len != 0) { 101*716fd348SMartin Matuska (void) fprintf(stdout, "%lld,%lld\n", (long long)diff_off, 102*716fd348SMartin Matuska (long long)diff_len); 103*716fd348SMartin Matuska } 104*716fd348SMartin Matuska 105*716fd348SMartin Matuska (void) close(fd1); 106*716fd348SMartin Matuska (void) close(fd2); 107*716fd348SMartin Matuska 108*716fd348SMartin Matuska return (0); 109*716fd348SMartin Matuska } 110