OSDN Git Service

Hi,
[uclinux-h8/elf2flt.git] / flthdr.c
1 /****************************************************************************/
2 /*
3  *      A simple program to manipulate flat files
4  *
5  *      Copyright (C) 2001-2003 SnapGear Inc, davidm@snapgear.com
6  *      Copyright (C) 2001 Lineo, davidm@lineo.com
7  *
8  * This is Free Software, under the GNU Public Licence v2 or greater.
9  *
10  */
11 /****************************************************************************/
12
13 #include <stdio.h>    /* Userland pieces of the ANSI C standard I/O package  */
14 #include <unistd.h>   /* Userland prototypes of the Unix std system calls    */
15 #include <time.h>
16 #include <stdlib.h>   /* exit() */
17 #include <string.h>   /* strcat(), strcpy() */
18
19 /* macros for conversion between host and (internet) network byte order */
20 #ifndef WIN32
21 #include <netinet/in.h> /* Consts and structs defined by the internet system */
22 #else
23 #include <winsock2.h>
24 #endif
25
26 /* from uClinux-x.x.x/include/linux */
27 #include "flat.h"     /* Binary flat header description                      */
28
29 #if defined(__MINGW32__)
30 #include <getopt.h>
31
32 #define mkstemp(p) mktemp(p)
33
34 #endif
35
36 /****************************************************************************/
37
38 char *program_name;
39
40 static char cmd[1024];
41 static int print = 0, compress = 0, ramload = 0, stacksize = 0, ktrace = 0;
42 static int short_format = 0;
43
44 /****************************************************************************/
45
46 void
47 transferr(FILE *ifp, FILE *ofp, int count)
48 {
49         int n, num;
50
51         while (count == -1 || count > 0) {
52                 if (count == -1 || count > sizeof(cmd))
53                         num = sizeof(cmd);
54                 else
55                         num = count;
56                 n = fread(cmd, 1, num, ifp);
57                 if (n == 0)
58                         break;
59                 if (fwrite(cmd, n, 1, ofp) != 1) {
60                         fprintf(stderr, "Write failed :-(\n");
61                         exit(1);
62                 }
63                 if (count != -1)
64                         count -= n;
65         }
66         if (count > 0) {
67                 fprintf(stderr, "Failed to transferr %d bytes\n", count);
68                 exit(1);
69         }
70 }
71         
72 /****************************************************************************/
73
74 void
75 process_file(char *ifile, char *ofile)
76 {
77         int old_flags, old_stack, new_flags, new_stack;
78         FILE *ifp, *ofp;
79         int ofp_is_pipe = 0;
80         struct flat_hdr old_hdr, new_hdr;
81         char tfile[256];
82         char tfile2[256];
83
84         *tfile = *tfile2 = '\0';
85
86         if ((ifp = fopen(ifile, "rb")) == NULL) {
87                 fprintf(stderr, "Cannot open %s\n", ifile);
88                 return;
89         }
90
91         if (fread(&old_hdr, sizeof(old_hdr), 1, ifp) != 1) {
92                 fprintf(stderr, "Cannot read header of %s\n", ifile);
93                 return;
94         }
95
96         if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
97                 fprintf(stderr, "Cannot read header of %s\n", ifile);
98                 return;
99         }
100
101         new_flags = old_flags = ntohl(old_hdr.flags);
102         new_stack = old_stack = ntohl(old_hdr.stack_size);
103         new_hdr = old_hdr;
104
105         if (compress == 1) {
106                 new_flags |= FLAT_FLAG_GZIP;
107                 new_flags &= ~FLAT_FLAG_GZDATA;
108         } else if (compress == 2) {
109                 new_flags |= FLAT_FLAG_GZDATA;
110                 new_flags &= ~FLAT_FLAG_GZIP;
111         } else if (compress < 0)
112                 new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
113         
114         if (ramload > 0)
115                 new_flags |= FLAT_FLAG_RAM;
116         else if (ramload < 0)
117                 new_flags &= ~FLAT_FLAG_RAM;
118         
119         if (ktrace > 0)
120                 new_flags |= FLAT_FLAG_KTRACE;
121         else if (ktrace < 0)
122                 new_flags &= ~FLAT_FLAG_KTRACE;
123         
124         if (stacksize)
125                 new_stack = stacksize;
126
127         if (print == 1) {
128                 time_t t;
129
130                 printf("%s\n", ifile);
131                 printf("    Magic:        %4.4s\n", old_hdr.magic);
132                 printf("    Rev:          %d\n",    ntohl(old_hdr.rev));
133                 t = (time_t) htonl(old_hdr.build_date);
134                 printf("    Build Date:   %s",      t?ctime(&t):"not specified\n");
135                 printf("    Entry:        0x%x\n",  ntohl(old_hdr.entry));
136                 printf("    Data Start:   0x%x\n",  ntohl(old_hdr.data_start));
137                 printf("    Data End:     0x%x\n",  ntohl(old_hdr.data_end));
138                 printf("    BSS End:      0x%x\n",  ntohl(old_hdr.bss_end));
139                 printf("    Stack Size:   0x%x\n",  ntohl(old_hdr.stack_size));
140                 printf("    Reloc Start:  0x%x\n",  ntohl(old_hdr.reloc_start));
141                 printf("    Reloc Count:  0x%x\n",  ntohl(old_hdr.reloc_count));
142                 printf("    Flags:        0x%x ( ",  ntohl(old_hdr.flags));
143                 if (old_flags) {
144                         if (old_flags & FLAT_FLAG_RAM)
145                                 printf("Load-to-Ram ");
146                         if (old_flags & FLAT_FLAG_GOTPIC)
147                                 printf("Has-PIC-GOT ");
148                         if (old_flags & FLAT_FLAG_GZIP)
149                                 printf("Gzip-Compressed ");
150                         if (old_flags & FLAT_FLAG_GZDATA)
151                                 printf("Gzip-Data-Compressed ");
152                         if (old_flags & FLAT_FLAG_KTRACE)
153                                 printf("Kernel-Traced-Load ");
154                         printf(")\n");
155                 }
156         } else if (print > 1) {
157                 static int first = 1;
158                 unsigned int text, data, bss, stk, rel, tot;
159
160                 if (first) {
161                         printf("Flag Rev   Text   Data    BSS  Stack Relocs    RAM Filename\n");
162                         printf("-----------------------------------------------------------\n");
163                         first = 0;
164                 }
165                 *tfile = '\0';
166                 strcat(tfile, (old_flags & FLAT_FLAG_KTRACE) ? "k" : "");
167                 strcat(tfile, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
168                 strcat(tfile, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
169                 strcat(tfile, (old_flags & FLAT_FLAG_GZIP) ? "z" :
170                                         ((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
171                 printf("-%-3.3s ", tfile);
172                 printf("%3d ", ntohl(old_hdr.rev));
173                 printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
174                 printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
175                 printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
176                 printf("%6d ", stk=ntohl(old_hdr.stack_size));
177                 printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
178                 /*
179                  * work out how much RAM is needed per invocation, this
180                  * calculation is dependent on the binfmt_flat implementation
181                  */
182                 tot = data; /* always need data */
183
184                 if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
185                         tot += text + sizeof(struct flat_hdr);
186                 
187                 if (bss + stk > rel) /* which is bigger ? */
188                         tot += bss + stk;
189                 else
190                         tot += rel;
191
192                 printf("%6d ", tot);
193                 /*
194                  * the total depends on whether the relocs are smaller/bigger than
195                  * the BSS
196                  */
197                 printf("%s\n", ifile);
198         }
199
200         /* if there is nothing else to do, leave */
201         if (new_flags == old_flags && new_stack == old_stack)
202                 return;
203         
204         new_hdr.flags = htonl(new_flags);
205         new_hdr.stack_size = htonl(new_stack);
206
207         strcpy(tfile, "/tmp/flatXXXXXX");
208         mkstemp(tfile);
209         if ((ofp = fopen(tfile, "wb")) == NULL) {
210                 fprintf(stderr, "Failed to open %s for writing\n", tfile);
211                 unlink(tfile);
212                 unlink(tfile2);
213                 exit(1);
214         }
215
216         if (fwrite(&new_hdr, sizeof(new_hdr), 1, ofp) != 1) {
217                 fprintf(stderr, "Failed to write to  %s\n", tfile);
218                 unlink(tfile);
219                 unlink(tfile2);
220                 exit(1);
221         }
222
223         /*
224          * get ourselves a fully uncompressed copy of the text/data/relocs
225          * so that we can manipulate it more easily
226          */
227         if (old_flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
228                 FILE *tfp;
229
230                 strcpy(tfile2, "/tmp/flat2XXXXXX");
231                 mkstemp(tfile2);
232                 
233                 if (old_flags & FLAT_FLAG_GZDATA) {
234                         tfp = fopen(tfile2, "wb");
235                         if (!tfp) {
236                                 fprintf(stderr, "Failed to open %s for writing\n", tfile2);
237                                 exit(1);
238                         }
239                         transferr(ifp, tfp, ntohl(old_hdr.data_start) -
240                                         sizeof(struct flat_hdr));
241                         fclose(tfp);
242                 }
243
244                 sprintf(cmd, "gunzip >> %s", tfile2);
245                 tfp = popen(cmd, "wb");
246                 if(!tfp) {
247                         perror("popen");
248                         exit(1);
249                 }
250                 transferr(ifp, tfp, -1);
251                 pclose(tfp);
252
253                 fclose(ifp);
254                 ifp = fopen(tfile2, "rb");
255                 if (!ifp) {
256                         fprintf(stderr, "Failed to open %s for reading\n", tfile2);
257                         unlink(tfile);
258                         unlink(tfile2);
259                         exit(1);
260                 }
261         }
262
263         if (new_flags & FLAT_FLAG_GZIP) {
264                 printf("zflat %s --> %s\n", ifile, ofile);
265                 fclose(ofp);
266                 sprintf(cmd, "gzip -9 -f >> %s", tfile);
267                 ofp = popen(cmd, "wb");
268                 ofp_is_pipe = 1;
269         } else if (new_flags & FLAT_FLAG_GZDATA) {
270                 printf("zflat-data %s --> %s\n", ifile, ofile);
271                 transferr(ifp, ofp, ntohl(new_hdr.data_start) -
272                                 sizeof(struct flat_hdr));
273                 fclose(ofp);
274                 sprintf(cmd, "gzip -9 -f >> %s", tfile);
275                 ofp = popen(cmd, "wb");
276                 ofp_is_pipe = 1;
277         }
278
279         if (!ofp) { /* can only happen if using gzip/gunzip */
280                 fprintf(stderr, "Can't run cmd %s\n", cmd);
281                 unlink(tfile);
282                 unlink(tfile2);
283                 exit(1);
284         }
285
286         transferr(ifp, ofp, -1);
287         
288         if (ferror(ifp) || ferror(ofp)) {
289                 fprintf(stderr, "Error on file pointer%s%s\n",
290                                 ferror(ifp) ? " input" : "", ferror(ofp) ? " output" : "");
291                 unlink(tfile);
292                 unlink(tfile2);
293                 exit(1);
294         }
295
296         fclose(ifp);
297         if (ofp_is_pipe)
298                 pclose(ofp);
299         else
300                 fclose(ofp);
301
302         /* cheat a little here to preserve file permissions */
303         sprintf(cmd, "cp %s %s", tfile, ofile);
304         system(cmd);
305         unlink(tfile);
306         unlink(tfile2);
307 }
308
309 /****************************************************************************/
310
311 void
312 usage(char *s)
313 {
314         if (s)
315                 fprintf(stderr, "%s\n", s);
316         fprintf(stderr, "usage: %s [options] flat-file\n", program_name);
317         fprintf(stderr, "       Allows you to change an existing flat file\n\n");
318         fprintf(stderr, "       -p      : print current settings\n");
319         fprintf(stderr, "       -z      : compressed flat file\n");
320         fprintf(stderr, "       -d      : compressed data-only flat file\n");
321         fprintf(stderr, "       -Z      : un-compressed flat file\n");
322         fprintf(stderr, "       -r      : ram load\n");
323         fprintf(stderr, "       -R      : do not RAM load\n");
324         fprintf(stderr, "       -k      : kernel traced load (for debug)\n");
325         fprintf(stderr, "       -K      : normal non-kernel traced load\n");
326         fprintf(stderr, "       -s size : stack size\n");
327         fprintf(stderr, "       -o file : output-file\n"
328                         "                 (default is to modify input file)\n");
329         exit(1);
330 }
331
332 /****************************************************************************/
333
334 int
335 main(int argc, char *argv[])
336 {
337         int c;
338         char *ofile = NULL, *ifile;
339
340         program_name = argv[0];
341
342         while ((c = getopt(argc, argv, "pdzZrRkKs:o:")) != EOF) {
343                 switch (c) {
344                 case 'p': print = 1;                break;
345                 case 'z': compress = 1;             break;
346                 case 'd': compress = 2;             break;
347                 case 'Z': compress = -1;            break;
348                 case 'r': ramload = 1;              break;
349                 case 'R': ramload = -1;             break;
350                 case 'k': ktrace = 1;               break;
351                 case 'K': ktrace = -1;              break;
352                 case 's': stacksize = atoi(optarg); break;
353                 case 'o': ofile = optarg;           break;
354                 default:
355                         usage("invalid option");
356                         break;
357                 }
358         }
359
360         if (optind >= argc)
361                 usage("No input files provided");
362
363         if (ofile && argc - optind > 1)
364                 usage("-o can only be used with a single file");
365         
366         if (!print && !compress && !ramload && !stacksize) /* no args == print */
367                 print = argc - optind; /* greater than 1 is short format */
368         
369         for (c = optind; c < argc; c++) {
370                 ifile = argv[c];
371                 if (!ofile)
372                         ofile = ifile;
373                 process_file(ifile, ofile);
374                 ofile = NULL;
375         }
376         
377         exit(0);
378 }
379
380 /****************************************************************************/