-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipspatch.c
103 lines (90 loc) · 2.01 KB
/
ipspatch.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
#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 dump = 0;
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");
if(dump)
fprint(2, "%ud %ud\n", *off, *sz);
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{
case 'd':
dump++;
break;
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);
}