1 /* $OpenBSD: extract.c,v 1.4 2014/09/24 00:13:13 doug Exp $ */
2
3 /*
4 * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22 #include <err.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27
28 struct header {
29 char filename[64];
30 int filesize;
31 int fileoffset;
32 };
33
34 int
main(int argc,char * argv[])35 main(int argc, char *argv[])
36 {
37 int i, fdin, fdout, nfiles;
38 void *p;
39 struct header **h;
40
41 if (argc < 2) {
42 printf("%s <firmware file>\n", argv[0]);
43 exit(1);
44 }
45
46 /* open firmware file */
47 if ((fdin = open(argv[1], O_RDONLY)) == -1)
48 err(1, "open of input file failed");
49
50 /* read first header */
51 if (read(fdin, &nfiles, sizeof(nfiles)) < 1)
52 err(1, "first header parse failed");
53 nfiles = ntohl(nfiles);
54
55 /* allocate space for header struct */
56 if ((h = reallocarray(NULL, nfiles, sizeof(*h))) == NULL)
57 err(1, "malloc");
58 for (i = 0; i < nfiles; i++) {
59 if ((h[i] = malloc(sizeof(struct header))) == NULL)
60 err(1, "malloc");
61 }
62
63 /* read header */
64 for (i = 0; i < nfiles; i++) {
65 if (read(fdin, h[i]->filename, sizeof(h[i]->filename)) < 1)
66 err(1, "filename header read failed\n");
67 if (read(fdin, &h[i]->filesize, sizeof(h[i]->filesize)) < 1)
68 err(1, "filesize header read failed\n");
69 h[i]->filesize = htonl(h[i]->filesize);
70 if (read(fdin, &h[i]->fileoffset, sizeof(h[i]->fileoffset)) < 1)
71 err(1, "fileoffset header read failed\n");
72 h[i]->fileoffset = htonl(h[i]->fileoffset);
73 }
74
75 /* write each file */
76 for (i = 0; i < nfiles; i++) {
77 if ((fdout = open(h[i]->filename, O_CREAT|O_TRUNC|O_RDWR, 0644))
78 == -1)
79 err(1, "open of output file failed");
80 if ((p = malloc(h[i]->filesize)) == NULL)
81 err(1, "malloc");
82 if (lseek(fdin, h[i]->fileoffset, SEEK_SET) == -1)
83 err(1, "lseek");
84 if (read(fdin, p, h[i]->filesize) < 1)
85 err(1, "read from input file failed");
86 if (write(fdout, p, h[i]->filesize) < 1)
87 err(1, "write to output file failed");
88 free(p);
89 close(fdout);
90 printf("extracting %s (filesize %d, fileoffset %d)\n",
91 h[i]->filename, h[i]->filesize, h[i]->fileoffset);
92 }
93
94 /* free header space */
95 for (i = 0; i < nfiles; i++)
96 free(h[i]);
97 free(h);
98
99 /* game over */
100 close (fdin);
101
102 return (0);
103 }
104