/* Copyright 2013, V. This file is part of findcrcs. findcrcs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. findcrcs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with findcrcs. If not, see . */ /* findcrcs is using crcutil-1.0 for providing fast crc calculations crcutil is made by Andrew Kadatch and Bob Jenkins and can be found on http://code.google.com/p/crcutil/ Do not contact them for support on findcrcs Also, findcrcs makes use of the MD5 implementation of Alexander Peslyak. This is found at http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 A small casting patch was made to support g++. This patch is released under the same license as the original md5.c file. */ // Usage: findcrcs [more crcs...] // not yet idiotproof // code comments also not included (yet, if ever) #include #include #include #include #include #include #include #include "md5.h" #include "interface.h" #ifndef O_BINARY #define O_BINARY 0 #endif #define BUFFERSIZE 65536 #define MD5_DIGEST_LENGTH 16 void checkcrcs(unsigned int crc, unsigned int crcs[], int totalcrcs, int fd, int offset, int windowsize); int main(int argc, char *argv[]) { int i1, i2, fd1, fd2, fd3, filesize, windowsize, readbytes; char *filename; crcutil_interface::CRC *crc; unsigned long long returnvalue; unsigned char buffer1[BUFFERSIZE], buffer2[BUFFERSIZE]; struct stat stats; unsigned int crcs[argc - 3]; if (argc < 4) { fprintf(stderr, "usage: findcrcs [more crcs...]\n"); return 1; } filename = argv[1]; if (stat(filename, &stats) == -1) { perror("findcrcs"); return 1; } filesize = stats.st_size; windowsize = atoi(argv[2]); if (windowsize > filesize) { fprintf(stderr, "findcrcs: window size too big\n"); return 1; } for (i1 = 0; i1 < argc - 3; i1++) { crcs[i1] = (unsigned int)strtoul(argv[i1 + 3], 0, 16); } crc = crcutil_interface::CRC::Create(0xedb88320, 0, 32, true, 0, 0, windowsize, 0, NULL); fd1 = open(filename, O_RDONLY | O_BINARY); fd2 = open(filename, O_RDONLY | O_BINARY); fd3 = open(filename, O_RDONLY | O_BINARY); returnvalue = 0; for (i1 = 0; i1 < windowsize / BUFFERSIZE; i1++) { read(fd1, &buffer1, BUFFERSIZE); crc->Compute(&buffer1, BUFFERSIZE, &returnvalue); } if ((windowsize % BUFFERSIZE) != 0) { read(fd1, &buffer1, (windowsize % BUFFERSIZE)); crc->Compute(&buffer1, (windowsize % BUFFERSIZE), &returnvalue); } checkcrcs((unsigned int)returnvalue, crcs, argc - 3, fd3, 0, windowsize); for (i1 = 0; i1 < ((filesize - windowsize) / BUFFERSIZE) + 1; i1++) { readbytes = read(fd1, &buffer1, BUFFERSIZE); read(fd2, &buffer2, BUFFERSIZE); for (i2 = 0; i2 < readbytes; i2++) { crc->Roll(buffer2[i2], buffer1[i2], &returnvalue, NULL); checkcrcs((unsigned int)returnvalue, crcs, argc - 3, fd3, (i1 * BUFFERSIZE) + i2 + 1, windowsize); } } close(fd3); close(fd2); close(fd1); crc->Delete(); return 0; } void checkcrcs(unsigned int crc, unsigned int crcs[], int totalcrcs, int fd, int offset, int windowsize) { int i1, i2; unsigned int buffer[BUFFERSIZE]; unsigned char md5[MD5_DIGEST_LENGTH]; MD5_CTX ctx; for (i1 = 0; i1 < totalcrcs; i1++) { if (crc == crcs[i1]) { lseek(fd, offset, SEEK_SET); MD5_Init(&ctx); for (i2 = 0; i2 < windowsize / BUFFERSIZE; i2++) { read(fd, &buffer, BUFFERSIZE); MD5_Update(&ctx, &buffer, BUFFERSIZE); } if ((windowsize % BUFFERSIZE) != 0) { read(fd, &buffer, (windowsize % BUFFERSIZE)); MD5_Update(&ctx, &buffer, (windowsize % BUFFERSIZE)); } MD5_Final(md5, &ctx); printf("%d %08x ", offset, crc); for (i2 = 0; i2 < MD5_DIGEST_LENGTH; i2++) { printf("%02x", md5[i2]); } printf("\n"); return; } } }