FreeBSD/Linux Kernel Cross Reference
sys/boot/addaout.c
1 /* A small utility to append an a.out header to an arbitrary file. This allows
2 * inclusion of arbitrary data in the boot image, so that it is magically
3 * loaded as a RAM disk. The a.out header is structured as follows:
4 *
5 * a_flags: A_IMG to indicate this is not an executable
6 *
7 * Created: April 2005, Jorrit N. Herder
8 */
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <a.out.h>
13 #include <sys/types.h>
14 #include <fcntl.h>
15 #include <sys/stat.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #define INPUT_FILE 1
20 #define OUTPUT_FILE 2
21
22 /* Report problems. */
23 void report(char *problem, char *message)
24 {
25 fprintf(stderr, "%s:\n", problem);
26 fprintf(stderr, " %s\n\n", message);
27 }
28
29
30 int copy_data(int srcfd, int dstfd)
31 {
32 char buf[8192];
33 ssize_t n;
34 int total=0;
35
36 /* Copy the little bytes themselves. (Source from cp.c). */
37 while ((n= read(srcfd, buf, sizeof(buf))) > 0) {
38 char *bp = buf;
39 ssize_t r;
40
41 while (n > 0 && (r= write(dstfd, bp, n)) > 0) {
42 bp += r;
43 n -= r;
44 total += r;
45 }
46 if (r <= 0) {
47 if (r == 0) {
48 fprintf(stderr, "Warning: EOF writing to output file.\n");
49 return(-1);
50 }
51 }
52 }
53 return(total);
54 }
55
56
57 /* Main program. */
58 int main(int argc, char **argv)
59 {
60 struct exec aout;
61 struct stat stin;
62 int fdin, fdout;
63 char * bp;
64 int n,r;
65 int total_size=0;
66 int result;
67
68 /* Check if command line arguments are present, or print usage. */
69 if (argc!=3) {
70 printf("Invalid arguments. Usage:\n");
71 printf(" %s <input_file> <output_file>\n",argv[0]);
72 return(1);
73 }
74
75 /* Check if we can open the input and output file. */
76 if (stat(argv[INPUT_FILE], &stin) != 0) {
77 report("Couldn't get status of input file", strerror(errno));
78 return(1);
79 }
80 if ((fdin = open(argv[INPUT_FILE], O_RDONLY)) < 0) {
81 report("Couldn't open input file", strerror(errno));
82 return(1);
83 }
84 if ((fdout = open(argv[OUTPUT_FILE], O_WRONLY|O_CREAT|O_TRUNC,
85 stin.st_mode & 0777)) < 0) {
86 report("Couldn't open output file", strerror(errno));
87 return(1);
88 }
89
90
91 /* Copy input file to output file, but leave space for a.out header. */
92 lseek(fdout, sizeof(aout), SEEK_SET);
93 total_size = copy_data(fdin, fdout);
94 if (total_size < 0) {
95 report("Aborted", "Output file may be truncated.");
96 return(1);
97 } else if (total_size == 0) {
98 report("Aborted without prepending header", "No data in input file.");
99 return(1);
100 }
101
102
103 /* Build a.out header and write to output file. */
104 memset(&aout, 0, sizeof(struct exec));
105 aout.a_magic[0] = A_MAGIC0;
106 aout.a_magic[1] = A_MAGIC1;
107 aout.a_flags |= A_IMG;
108 aout.a_hdrlen = sizeof(aout);
109 aout.a_text = 0;
110 aout.a_data = total_size;
111 aout.a_bss = 0;
112 aout.a_total = aout.a_hdrlen + aout.a_data;
113
114 bp = (char *) &aout;
115 n = sizeof(aout);
116 lseek(fdout, 0, SEEK_SET);
117 while (n > 0 && (r= write(fdout, bp, n)) > 0) {
118 bp += r;
119 n -= r;
120 }
121
122 printf("Prepended data file (%u bytes) with a.out header (%u bytes).\n",
123 total_size, sizeof(aout));
124 printf("Done.\n");
125
126 return(0);
127 }
128
Cache object: c4d2676f47f96ca64b0f67a9488c1f08
|