#define _LARGE_FILE_SOURCE 1 #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #define PATMAXLEN 1024 #define PATMAXPRINT 16 #define hexdigval(c) ((c) <= '9' ? (c) - '0' : tolower((c)) - 'a' + 10) const uint8_t *mmap_ro( const char *fname, off_t *size ); int main( int argc, char **argv ) { const uint8_t *data, *scan; uint8_t *pattern, *mask; unsigned *histo; off_t filesize, offset; unsigned argind, patdigs, maskdigs, patlen; int nonxdig, ind, cind; patdigs= maskdigs= 0; if( argc >= 3 ) { for( ind= 0; argv[1][ind]; ++ind ) if( isxdigit(argv[1][ind]) ) ++patdigs; if( argc > 3 ) for( ind= 0; argv[2][ind]; ++ind ) if( isxdigit(argv[2][ind]) ) ++maskdigs; } if( !patdigs || argc != 3 && argc != 4 || argc == 4 && !maskdigs || !strcmp("-h", argv[1]) || !strcmp("--help", argv[1]) ) { fprintf(stderr, "Usage: bingrep [ ] \n" "Prints offsets and values of occurrences of (optionally and'ed with\n" ") in . must be given without 0x prefix and in storage\n" "order.\n"); return 1; } if( (patdigs & 1) || maskdigs && patdigs != maskdigs ) fprintf(stderr, "Warning: odd number of digits in pattern or differing lengths of pattern and mask will be right aligned, i.e. filled up with zeros / truncated on the left.\n"); if( maskdigs > 0 ) { patlen= (maskdigs + 1) / 2; pattern= malloc(2*patlen); mask= pattern + patlen; } else { patlen= (patdigs + 1) / 2; pattern= malloc(patlen); mask= NULL; } if( ! pattern ) { fprintf(stderr, "Could not allocate memory for pattern\n"); return 2; } memset(pattern, 0, patlen); for( ind= patlen-1, cind= strlen(argv[1])-1; ind >= 0 && cind >= 0; --ind ) { while( !isxdigit(argv[1][cind]) ) if( --cind < 0 ) goto patdone; pattern[ind]= hexdigval(argv[1][cind]); do { if( --cind < 0 ) goto patdone; } while( !isxdigit(argv[1][cind]) ); pattern[ind] += 16 * hexdigval(argv[1][cind]); --cind; } patdone: if( mask ) { memset(mask, 0, patlen); for( ind= patlen-1, cind= strlen(argv[2])-1; ind >= 0 && cind >= 0; --ind ) { while( !isxdigit(argv[2][cind]) ) if( --cind < 0 ) goto patdone; mask[ind]= hexdigval(argv[2][cind]); do { if( --cind < 0 ) goto patdone; } while( !isxdigit(argv[2][cind]) ); mask[ind] += 16 * hexdigval(argv[2][cind]); --cind; } } data= mmap_ro(argv[argc-1], &filesize); if( ! data ) return 2; if( !mask ) for( offset= 0; scan= memmem(data+offset, filesize-offset, pattern, patlen); ++offset ) { offset= scan - data; printf("%012llX %16llu\n", offset, offset); } else for( offset= 0; offset <= filesize-patlen; ++offset ) { for( ind= 0; ind< patlen && (data[offset+ind] & mask[ind]) == pattern[ind]; ++ind ); if( ind == patlen ) { printf("%012llX %16llu ", offset, offset); for( ind= 0; ind< patlen && ind< PATMAXPRINT; ++ind ) printf(" %02X", data[offset+ind]); printf("\n"); } } munmap((void*)data, filesize); free(pattern); return 0; } const uint8_t *mmap_ro( const char *fname, off_t *size ) { struct stat statdata; uint8_t *map; size_t flen; int fd; fd= open(fname, O_RDONLY); if( fd < 0 ) { perror("Error opening file for memory mapping"); fprintf(stderr, "Could not open file %s.\n", fname); return NULL; } fstat(fd, &statdata); flen= statdata.st_size; map= mmap(NULL, flen, PROT_READ, MAP_SHARED, fd, 0); if( map == MAP_FAILED ) { perror("Error mapping file"); return NULL; } close(fd); *size= flen; return map; }