-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
111 lines (97 loc) · 2.9 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "reloc.h"
void show_version() {
printf("%s\n", VERSION);
}
void usage(char *program) {
printf("usage: %s [-hV] <str1> <str2> <input_file> [output_file]\n"
"\n"
"Options:\n"
"--help (-h) - Display this help message and exit\n"
"--version (-V) - Display version and exit\n"
"\n"
"Positional arguments:\n"
"str1 - Search string\n"
"str2 - Replacement string\n"
"input_file - Input file name\n"
"output_file - Output file name\n"
"\n"
"Example:\n"
"%s /original/string /new/string input.bin output.bin\n"
"\n", program, program);
}
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], "--help") || !strcmp(argv[i], "-h")) {
usage(program);
exit(0);
}
if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-V")) {
show_version();
exit(0);
}
}
if (argc < 4) {
usage(program);
exit(1);
}
char *needle = strdup(argv[1]);
char *replacement = strdup(argv[2]);
char *input_file = strdup(argv[3]);
char *output_file = NULL;
unsigned char in_place = 0;
size_t records = 0;
size_t replacement_length = strlen(replacement);
RelocData *info = NULL;
if (argc > 4) {
output_file = strdup(argv[4]);
} else {
output_file = input_file;
in_place = 1;
}
if (!(info = reloc_read(input_file))) {
reloc_perror(input_file);
exit(reloc_error);
}
for (size_t i = 0; i < info->size; i++) {
RelocMatch *match = NULL;
if (!(match = reloc_match(&info->data[i], needle))) {
if (reloc_error) {
reloc_perror("reloc_match: ");
reloc_deinit_data(info);
exit(reloc_error);
}
// No match found
continue;
}
if (replacement_length > match->length) {
fprintf(stderr, "Replacement string is too long ("SIZE_T_FMT " > " SIZE_T_FMT ")\n", replacement_length, match->length);
free(match);
continue;
}
// Replace string
reloc_replace(match, replacement);
free(match);
records++;
}
// Write output file to disk
reloc_write(info, output_file);
if (reloc_error) {
perror(output_file);
exit(reloc_error);
}
// Report number of strings processed
printf(SIZE_T_FMT"\n", records);
free(needle);
free(replacement);
free(input_file);
input_file = NULL;
if (!in_place)
free(output_file);
reloc_deinit_data(info);
return 0;
}