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
104
105
106
107
108
|
#include <u.h>
#include <libc.h>
#include <flate.h>
int infd, outfd;
ulong dcrc;
ulong *tab;
uchar buf[65536];
enum {
IH_TYPE_SCRIPT = 6,
};
void
put(uchar *p, u32int v)
{
*p++ = v >> 24;
*p++ = v >> 16;
*p++ = v >> 8;
*p = v;
}
void
usage(void)
{
fprint(2, "usage: %s a.out\n", argv0);
exits("usage");
}
void
block(int n)
{
int rc;
rc = readn(infd, buf, n);
if(rc < 0) sysfatal("read: %r");
if(rc < n) sysfatal("input file truncated");
if(write(outfd, buf, n) < 0) sysfatal("write: %r");
dcrc = blockcrc(tab, dcrc, buf, n);
}
void
copy(int n)
{
int i;
for(i = sizeof(buf) - 1; i < n; i += sizeof(buf))
block(sizeof(buf));
i = n & sizeof(buf) - 1;
if(i > 0)
block(i);
}
void
main(int argc, char **argv)
{
uchar header[64];
char *ofile;
Dir *dir;
ofile = nil;
ARGBEGIN {
case 'o': ofile = strdup(EARGF(usage())); break;
default: usage();
} ARGEND;
if(argc == 0)
infd = 0;
else {
if(argc != 1) usage();
infd = open(argv[0], OREAD);
if(infd < 0) sysfatal("infd: %r");
}
dir = dirfstat(infd);
if(dir == nil) sysfatal("stat: %r");
if(dir->length > 0xFFFFFFFF-8) sysfatal("file too big");
if(ofile == nil) ofile = smprint("%s.u", dir->name);
outfd = create(ofile, OWRITE|OTRUNC, 0666);
if(outfd < 0) sysfatal("create: %r");
tab = mkcrctab(0xEDB88320);
seek(outfd, sizeof(header), 0);
put(buf+0, dir->length);
put(buf+4, 0);
dcrc = blockcrc(tab, 0, buf, 8);
if(write(outfd, buf, 8) != 8) sysfatal("write: %r");
copy(dir->length);
memset(header, 0, sizeof(header));
put(&header[0], 0x27051956); /* magic */
put(&header[8], time(0)); /* time */
put(&header[12], 8+dir->length); /* image size */
put(&header[16], 0); /* load address */
put(&header[20], 0); /* entry point */
put(&header[24], dcrc); /* data crc */
header[28] = 0;
header[29] = 0;
header[30] = IH_TYPE_SCRIPT;
header[31] = 0; /* compressed = no */
strncpy((char*)&header[32], dir->name, sizeof(header)-32);
put(&header[4], blockcrc(tab, 0, header, sizeof(header)));
seek(outfd, 0, 0);
if(write(outfd, header, sizeof(header)) < sizeof(header)) sysfatal("write: %r");
exits(nil);
}
|