Skip to content

Instantly share code, notes, and snippets.

@ilyakurdyukov
Created October 31, 2024 07:49
Show Gist options
  • Save ilyakurdyukov/c916aec0bbbb9a2584ae2c19dc39e07c to your computer and use it in GitHub Desktop.
Save ilyakurdyukov/c916aec0bbbb9a2584ae2c19dc39e07c to your computer and use it in GitHub Desktop.
Program to apply IPS patches.
#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