findhex.c (1668B)
1#include <err.h> 2#include <string.h> 3#include <stdint.h> 4#include <stdio.h> 5#include <stdlib.h> 6 7int 8main(int argc, const char **argv) 9{ 10 uint8_t *pattern, *pattern_mask; 11 size_t patlen; 12 uint8_t *buf; 13 size_t buflen; 14 ssize_t nread; 15 size_t i, k; 16 size_t pos, off; 17 size_t arglen; 18 FILE *file; 19 20 setvbuf(stdout, NULL, _IONBF, 0); 21 22 if (argc < 2 || argc > 3) { 23 printf("Usage: findhex PATTERN [FILE]\n"); 24 return 0; 25 } 26 27 arglen = strlen(argv[1]); 28 if (!arglen || arglen % 2 != 0) { 29 fprintf(stderr, "Pattern length invalid\n"); 30 return 1; 31 } 32 patlen = arglen / 2; 33 34 pattern = malloc(patlen); 35 if (!pattern) err(1, "malloc"); 36 37 pattern_mask = malloc(patlen); 38 if (!pattern_mask) err(1, "malloc"); 39 40 buflen = 16 * 1024; 41 if (patlen * 2 > buflen) 42 buflen = patlen * 2; 43 44 buf = malloc(buflen); 45 if (!buf) err(1, "malloc"); 46 47 for (i = 0; i < arglen; i += 2) { 48 if (!strncmp(argv[1] + i, "__", 2)) 49 continue; 50 if (!sscanf(argv[1] + i, "%02hhx", &pattern[i / 2])) { 51 fprintf(stderr, "Invalid hex in pattern\n"); 52 return 1; 53 } 54 pattern_mask[i / 2] = 0xff; 55 } 56 57 if (argc == 3) { 58 file = fopen(argv[2], "r"); 59 if (!file) err(1, "fopen"); 60 } else { 61 file = stdin; 62 } 63 64 off = patlen > 0 ? patlen - 1 : 0; 65 if (fread(buf, 1, off, file) != off) 66 exit(0); 67 68 pos = 0; 69 while (1) { 70 nread = fread(buf + off, 1, buflen - off, file); 71 if (nread <= 0) break; 72 73 for (i = 0; i <= nread + off - patlen; i++) { 74 for (k = 0; k < patlen; k++) { 75 if (!pattern_mask[k]) 76 continue; 77 if (buf[i+k] != pattern[k]) 78 break; 79 } 80 if (k == patlen) 81 printf("%016lX\n", pos + i); 82 } 83 84 pos += nread; 85 memcpy(buf, buf + buflen - off, off); 86 } 87 88 fclose(file); 89}