xref: /freebsd-src/sys/contrib/openzfs/tests/zfs-tests/cmd/get_diff.c (revision 716fd348e01c5f2ba125f878a634a753436c2994)
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