1 /* $OpenBSD: build.c,v 1.4 2014/07/20 02:03:21 guenther 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 <errno.h> 24 #include <fcntl.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 //#define VERBOSE 1 31 #define FILENAME "bwi-airforce" 32 33 struct header { 34 char filename[64]; 35 int filesize; 36 int fileoffset; 37 }; 38 39 int 40 main(int argc, char *argv[]) 41 { 42 void *p; 43 int i, j, offset; 44 int fdout, fdin; 45 int nfiles, headersize; 46 int fwsize, totalsize; 47 struct header h[argc - 1]; 48 struct stat s; 49 50 if (argc < 2) { 51 printf("%s <firmware files>\n", argv[0]); 52 exit(1); 53 } 54 55 nfiles = argc - 1; /* number of firmware files */ 56 headersize = sizeof(h) + sizeof(nfiles); /* size of file header */ 57 58 /* initialize header struct */ 59 for (i = 1, j = 0, fwsize = 0; i < argc; i++, j++) { 60 bzero(h[j].filename, sizeof(h[j].filename)); 61 strlcpy(h[j].filename, argv[i], sizeof(h[j].filename)); 62 63 if (stat(h[j].filename, &s) == -1) 64 err(1, "header initialization failed"); 65 66 h[j].filesize = s.st_size; 67 h[j].fileoffset = 0; 68 69 fwsize += h[j].filesize; 70 #ifdef VERBOSE 71 printf("create header entry for %s (%d bytes)\n", 72 h[j].filename, h[j].filesize); 73 #endif 74 } 75 76 /* calculate total file size */ 77 totalsize = headersize + fwsize; 78 #if VERBOSE 79 printf("\n"); 80 printf("header size = %d bytes, ", headersize); 81 printf("fw size = %d bytes, ", fwsize); 82 printf("total file size = %d bytes\n", totalsize); 83 printf("\n"); 84 #endif 85 86 /* calculating firmware offsets */ 87 for (i = 0, offset = headersize; i < nfiles; i++) { 88 h[i].fileoffset = offset; 89 offset += h[i].filesize; 90 #ifdef VERBOSE 91 printf("offset of %s = %d\n", h[i].filename, h[i].fileoffset); 92 #endif 93 } 94 95 /* open output file */ 96 if ((fdout = open(FILENAME, O_CREAT|O_TRUNC|O_RDWR, 0644)) == -1) 97 err(1, "open output file failed"); 98 99 /* host to network byte order */ 100 for (i = 0; i < nfiles; i++) { 101 h[i].filesize = htonl(h[i].filesize); 102 h[i].fileoffset = htonl(h[i].fileoffset); 103 } 104 nfiles = htonl(nfiles); 105 106 /* write header */ 107 if (write(fdout, &nfiles, sizeof(nfiles)) < 1) { 108 int saved_errno = errno; 109 close(fdout); 110 errc(1, saved_errno, "write header 1 to output file failed"); 111 } 112 if (write(fdout, h, headersize - sizeof(nfiles)) < 1) { 113 int saved_errno = errno; 114 close(fdout); 115 errc(1, saved_errno, "write header 2 to output file failed"); 116 } 117 118 /* network to host byte order */ 119 nfiles = ntohl(nfiles); 120 for (i = 0; i < nfiles; i++) { 121 h[i].filesize = ntohl(h[i].filesize); 122 h[i].fileoffset = ntohl(h[i].fileoffset); 123 } 124 125 /* write each file */ 126 for (i = 0; i < nfiles; i++) { 127 if ((fdin = open(h[i].filename, O_RDONLY)) == -1) { 128 int saved_errno = errno; 129 close(fdout); 130 errc(1, saved_errno, "open input file failed"); 131 } 132 if ((p = malloc(h[i].filesize)) == NULL) { 133 int saved_errno = errno; 134 close(fdout); 135 close(fdin); 136 errc(1, saved_errno, "malloc"); 137 } 138 if (read(fdin, p, h[i].filesize) < 1) { 139 int saved_errno = errno; 140 free(p); 141 close(fdout); 142 close(fdin); 143 errc(1, saved_errno, "read input file failed"); 144 } 145 if (write(fdout, p, h[i].filesize) < 1) { 146 int saved_errno = errno; 147 free(p); 148 close(fdout); 149 close(fdin); 150 errc(1, saved_errno, "write to output file failed"); 151 } 152 free(p); 153 close(fdin); 154 } 155 156 close(fdout); 157 158 #ifdef VERBOSE 159 printf("\n"); 160 #endif 161 162 /* game over */ 163 printf("wrote %d files to %s (%d bytes).\n", 164 nfiles, FILENAME, totalsize); 165 166 return (0); 167 } 168