prime/tools/metroidbuildinfo.c

115 lines
3.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VERSION_MAX_LEN (size_t)(35)
#define METROID_BUILD_INFO_TAG "!#$MetroidBuildInfo!#$"
void* memmem(const void* l, size_t l_len, const void* s, size_t s_len) {
register char *cur, *last;
const char* cl = (const char*)l;
const char* cs = (const char*)s;
/* we need something to compare */
if (l_len == 0 || s_len == 0)
return NULL;
/* "s" must be smaller or equal to "l" */
if (l_len < s_len)
return NULL;
/* special case where s_len == 1 */
if (s_len == 1)
return memchr(l, (int)*cs, l_len);
/* the last position where its possible to find "s" in "l" */
last = (char*)cl + l_len - s_len;
for (cur = (char*)cl; cur <= last; cur++)
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
return cur;
return NULL;
}
int main(int argc, const char* argv[]) {
if (argc < 3) {
fprintf(stdout, "\t--- METROID BUILD INFO ---\n"
"\tWritten by Phillip \"Antidote\" Stephens\n"
"\tReleased under the MIT License\n\n"
"\tSets the MetroidBuildInfo tag value in a given binary\n"
"\tThe version string can be a maximum of 35 characters,\n"
"\texcluding null terminator\n"
"\t--------------------------\n"
);
fprintf(stdout, "Usage:\n"
"\tmetroidbuildinfo <binary> <build_file>\n");
return -1;
}
/* Let's try to get the source binary */
FILE* source = fopen(argv[1], "rb");
if (!source) {
fprintf(stderr, "Unable to open '%s'\nPlease ensure the file exists!\n", argv[1]);
return -2;
}
char build_string[36] = {0};
FILE* build = fopen(argv[2], "rb");
if (!build) {
fprintf(stderr, "Unable to open '%s'\nPlease ensure the file exists!\n", argv[2]);
return -3;
}
size_t read_len = fread(build_string, 1, 35, build);
fclose(build);
if (read_len <= 0) {
fprintf(stderr, "Empty file %s specified for build version!\n", argv[2]);
return -4;
}
build_string[strcspn(build_string, "\r\n")] = '\0';
/* Get source length */
fseek(source, 0, SEEK_END);
size_t source_len = ftell(source);
rewind(source);
void* source_buf = malloc(source_len);
if (source_buf == NULL) {
fprintf(stderr, "Unable to allocate buffer of size %zubytes!\n", source_len);
return -5;
}
fread(source_buf, 1, source_len, source);
fclose(source);
/* Find the build info tag so we can stuff our version info in the binary */
void* ptr =
memmem(source_buf, source_len, METROID_BUILD_INFO_TAG, strlen(METROID_BUILD_INFO_TAG));
if (ptr == NULL) {
fprintf(stderr, "Unable to find build info tag in source!\n");
return -6;
}
/* Lets actually copy over the build string */
strcpy(ptr + strlen(METROID_BUILD_INFO_TAG), build_string);
/* Now attempt to open the target file */
FILE* target = fopen(argv[1], "wb");
if (!target) {
fprintf(stderr, "Unable to open '%s'\nPlease ensure you have write permissions!\n", argv[1]);
return -7;
}
/* Finally write the buffer to the target file */
fwrite(source_buf, 1, source_len, target);
fclose(target);
/* Don't leak */
free(source_buf);
return 0;
}