1716fd348SMartin Matuska /* 2716fd348SMartin Matuska * This file and its contents are supplied under the terms of the 3716fd348SMartin Matuska * Common Development and Distribution License ("CDDL"), version 1.0. 4716fd348SMartin Matuska * You may only use this file in accordance with the terms of version 5716fd348SMartin Matuska * 1.0 of the CDDL. 6716fd348SMartin Matuska * 7716fd348SMartin Matuska * A full copy of the text of the CDDL should have accompanied this 8716fd348SMartin Matuska * source. A copy of the CDDL is also available via the Internet at 9716fd348SMartin Matuska * http://www.illumos.org/license/CDDL. 10716fd348SMartin Matuska */ 11716fd348SMartin Matuska 12716fd348SMartin Matuska /* 13716fd348SMartin Matuska * Copyright (c) 2018 by Delphix. All rights reserved. 14716fd348SMartin Matuska */ 15716fd348SMartin Matuska 16716fd348SMartin Matuska #include <stdio.h> 17716fd348SMartin Matuska #include <fcntl.h> 18716fd348SMartin Matuska #include <unistd.h> 19716fd348SMartin Matuska #include <stdlib.h> 20716fd348SMartin Matuska #include <string.h> 21716fd348SMartin Matuska #include <assert.h> 22716fd348SMartin Matuska #include <sys/param.h> 23716fd348SMartin Matuska #include <sys/types.h> 24716fd348SMartin Matuska #include <sys/stat.h> 25716fd348SMartin Matuska #include <errno.h> 26716fd348SMartin Matuska 27716fd348SMartin Matuska static void 28*a0b956f5SMartin Matuska usage(const char *msg, int exit_value) 29716fd348SMartin Matuska { 30*a0b956f5SMartin Matuska (void) fprintf(stderr, "usage: get_diff file redacted_file\n%s\n", msg); 31716fd348SMartin Matuska exit(exit_value); 32716fd348SMartin Matuska } 33716fd348SMartin Matuska 34716fd348SMartin Matuska /* 35716fd348SMartin Matuska * This utility compares two files, an original and its redacted counterpart 36716fd348SMartin Matuska * (in that order). It compares the files 512 bytes at a time, printing out 37716fd348SMartin Matuska * any ranges (as offset and length) where the redacted file does not match 38716fd348SMartin Matuska * the original. This output is used to verify that the expected ranges of 39716fd348SMartin Matuska * a redacted file do not contain the original data. 40716fd348SMartin Matuska */ 41716fd348SMartin Matuska int 42716fd348SMartin Matuska main(int argc, char *argv[]) 43716fd348SMartin Matuska { 44716fd348SMartin Matuska off_t diff_off = 0, diff_len = 0, off = 0; 45716fd348SMartin Matuska int fd1, fd2; 46716fd348SMartin Matuska char *fname1, *fname2; 47716fd348SMartin Matuska char buf1[DEV_BSIZE], buf2[DEV_BSIZE]; 48716fd348SMartin Matuska ssize_t bytes; 49716fd348SMartin Matuska 50716fd348SMartin Matuska if (argc != 3) 51716fd348SMartin Matuska usage("Incorrect number of arguments.", 1); 52716fd348SMartin Matuska 53716fd348SMartin Matuska if ((fname1 = argv[1]) == NULL) 54716fd348SMartin Matuska usage("Filename missing.", 1); 55716fd348SMartin Matuska if ((fd1 = open(fname1, O_LARGEFILE | O_RDONLY)) < 0) { 56716fd348SMartin Matuska perror("open1 failed"); 57716fd348SMartin Matuska exit(1); 58716fd348SMartin Matuska } 59716fd348SMartin Matuska 60716fd348SMartin Matuska if ((fname2 = argv[2]) == NULL) 61716fd348SMartin Matuska usage("Redacted filename missing.", 1); 62716fd348SMartin Matuska if ((fd2 = open(fname2, O_LARGEFILE | O_RDONLY)) < 0) { 63716fd348SMartin Matuska perror("open2 failed"); 64716fd348SMartin Matuska exit(1); 65716fd348SMartin Matuska } 66716fd348SMartin Matuska 67716fd348SMartin Matuska while ((bytes = pread(fd1, buf1, DEV_BSIZE, off)) > 0) { 68716fd348SMartin Matuska if (pread(fd2, buf2, DEV_BSIZE, off) < 0) { 69716fd348SMartin Matuska if (errno == EIO) { 70716fd348SMartin Matuska /* 71716fd348SMartin Matuska * A read in a redacted section of a file will 72716fd348SMartin Matuska * fail with EIO. If we get EIO, continue on 73716fd348SMartin Matuska * but ensure that a comparison of buf1 and 74716fd348SMartin Matuska * buf2 will fail, indicating a redacted block. 75716fd348SMartin Matuska */ 76716fd348SMartin Matuska buf2[0] = ~buf1[0]; 77716fd348SMartin Matuska } else { 78716fd348SMartin Matuska perror("pread failed"); 79716fd348SMartin Matuska exit(1); 80716fd348SMartin Matuska } 81716fd348SMartin Matuska } 82716fd348SMartin Matuska if (memcmp(buf1, buf2, bytes) == 0) { 83716fd348SMartin Matuska if (diff_len != 0) { 84716fd348SMartin Matuska (void) fprintf(stdout, "%lld,%lld\n", 85716fd348SMartin Matuska (long long)diff_off, (long long)diff_len); 86716fd348SMartin Matuska assert(off == diff_off + diff_len); 87716fd348SMartin Matuska diff_len = 0; 88716fd348SMartin Matuska } 89716fd348SMartin Matuska diff_off = 0; 90716fd348SMartin Matuska } else { 91716fd348SMartin Matuska if (diff_len == 0) 92716fd348SMartin Matuska diff_off = off; 93716fd348SMartin Matuska assert(off == diff_off + diff_len); 94716fd348SMartin Matuska diff_len += bytes; 95716fd348SMartin Matuska } 96716fd348SMartin Matuska off += bytes; 97716fd348SMartin Matuska } 98716fd348SMartin Matuska 99716fd348SMartin Matuska if (diff_len != 0 && diff_len != 0) { 100716fd348SMartin Matuska (void) fprintf(stdout, "%lld,%lld\n", (long long)diff_off, 101716fd348SMartin Matuska (long long)diff_len); 102716fd348SMartin Matuska } 103716fd348SMartin Matuska 104716fd348SMartin Matuska (void) close(fd1); 105716fd348SMartin Matuska (void) close(fd2); 106716fd348SMartin Matuska 107716fd348SMartin Matuska return (0); 108716fd348SMartin Matuska } 109