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
usage(const char * msg,int exit_value)28a0b956f5SMartin Matuska usage(const char *msg, int exit_value)
29716fd348SMartin Matuska {
30a0b956f5SMartin 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
main(int argc,char * argv[])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
99*be181ee2SMartin Matuska if (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