Created
October 31, 2024 07:49
-
-
Save ilyakurdyukov/c916aec0bbbb9a2584ae2c19dc39e07c to your computer and use it in GitHub Desktop.
Program to apply IPS patches.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdint.h> | |
#if 0 | |
#define DBG_LOG(...) fprintf(stderr, __VA_ARGS__) | |
#else | |
#define DBG_LOG(...) (void)0 | |
#endif | |
int main(int argc, char **argv) { | |
FILE *fo = NULL, *fi = stdin; | |
const char *err; unsigned n; | |
uint8_t buf[256]; | |
err = "Usage: ips_patch dest.bin [patch.ips]\n"; | |
if (argc < 2 || argc > 3) goto end; | |
if (argc > 2) { | |
fi = fopen(argv[2], "rb"); | |
err = "!!! can't open patch file\n"; | |
if (!fi) goto end; | |
} | |
err = "!!! fread failed\n"; | |
n = fread(buf, 1, 5, fi); | |
if (!n && fi == stdin) | |
err = "!!! expected patch in stdin\n"; | |
if (n != 5) goto end; | |
err = "!!! wrong patch header\n"; | |
if (memcmp(buf, "PATCH", 5)) goto end; | |
err = "!!! can't open dest file\n"; | |
fo = fopen(argv[1], "rb+"); | |
if (!fo) goto end; | |
for (;;) { | |
unsigned offset, size, rep = 0; | |
n = fread(buf, 1, 5, fi); | |
if (n != 5) { | |
err = "!!! fread failed\n"; | |
if (n == 3 && !memcmp(buf, "EOF", 3)) err = NULL; | |
break; | |
} | |
offset = buf[0] << 16 | buf[1] << 8 | buf[2]; | |
size = buf[3] << 8 | buf[4]; | |
if (!size) { | |
err = "!!! fread failed\n"; | |
if (fread(buf, 1, 3, fi) != 3) break; | |
size = rep = buf[0] << 8 | buf[1]; | |
DBG_LOG("rle: 0x%x, 0x%x, 0x%02x\n", offset, size, buf[2]); | |
err = "!!! empty rle record\n"; | |
if (!rep) goto end; | |
n = sizeof(buf); | |
if (n > size) n = size; | |
memset(buf, buf[2], n); | |
} else { | |
DBG_LOG("copy: 0x%x, 0x%x\n", offset, size); | |
} | |
err = "!!! fseek failed\n"; | |
if (fseek(fo, offset, SEEK_SET)) break; | |
do { | |
n = sizeof(buf); | |
if (n > size) n = size; | |
if (!rep) { | |
err = "!!! fread failed\n"; | |
if (fread(buf, 1, n, fi) != n) goto end; | |
} | |
err = "!!! fwrite failed\n"; | |
if (fwrite(buf, 1, n, fo) != n) goto end; | |
} while ((size -= n)); | |
} | |
end: | |
if (fo) fclose(fo); | |
if (fi != stdin) fclose(fi); | |
if (err) fputs(err, stderr); | |
return !!err; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment