Imported Upstream version 2.3.3
[platform/upstream/cryptsetup.git] / tests / differ.c
1 /*
2  * cryptsetup file differ check (rewritten Clemens' fileDiffer in Python)
3  *
4  * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <ctype.h>
27 #include <sys/stat.h>
28 #include <sys/mman.h>
29
30 struct ffile {
31         char *name;
32         int fd;
33         unsigned char *addr;
34         size_t size;
35 };
36
37 enum df { OK , FAIL };
38
39 static void print_diff(off_t from, int max,
40                        const unsigned char *o,
41                        const unsigned char *n)
42 {
43         int i, len = max;
44
45         if (len > 16)
46                 len = 16;
47
48         printf("OLD:");
49         for (i = 0; i < len; i++)
50                 printf(" %02x", o[from + i]);
51         printf("%s\n    ", max != len ? " ..." : "");
52         for (i = 0; i < len; i++)
53                 printf(" %2c", o[from + i] > ' ' ? o[from + i]: '.');
54         printf("\nNEW:");
55         for (i = 0; i < len; i++)
56                 printf(" %02x", n[from + i]);
57         printf("%s\n    ", max != len ? " ..." : "");
58         for (i = 0; i < len; i++)
59                 printf(" %2c", n[from + i] > ' ' ? n[from + i]: '.');
60         printf("\n");
61 }
62
63 /*
64  * Xfrom-to (e.g. R10-15)
65  * A - change allowed
66  * S - change required, semantic
67  * R - change required, random
68  * F - change forbidden
69  */
70 static enum df check(const char *range, unsigned char *o, unsigned char *n)
71 {
72         char strict;
73         unsigned long long from, to;
74         enum df ret;
75
76         if (sscanf(range, "%c%llu-%llu", &strict, &from, &to) != 3) {
77                 printf("Unknown range format %s.\n", range);
78                 return FAIL;
79         }
80
81         switch (toupper(strict)) {
82         case 'A':
83                 ret = OK;
84                 break;
85         case 'S':
86                 ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
87                 break;
88         case 'R': /* FIXME - random test */
89                 ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
90                 break;
91         case 'F':
92                 ret = memcmp(&o[from], &n[from], to - from + 1) == 0 ? OK : FAIL;
93                 break;
94         default:
95                 ret = FAIL;
96                 break;
97         }
98
99         if (ret == FAIL)
100                 print_diff(from,  to - from + 1, o, n);
101
102         return ret;
103 }
104
105 static int open_mmap(struct ffile *f)
106 {
107         struct stat st;
108
109         f->fd = open(f->name, O_RDONLY);
110         if (f->fd == -1 || fstat(f->fd, &st) == -1)
111                 return 0;
112
113         f->size = st.st_size;
114         f->addr = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
115
116         return (f->addr == MAP_FAILED) ? 0 : 1;
117 }
118
119 static void close_mmap(struct ffile *f)
120 {
121         if (f->addr != MAP_FAILED && !munmap(f->addr, f->size))
122                 f->addr = MAP_FAILED;
123
124         if (f->fd != -1 && !close(f->fd))
125                 f->fd = -1;
126 }
127
128 int main(int argc, char *argv[])
129 {
130         int i, r = 1;
131         struct ffile file_old = {
132                 .fd = -1,
133                 .addr = MAP_FAILED,
134         };
135         struct ffile file_new = {
136                 .fd = -1,
137                 .addr = MAP_FAILED,
138         };
139
140         if (argc < 3) {
141                 printf("Use: differ old_file new_file change_list.\n");
142                 goto bad;
143         }
144
145         file_old.name = argv[1];
146         if (!open_mmap(&file_old))
147                 goto bad;
148
149         file_new.name = argv[2];
150         if (!open_mmap(&file_new))
151                 goto bad;
152
153         for (i = 3; i < argc; i++)
154                 if (check(argv[i], file_old.addr, file_new.addr) == FAIL) {
155                         printf ("FAILED for %s\n", argv[i]);
156                         r = 1;
157                         goto bad;
158                 }
159
160         r = 0;
161 bad:
162         close_mmap(&file_new);
163         close_mmap(&file_old);
164
165         return r;
166 }