aboutsummaryrefslogtreecommitdiff
path: root/reloc.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2019-11-13 16:46:39 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2019-11-13 16:46:39 -0500
commit534d2e4abb5ef821de5e04302d9217ba7bba5feb (patch)
tree7396c9352af1f9e7f2253ab7a533c174489f5376 /reloc.c
parent2653ac737f0df2a41d939e0c36f9b4ae502f5a48 (diff)
downloadreloc-534d2e4abb5ef821de5e04302d9217ba7bba5feb.tar.gz
Rename main.c
Diffstat (limited to 'reloc.c')
-rw-r--r--reloc.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/reloc.c b/reloc.c
new file mode 100644
index 0000000..ee3cc0b
--- /dev/null
+++ b/reloc.c
@@ -0,0 +1,184 @@
+#include "reloc.h"
+
+
+RelocMatch *reloc_match(char *haystack, const char *needle) {
+ char *data = haystack;
+ size_t needle_size = strlen(needle);
+ RelocMatch *match = NULL;
+
+ // Search the needle in the data
+ if (!(memcmp(data, needle, needle_size))) {
+ if (!(match = calloc(1, sizeof(RelocMatch)))) {
+ fprintf(stderr,"Failed to allocate RelocMatch structure: %s\n", strerror(errno));
+ exit(1);
+ }
+ size_t data_end = strlen(data);
+ match->begin = data;
+ match->end = match->begin + needle_size;
+ match->length = match->end - match->begin;
+ match->post = match->end;
+ match->post_length = strlen(match->post);
+ match->total_length = data_end;
+ }
+ return match;
+}
+
+
+RelocData *reloc_read(const char *filename) {
+ char *data = NULL;
+ FILE *fp = NULL;
+ size_t size = 0;
+ RelocData *result;
+
+ // Open file for reading in binary mode
+ if (!(fp = fopen(filename, "rb"))) {
+ fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+
+ // Determine file size
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ rewind(fp);
+
+ if (!(data = calloc(sizeof(char), size + 1))) {
+ fprintf(stderr, "Failed to allocate data array: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ // Read data into array
+ fread(data, sizeof(char), size, fp);
+ if (!(result = (RelocData *)malloc(sizeof(RelocData)))) {
+ fprintf(stderr, "Failed to allocate RelocData structure: %s\n", strerror(errno));
+ exit(1);
+ }
+ result->size = size;
+ result->data = data;
+ result->path = strdup(filename);
+ return result;
+}
+
+
+size_t reloc_write(RelocData *finfo, const char *filename) {
+ FILE *fp;
+
+ // Open file for writing in binary mode
+ if (!(fp = fopen(filename, "w+b"))) {
+ fprintf(stderr,"Cannot open %s for writing: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+
+ // Write data
+ return fwrite(finfo->data, sizeof(char), finfo->size, fp);
+}
+
+
+void reloc_deinit_data(RelocData *finfo) {
+ if (finfo) {
+ if (finfo->path) {
+ free(finfo->path);
+ }
+ free(finfo);
+ }
+}
+
+
+void reloc_replace(RelocMatch *match, const char *rstr) {
+ size_t rstr_length = strlen(rstr);
+ if (rstr_length > match->length) {
+ fprintf(stderr, "Replacement string is too long ("SIZE_T_FMT " > " SIZE_T_FMT ")\n", rstr_length, match->length);
+ return;
+ }
+ char *data = match->begin;
+ size_t i = 0;
+
+ // Overwrite data with replacement string
+ while (i < rstr_length) {
+ *data = *rstr;
+ data++;
+ rstr++;
+ i++;
+ }
+
+ i = 0;
+ // Append remaining bytes not part of the original match to the replaced string
+ char *post = match->post;
+ while (i < match->post_length) {
+ *data = *post;
+ data++;
+ post++;
+ i++;
+ }
+
+ // Destroy bytes between the end of the original data and the end of the replaced string
+ memset(data, '\0', post - data);
+}
+
+
+void show_version() {
+ printf("%s\n", VERSION);
+}
+
+
+int main(int argc, char *argv[]) {
+ char *program = argv[0];
+ char *program_relative = strrchr(program, DIRSEP);
+ if (program_relative) {
+ program = program_relative + 1;
+ }
+
+ for (int i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-V")) {
+ show_version();
+ exit(0);
+ }
+ }
+
+ if (argc < 5) {
+ printf("%s [-V] <str1> <str2> <input_file> <output_file>\n"
+ "\n"
+ "Arguments:\n"
+ "--version (-V) - Display version and exit\n"
+ "str1 - Pattern to search for\n"
+ "str2 - Replace str1 with contents of str2\n"
+ "input_file - Path to input file\n"
+ "output_file - Path to output file\n"
+ "\n"
+ "Example:\n"
+ "%s /original/path /new/path input.bin output.bin\n"
+ "\n", program, program);
+ exit(1);
+ }
+
+ char *needle = strdup(argv[1]);
+ char *replacement = strdup(argv[2]);
+ char *input_file = strdup(argv[3]);
+ char *output_file = strdup(argv[4]);
+ RelocData *info = reloc_read(input_file);
+ size_t records = 0;
+
+ for (size_t i = 0; i < info->size; i++) {
+ RelocMatch *match = NULL;
+ if (!(match = reloc_match(&info->data[i], needle))) {
+ // No match found
+ continue;
+ }
+ // Replace string
+ reloc_replace(match, replacement);
+ free(match);
+ records++;
+ }
+
+ // Write output file to disk
+ reloc_write(info, output_file);
+
+ // Report number of strings processed
+ printf(SIZE_T_FMT"\n", records);
+
+ free(needle);
+ free(replacement);
+ free(input_file);
+ free(output_file);
+ reloc_deinit_data(info);
+ return 0;
+}