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