1 /****************************************************************************/
3 * A simple program to manipulate flat files
5 * Copyright (C) 2001,2002 SnapGear Inc, davidm@snapgear.com
6 * Copyright (C) 2001 Lineo, davidm@lineo.com
8 /****************************************************************************/
10 #include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
11 #include <unistd.h> /* Userland prototypes of the Unix std system calls */
14 /* macros for conversion between host and (internet) network byte order */
15 #include <netinet/in.h> /* Consts and structs defined by the internet system */
17 /* from uClinux-x.x.x/include/linux */
18 #include "flat.h" /* Binary flat header description */
20 /****************************************************************************/
24 static char cmd[1024];
25 static int print = 0, compress = 0, ramload = 0, stacksize = 0;
26 static int short_format = 0;
28 /****************************************************************************/
31 transferr(FILE *ifp, FILE *ofp, int count)
35 while (count == -1 || count > 0) {
36 if (count == -1 || count > sizeof(cmd))
40 n = fread(cmd, 1, num, ifp);
43 if (fwrite(cmd, n, 1, ofp) != 1) {
44 fprintf(stderr, "Write failed :-(\n");
51 fprintf(stderr, "Failed to transferr %d bytes\n", count);
56 /****************************************************************************/
59 process_file(char *ifile, char *ofile)
61 int old_flags, old_stack, new_flags, new_stack;
63 struct flat_hdr old_hdr, new_hdr;
67 *tfile = *tfile2 = '\0';
69 if ((ifp = fopen(ifile, "r")) == NULL) {
70 fprintf(stderr, "Cannot open %s\n", ifile);
74 if (fread(&old_hdr, sizeof(old_hdr), 1, ifp) != 1) {
75 fprintf(stderr, "Cannot read header of %s\n", ifile);
79 if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
80 fprintf(stderr, "Cannot read header of %s\n", ifile);
84 new_flags = old_flags = ntohl(old_hdr.flags);
85 new_stack = old_stack = ntohl(old_hdr.stack_size);
89 new_flags |= FLAT_FLAG_GZIP;
90 new_flags &= ~FLAT_FLAG_GZDATA;
91 } else if (compress == 2) {
92 new_flags |= FLAT_FLAG_GZDATA;
93 new_flags &= ~FLAT_FLAG_GZIP;
94 } else if (compress < 0)
95 new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
98 new_flags |= FLAT_FLAG_RAM;
100 new_flags &= ~FLAT_FLAG_RAM;
103 new_stack = stacksize;
108 printf("%s\n", ifile);
109 printf(" Magic: %4.4s\n", old_hdr.magic);
110 printf(" Rev: %d\n", ntohl(old_hdr.rev));
111 t = (time_t) htonl(old_hdr.build_date);
112 printf(" Build Date: %s", t?ctime(&t):"not specified\n");
113 printf(" Entry: 0x%x\n", ntohl(old_hdr.entry));
114 printf(" Data Start: 0x%x\n", ntohl(old_hdr.data_start));
115 printf(" Data End: 0x%x\n", ntohl(old_hdr.data_end));
116 printf(" BSS End: 0x%x\n", ntohl(old_hdr.bss_end));
117 printf(" Stack Size: 0x%x\n", ntohl(old_hdr.stack_size));
118 printf(" Reloc Start: 0x%x\n", ntohl(old_hdr.reloc_start));
119 printf(" Reloc Count: 0x%x\n", ntohl(old_hdr.reloc_count));
120 printf(" Flags: 0x%x ( ", ntohl(old_hdr.flags));
122 if (old_flags & FLAT_FLAG_RAM)
123 printf("Load-to-Ram ");
124 if (old_flags & FLAT_FLAG_GOTPIC)
125 printf("Has-PIC-GOT ");
126 if (old_flags & FLAT_FLAG_GZIP)
127 printf("Gzip-Compressed ");
128 if (old_flags & FLAT_FLAG_GZDATA)
129 printf("Gzip-Data-Compressed ");
132 } else if (print > 1) {
133 static int first = 1;
134 unsigned int text, data, bss, stk, rel, tot;
137 printf("Flag Rev Text Data BSS Stack Relocs RAM Filename\n");
138 printf("-----------------------------------------------------------\n");
142 strcat(tfile, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
143 strcat(tfile, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
144 strcat(tfile, (old_flags & FLAT_FLAG_GZIP) ? "z" :
145 ((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
146 printf("-%-3.3s ", tfile);
147 printf("%3d ", ntohl(old_hdr.rev));
148 printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
149 printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
150 printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
151 printf("%6d ", stk=ntohl(old_hdr.stack_size));
152 printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
154 * work out how much RAM is needed per invocation, this
155 * calculation is dependent on the binfmt_flat implementation
157 tot = data; /* always need data */
159 if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
160 tot += text + sizeof(struct flat_hdr);
162 if (bss + stk > rel) /* which is bigger ? */
169 * the total depends on whether the relocs are smaller/bigger than
172 printf("%s\n", ifile);
175 /* if there is nothing else to do, leave */
176 if (new_flags == old_flags && new_stack == old_stack)
179 new_hdr.flags = htonl(new_flags);
180 new_hdr.stack_size = htonl(new_stack);
182 strcpy(tfile, "/tmp/flatXXXXXX");
184 if ((ofp = fopen(tfile, "w")) == NULL) {
185 fprintf(stderr, "Failed to open %s for writing\n", tfile);
191 if (fwrite(&new_hdr, sizeof(new_hdr), 1, ofp) != 1) {
192 fprintf(stderr, "Failed to write to %s\n", tfile);
199 * get ourselves a fully uncompressed copy of the text/data/relocs
200 * so that we can manipulate it more easily
202 if (old_flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
205 strcpy(tfile2, "/tmp/flat2XXXXXX");
208 if (old_flags & FLAT_FLAG_GZDATA) {
209 tfp = fopen(tfile2, "w");
211 fprintf(stderr, "Failed to open %s for writing\n", tfile2);
214 transferr(ifp, tfp, ntohl(old_hdr.data_start) -
215 sizeof(struct flat_hdr));
219 sprintf(cmd, "gunzip >> %s", tfile2);
220 tfp = popen(cmd, "w");
221 transferr(ifp, tfp, -1);
225 ifp = fopen(tfile2, "r");
227 fprintf(stderr, "Failed to open %s for reading\n", tfile2);
234 if (new_flags & FLAT_FLAG_GZIP) {
235 printf("zflat %s --> %s\n", ifile, ofile);
237 sprintf(cmd, "gzip -9 -f >> %s", tfile);
238 ofp = popen(cmd, "w");
239 } else if (new_flags & FLAT_FLAG_GZDATA) {
240 printf("zflat-data %s --> %s\n", ifile, ofile);
241 transferr(ifp, ofp, ntohl(new_hdr.data_start) -
242 sizeof(struct flat_hdr));
244 sprintf(cmd, "gzip -9 -f >> %s", tfile);
245 ofp = popen(cmd, "w");
248 if (!ofp) { /* can only happen if using gzip/gunzip */
249 fprintf(stderr, "Can't run cmd %s\n", cmd);
255 transferr(ifp, ofp, -1);
257 if (ferror(ifp) || ferror(ofp)) {
258 fprintf(stderr, "Error on file pointer%s%s\n",
259 ferror(ifp) ? " input" : "", ferror(ofp) ? " output" : "");
268 /* cheat a little here to preserve file permissions */
269 sprintf(cmd, "cp %s %s", tfile, ofile);
275 /****************************************************************************/
281 fprintf(stderr, "%s\n", s);
282 fprintf(stderr, "usage: %s [options] flat-file\n", program_name);
283 fprintf(stderr, " Allows you to change an existing flat file\n\n");
284 fprintf(stderr, " -p : print current settings\n");
285 fprintf(stderr, " -z : compressed flat file\n");
286 fprintf(stderr, " -d : compressed data-only flat file\n");
287 fprintf(stderr, " -Z : un-compressed flat file\n");
288 fprintf(stderr, " -r : ram load\n");
289 fprintf(stderr, " -R : do not RAM load\n");
290 fprintf(stderr, " -s size : stack size\n");
291 fprintf(stderr, " -o file : output-file\n"
292 " (default is to modify input file)\n");
296 /****************************************************************************/
299 main(int argc, char *argv[])
302 char *ofile = NULL, *ifile;
304 program_name = argv[0];
306 while ((c = getopt(argc, argv, "pdzZrRs:o:")) != EOF) {
308 case 'p': print = 1; break;
309 case 'z': compress = 1; break;
310 case 'd': compress = 2; break;
311 case 'Z': compress = -1; break;
312 case 'r': ramload = 1; break;
313 case 'R': ramload = -1; break;
314 case 's': stacksize = atoi(optarg); break;
315 case 'o': ofile = optarg; break;
317 usage("invalid option");
323 usage("No input files provided");
325 if (ofile && argc - optind > 1)
326 usage("-o can only be used with a single file");
328 if (!print && !compress && !ramload && !stacksize) /* no args == print */
329 print = argc - optind; /* greater than 1 is short format */
331 for (c = optind; c < argc; c++) {
335 process_file(ifile, ofile);
342 /****************************************************************************/