1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* cryptsetup file differ check (rewritten Clemens' fileDiffer in Python)
*
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/mman.h>
struct ffile {
char *name;
int fd;
unsigned char *addr;
size_t size;
};
enum df { OK , FAIL };
static void print_diff(off_t from, int max,
const unsigned char *o,
const unsigned char *n)
{
int i, len = max;
if (len > 16)
len = 16;
printf("OLD:");
for (i = 0; i < len; i++)
printf(" %02x", o[from + i]);
printf("%s\n ", max != len ? " ..." : "");
for (i = 0; i < len; i++)
printf(" %2c", o[from + i] > ' ' ? o[from + i]: '.');
printf("\nNEW:");
for (i = 0; i < len; i++)
printf(" %02x", n[from + i]);
printf("%s\n ", max != len ? " ..." : "");
for (i = 0; i < len; i++)
printf(" %2c", n[from + i] > ' ' ? n[from + i]: '.');
printf("\n");
}
/*
* Xfrom-to (e.g. R10-15)
* A - change allowed
* S - change required, semantic
* R - change required, random
* F - change forbidden
*/
static enum df check(const char *range, unsigned char *o, unsigned char *n)
{
char strict;
unsigned long long from, to;
enum df ret;
if (sscanf(range, "%c%llu-%llu", &strict, &from, &to) != 3) {
printf("Unknown range format %s.\n", range);
return FAIL;
}
switch (toupper(strict)) {
case 'A':
ret = OK;
break;
case 'S':
ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
break;
case 'R': /* FIXME - random test */
ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
break;
case 'F':
ret = memcmp(&o[from], &n[from], to - from + 1) == 0 ? OK : FAIL;
break;
default:
ret = FAIL;
break;
}
if (ret == FAIL)
print_diff(from, to - from + 1, o, n);
return ret;
}
static int open_mmap(struct ffile *f)
{
struct stat st;
f->fd = open(f->name, O_RDONLY);
if (f->fd == -1 || fstat(f->fd, &st) == -1)
return 0;
f->size = st.st_size;
f->addr = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
return (f->addr == MAP_FAILED) ? 0 : 1;
}
static void close_mmap(struct ffile *f)
{
if (f->addr != MAP_FAILED && !munmap(f->addr, f->size))
f->addr = MAP_FAILED;
if (f->fd != -1 && !close(f->fd))
f->fd = -1;
}
int main(int argc, char *argv[])
{
int i, r = 1;
struct ffile file_old = {
.fd = -1,
.addr = MAP_FAILED,
};
struct ffile file_new = {
.fd = -1,
.addr = MAP_FAILED,
};
if (argc < 3) {
printf("Use: differ old_file new_file change_list.\n");
goto bad;
}
file_old.name = argv[1];
if (!open_mmap(&file_old))
goto bad;
file_new.name = argv[2];
if (!open_mmap(&file_new))
goto bad;
for (i = 3; i < argc; i++)
if (check(argv[i], file_old.addr, file_new.addr) == FAIL) {
printf ("FAILED for %s\n", argv[i]);
r = 1;
goto bad;
}
r = 0;
bad:
close_mmap(&file_new);
close_mmap(&file_old);
return r;
}
|