findhex

Hex pattern matcher
git clone https://git.sinitax.com/sinitax/findhex
Log | Files | Refs | LICENSE | sfeed.txt

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}