Merge branch 'vendor/LIBPCAP' and updated build for new version.
[dragonfly.git] / usr.bin / kzip / kzip.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * Copyright (C) 1993  Hannu Savolainen
10  * Ported to 386bsd by Serge Vakulenko
11  * based on tools/build.c by Linus Torvalds
12  *
13  * $FreeBSD: src/usr.bin/kzip/kzip.c,v 1.13.2.2 2000/07/20 10:35:20 kris Exp $
14  * $DragonFly: src/usr.bin/kzip/kzip.c,v 1.3 2003/10/04 20:36:47 hmp Exp $
15  */
16
17 #include <err.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <sys/file.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/param.h>
25 #include <sys/wait.h>
26 #include <a.out.h>
27 #include <string.h>
28
29 #define MAXIMAGE        (2*1024*1024)
30         /* This is the limit because a kzip'ed kernel loads at 3Mb and
31          * ends up at 1Mb
32          */
33 static void
34 usage(void)
35 {
36         fprintf(stderr, "usage: kzip [-v] [ -l loadaddr] kernel\n");
37         exit(1);
38 }
39
40 int
41 main(int argc, char **argv)
42 {
43         pid_t Pext, Pgzip, Ppiggy, Pld;
44         int pipe1[2], pipe2[2];
45         int status, fdi, fdo, fdn, c, verbose;
46         int size;
47         struct exec hdr;
48         int zip_size, offset;
49         struct stat st;
50         u_long forceaddr = 0, entry;
51         char *kernname;
52         char obj[MAXPATHLEN + 1];
53         char out[MAXPATHLEN + 1];
54         char base[32];
55         
56         while ((c = getopt(argc, argv, "l:v")) != -1) {
57                 switch (c) {
58                 case 'l':
59                         forceaddr = strtoul(optarg, NULL, 0);
60                         if (forceaddr == 0)
61                                 errx(1, "invalid load address");
62                         break;
63                 case 'v':
64                         verbose++;
65                         break;
66                 default:
67                         usage();
68                 }
69         }
70
71         if ((argc - optind) != 1)
72                 usage();
73
74         argc -= optind;
75         argv += optind;
76
77         kernname = argv[0];
78                         
79         if (strlen(kernname) > MAXPATHLEN - 3)
80                 errx(1, "%s: File name too long", kernname);
81         strcpy(obj, kernname); strcat(obj,".o");
82         strcpy(out, kernname); strcat(out,".kz");
83
84         fdi = open(kernname ,O_RDONLY);
85         if(fdi<0) {
86                 warn("%s", kernname);
87                 return 2;
88         }
89
90         /* figure out how big the uncompressed image will be */
91         if (read (fdi, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
92                 err(2, "%s", argv[1]);
93
94         size = hdr.a_text + hdr.a_data + hdr.a_bss;
95         entry = hdr.a_entry & 0x00FFFFFF;
96
97         lseek (fdi, 0, SEEK_SET);
98
99         if (verbose) {
100                 printf("real kernel start address will be: 0x%x\n", entry);
101                 printf("real kernel end   address will be: 0x%x\n", entry+size);
102         }
103
104
105         fdo = open(obj,O_WRONLY|O_TRUNC|O_CREAT,0666);
106         if(fdo<0) {
107                 warn("%s", obj);
108                 return 2;
109         }
110
111         if (pipe(pipe1) < 0) { perror("pipe()"); return 1; }
112
113         if (pipe(pipe2) < 0) { perror("pipe()"); return 1; }
114
115         Pext = fork();
116         if (Pext < 0) { perror("fork()"); return 1; }
117         if (!Pext) {
118                 dup2(fdi,0);
119                 dup2(pipe1[1],1);
120                 close(pipe1[0]); close(pipe1[1]);
121                 close(pipe2[0]); close(pipe2[1]);
122                 close(fdi); close(fdo);
123                 extract(kernname);
124                 exit(0);
125         }
126
127         Pgzip = fork();
128         if (Pgzip < 0) { perror("fork()"); return 1; }
129         if (!Pgzip) {
130                 dup2(pipe1[0],0);
131                 dup2(pipe2[1],1);
132                 close(pipe1[0]); close(pipe1[1]);
133                 close(pipe2[0]); close(pipe2[1]);
134                 close(fdi); close(fdo);
135                 execlp("gzip", "gzip", "-9", "-n", NULL);
136                 exit (0);
137         }
138
139         Ppiggy = fork();
140         if (Ppiggy < 0) { warn("fork()"); return 1; }
141         if (!Ppiggy) {
142                 dup2(pipe2[0],0);
143                 dup2(fdo,1);
144                 close(pipe1[0]); close(pipe1[1]);
145                 close(pipe2[0]); close(pipe2[1]);
146                 close(fdi); close(fdo);
147                 piggyback(obj);
148                 exit(0);
149         }
150
151         close(pipe1[0]); close(pipe1[1]);
152         close(pipe2[0]); close(pipe2[1]);
153         close(fdi); close(fdo);
154
155         if (waitpid(Pext, &status,0) < 0)
156                 { warn("waitpid(Pextract)"); return 1; }
157
158         if(status) {
159                 warnx("extract returned %x",status);
160                 return 3;
161         }
162
163         if (waitpid(Pgzip, &status,0) < 0)
164                 { perror("waitpid(Pgzip)"); return 1; }
165
166         if(status) {
167                 warnx("gzip returned %x",status);
168                 return 3;
169         }
170
171         if (waitpid(Ppiggy, &status,0) < 0)
172                 { warn("waitpid(Ppiggy)"); return 1; }
173
174         if(status) {
175                 warnx("piggyback returned %x",status);
176                 return 3;
177         }
178
179         if (forceaddr)
180                 offset = forceaddr;
181         else {
182                 /* a kludge to dynamically figure out where to start it */
183                 if (stat (obj, &st) < 0) {
184                         warn("cannot get size of compressed data");
185                         return 3;
186                 }
187                 zip_size = (int)st.st_size;
188                 offset = entry + size - zip_size + 0x8000; /* fudge factor */
189         }
190         sprintf(base, "0x%x", roundup(offset, 4096));
191
192         Pld = fork();
193         if (Pld < 0) { warn("fork()"); return 1; }
194         if (!Pld) {
195                 execlp("ld",
196                         "ld",
197                         "-aout",
198                         "-Bstatic",
199                         "-Z",
200                         "-T",
201                         base,
202                         "-o",
203                         out,
204                         "/usr/lib/aout/kzhead.o",
205                         obj,
206                         "/usr/lib/aout/kztail.o",
207                         NULL);
208                 exit(2);
209         }
210
211         if (waitpid(Pld, &status,0) < 0)
212                 { warn("waitpid(Pld)"); return 1; }
213
214         if(status) {
215                 warnx("ld returned %x",status);
216                 return 3;
217         }
218
219         if (verbose) {
220
221                 fdn = open(obj ,O_RDONLY);
222                 if(fdn<0) {
223                         warn("%s", obj);
224                         return 3;
225                 }
226
227                 /* figure out how big the compressed image is */
228                 if (read (fdn, (char *)&hdr, sizeof(hdr)) != sizeof(hdr)) {
229                         warn("%s", obj);
230                         return 3;
231                 }
232                 close(fdn);
233
234                 size = hdr.a_text + hdr.a_data + hdr.a_bss;
235
236                 printf("kzip data   start address will be: 0x%x\n",offset);
237                 printf("kzip data   end   address will be: 0x%x\n",offset+size);
238         }
239
240         unlink(obj);
241         exit(0);
242 }
243
244 int
245 extract (char *file)
246 {
247         int sz;
248         char buf[BUFSIZ];
249         struct exec hdr;
250
251         if (read (0, (char *)&hdr, sizeof(hdr)) != sizeof(hdr))
252                 err(2, "%s", file);
253         if (hdr.a_magic != ZMAGIC)
254                 errx(2, "bad magic in file %s, probably not a kernel", file);
255         if (lseek (0, N_TXTOFF(hdr), 0) < 0)
256                 err(2, "%s", file);
257
258         sz = N_SYMOFF (hdr) - N_TXTOFF (hdr);
259
260         while (sz) {
261                 int l, n;
262
263                 l = sz;
264                 if (l > sizeof(buf))
265                         l = sizeof(buf);
266
267                 n = read (0, buf, l);
268                 if (n != l) {
269                         if (n == -1)
270                                 err(1, "%s", file);
271                         else
272                                 errx(1, "unexpected EOF");
273                 }
274
275                 write (1, buf, l);
276                 sz -= l;
277         }
278         exit(0);
279 }
280
281
282 char string_names[] = {"_input_data\0_input_len\0"};
283
284 struct nlist var_names[2] = {                           /* Symbol table */
285         { { (char*)  4 }, N_EXT|N_TEXT, 0, 0, 0 },      /* _input_data  */
286         { { (char*) 16 }, N_EXT|N_TEXT, 0, 0, 0 },      /* _input_len */
287 };
288
289 int
290 piggyback(char *file)
291 {
292         int n, len;
293         struct exec hdr;                        /* object header */
294         char image[MAXIMAGE];                   /* kernel image buffer */
295
296         len = 0;
297         while ((n = read (0, &image[len], sizeof(image)-len+1)) > 0)
298               len += n;
299
300         if (n < 0)
301                 err(1, "stdin");
302
303         if (len >= sizeof(image))
304                 errx(1, "input too large");
305
306         /*
307          *      Output object header
308          */
309         memset(&hdr,0,sizeof hdr);
310         hdr.a_magic = OMAGIC;
311         hdr.a_text = len + sizeof(long);
312         hdr.a_syms = sizeof(var_names);
313         write (1, (char *)&hdr, sizeof(hdr));
314
315         /*
316          *      Output text segment (compressed system & len)
317          */
318         write (1, image, len);
319         write (1, (char *)&len, sizeof(len));
320
321         /*
322          *      Output symbol table
323          */
324         var_names[1].n_value = len;
325         write (1, (char *)&var_names, sizeof(var_names));
326
327         /*
328          *      Output string table
329          */
330         len = sizeof(string_names) + sizeof(len);
331         write (1, (char *)&len, sizeof(len));
332         write (1, string_names, sizeof(string_names));
333
334         return (0);
335 }