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
main(int argc,char * argv[])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