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 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