Recursive Binary String Search

This program is similar to the other one I made a while back, except this one searches for matches against a binary (string) value instead. For ease of use, the binary string is specified using a hexadecimal string.

```#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>

static int hex_value(int c)
{
if (c >= 0x30 && c <= 0x39) /* '0' - '9' */
return c - 0x30;
else if (c >= 0x41 && c <= 0x46) /* 'A' - 'F' */
return (c - 0x41) + 10;
else if (c >= 0x61 && c <= 0x66) /* 'a' - 'f' */
return (c - 0x61) + 10;
else
return -1;
}

static int convert_from_hex(char *hex_string,
unsigned char *bin_string, int bin_string_len)
{
int n1, n2, high;

high = -1;
n1 = n2 = 0;
while (hex_string[n1] != '\0') {
if (hex_value(hex_string[n1]) >= 0) {
if (high == -1) {
high = hex_string[n1];
} else {
bin_string[n2] = hex_value(high) * 16 + hex_value(hex_string[n1]);
if (n2 >= bin_string_len)
break;
n2++;
high = -1;
}
}
n1++;
}

return n2;
}

static void search(char *path, unsigned char *bin_string, int len)
{
FILE *fh;

fh = fopen(path, "rb");
if (fh == NULL) {
fprintf(stderr, "Warning: Unable to open file: %s\n", path);
return;
}

while ((c = fgetc(fh)) != EOF) {
if (c == bin_string[match]) {
match++;
if (match >= len) {
if (! name_shown) {
printf("%s\n", path);
name_shown = 1;
}
match = 0;
}
} else {
match = 0;
}
}
fclose(fh);
}

static void recurse(char *path, unsigned char *bin_string, int len)
{
char full_path[PATH_MAX];
struct dirent *entry;
struct stat st;
DIR *dh;

dh = opendir(path);
if (dh == NULL) {
fprintf(stderr, "Warning: Unable to open directory: %s\n", path);
return;
}

if (entry->d_name[0] == '.')
continue; /* Ignore files with leading dot. */

#ifdef WINNT
snprintf(full_path, PATH_MAX, "%s\\%s", path, entry->d_name);
#else
snprintf(full_path, PATH_MAX, "%s/%s", path, entry->d_name);
#endif

stat(full_path, &st);
if (S_ISDIR(st.st_mode)) {
recurse(full_path, bin_string, len);
} else if (S_ISREG(st.st_mode)) {
search(full_path, bin_string, len);
}
}

closedir(dh);
return;
}

int main(int argc, char *argv[])
{
int len;
unsigned char *bin_string;
struct stat st;

if (argc != 3) {
fprintf(stderr, "Usage: %s <directory or file> <hex string>\n", argv[0]);
return 1;
}

len = strlen(argv[2]) / 2;
bin_string = malloc(sizeof(unsigned char) * len);
if (bin_string == NULL) {
fprintf(stderr, "Error: Unable to malloc().\n");
return 1;
}

len = convert_from_hex(argv[2], bin_string, len);
if (len == 0) {
fprintf(stderr, "Error: Invalid input hex string.\n");
return 1;
}

stat(argv[1], &st);
if (S_ISDIR(st.st_mode)) {
recurse(argv[1], bin_string, len);
} else if (S_ISREG(st.st_mode)) {
search(argv[1], bin_string, len);
} else {
fprintf(stderr, "Error: Not a directory or regular file.\n");
free(bin_string);
return 1;
}

free(bin_string);

return 0;
}
```

Topic: Scripts and Code, by Kjetil @ 05/01-2013, Article Link