ref: cc747ead109a2d48e0242108addf3cb8d349f2d3
author: Jacob Moody <moody@posixcafe.org>
date: Tue May 2 22:01:36 EDT 2023
initial commit
--- /dev/null
+++ b/ips.c
@@ -1,0 +1,97 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#define GET2(p) (u16int)(p)[1] | (u16int)(p)[0]<<8
+#define GET3(p) (u16int)(p)[2] | (u16int)(p)[1]<<8 | (u16int)(p[0])<<16
+
+enum{
+ Hdrsz = 3 + 2,
+ RLEsz = 2 + 1,
+};
+
+static uchar section[Hdrsz + 0xFFFF + RLEsz];
+static Biobuf *ips;
+
+static int
+readsect(u32int *off, u16int *sz)
+{
+ u16int count;
+ uchar val;
+
+ if(Bread(ips, section, 3) != 3)
+ sysfatal("short read of off: %r");
+ if(memcmp(section, "EOF", 3) == 0)
+ return 0;
+ if(Bread(ips, section + 3, 2) != 2)
+ sysfatal("short read of size: %r");
+ *off = GET3(section);
+
+ *sz = GET2(section + 3);
+ if(*sz == 0){
+ if(Bread(ips, section + Hdrsz + 0xFFFF, RLEsz) != RLEsz)
+ sysfatal("short read of RLE: %r");
+ count = GET2(section + Hdrsz + 0xFFFF);
+ val = section[Hdrsz + 0xFFFF + 2];
+ memset(section + Hdrsz, val, count);
+ *sz = count;
+ } else if(Bread(ips, section + Hdrsz, *sz) != *sz)
+ sysfatal("short read of data: %r");
+ return 1;
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s patch.ips <file.orig >file.new\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ ulong dot, x;
+ long n;
+ uchar buf[8192];
+ u32int off;
+ u16int sz;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND;
+ if(argc < 1)
+ usage();
+
+ ips = Bopen(argv[0], OREAD);
+ if(ips == nil)
+ sysfatal("open: %r");
+
+ if(Bread(ips, buf, 5) != 5)
+ sysfatal("short read on magic: %r");
+ if(memcmp(buf, "PATCH", 5) != 0)
+ sysfatal("bad magic");
+
+ if(readsect(&off, &sz) == 0)
+ sysfatal("not a single section");
+
+ for(dot = 0; (n = read(0, buf, sizeof buf)) > 0; dot += n){
+ while(off < dot+n){
+ if(off < dot)
+ sysfatal("skipped region");
+ if(off + sz > dot + n){
+ x = (dot + n) - off;
+ memcpy(buf + (off - dot), section + Hdrsz, x);
+ memmove(section + Hdrsz, section + Hdrsz + x, sz - x);
+ sz -= x;
+ off += x;
+ break;
+ }
+ memcpy(buf + (off - dot), section + Hdrsz, sz);
+ if(readsect(&off, &sz) == 0)
+ break;
+ }
+ write(1, buf, n);
+ }
+ exits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+
+BIN=$home/bin/$objtype
+TARG=ips
+OFILES=\
+ ips.$O\
+
+</sys/src/cmd/mkone