summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'cpio/mkbootfs.c')
-rw-r--r--cpio/mkbootfs.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
new file mode 100644
index 000000000..9fe625278
--- /dev/null
+++ b/cpio/mkbootfs.c
@@ -0,0 +1,220 @@
1
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <string.h>
6
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <dirent.h>
10
11#include <stdarg.h>
12#include <fcntl.h>
13
14#include <private/android_filesystem_config.h>
15
16/* NOTES
17**
18** - see buffer-format.txt from the linux kernel docs for
19** an explanation of this file format
20** - dotfiles are ignored
21** - directories named 'root' are ignored
22** - device notes, pipes, etc are not supported (error)
23*/
24
25void die(const char *why, ...)
26{
27 va_list ap;
28
29 va_start(ap, why);
30 fprintf(stderr,"error: ");
31 vfprintf(stderr, why, ap);
32 fprintf(stderr,"\n");
33 va_end(ap);
34 exit(1);
35}
36
37static int verbose = 0;
38static int total_size = 0;
39
40static void fix_stat(const char *path, struct stat *s)
41{
42 fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode);
43}
44
45static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
46{
47 while(total_size & 3) {
48 total_size++;
49 putchar(0);
50 }
51
52 fix_stat(out, s);
53// fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode);
54
55 printf("%06x%08x%08x%08x%08x%08x%08x"
56 "%08x%08x%08x%08x%08x%08x%08x%s%c",
57 0x070701,
58 (unsigned) s->st_ino,
59 s->st_mode,
60 0, // s.st_uid,
61 0, // s.st_gid,
62 1, // s.st_nlink,
63 (unsigned) s->st_mtime,
64 datasize,
65 0, // volmajor
66 0, // volminor
67 0, // devmajor
68 0, // devminor,
69 olen + 1,
70 0,
71 out,
72 0
73 );
74
75 total_size += 6 + 8*13 + olen + 1;
76
77 if(strlen(out) != olen) die("ACK!");
78
79 while(total_size & 3) {
80 total_size++;
81 putchar(0);
82 }
83
84 if(datasize) {
85 fwrite(data, datasize, 1, stdout);
86 total_size += datasize;
87 }
88}
89
90static void _eject_trailer()
91{
92 struct stat s;
93 memset(&s, 0, sizeof(s));
94 _eject(&s, "TRAILER!!!", 10, 0, 0);
95
96 while(total_size & 0xff) {
97 total_size++;
98 putchar(0);
99 }
100}
101
102static void _archive(char *in, char *out, int ilen, int olen);
103
104static void _archive_dir(char *in, char *out, int ilen, int olen)
105{
106 int t;
107 DIR *d;
108 struct dirent *de;
109
110 if(verbose) {
111 fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
112 in, out, ilen, olen);
113 }
114
115 d = opendir(in);
116 if(d == 0) die("cannot open directory '%s'", in);
117
118 while((de = readdir(d)) != 0){
119 /* xxx: feature? maybe some dotfiles are okay */
120 if(de->d_name[0] == '.') continue;
121
122 /* xxx: hack. use a real exclude list */
123 if(!strcmp(de->d_name, "root")) continue;
124
125 t = strlen(de->d_name);
126 in[ilen] = '/';
127 memcpy(in + ilen + 1, de->d_name, t + 1);
128
129 if(olen > 0) {
130 out[olen] = '/';
131 memcpy(out + olen + 1, de->d_name, t + 1);
132 _archive(in, out, ilen + t + 1, olen + t + 1);
133 } else {
134 memcpy(out, de->d_name, t + 1);
135 _archive(in, out, ilen + t + 1, t);
136 }
137
138 in[ilen] = 0;
139 out[olen] = 0;
140 }
141}
142
143static void _archive(char *in, char *out, int ilen, int olen)
144{
145 struct stat s;
146
147 if(verbose) {
148 fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
149 in, out, ilen, olen);
150 }
151
152 if(lstat(in, &s)) die("could not stat '%s'\n", in);
153
154 if(S_ISREG(s.st_mode)){
155 char *tmp;
156 int fd;
157
158 fd = open(in, O_RDONLY);
159 if(fd < 0) die("cannot open '%s' for read", in);
160
161 tmp = (char*) malloc(s.st_size);
162 if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
163
164 if(read(fd, tmp, s.st_size) != s.st_size) {
165 die("cannot read %d bytes", s.st_size);
166 }
167
168 _eject(&s, out, olen, tmp, s.st_size);
169
170 free(tmp);
171 close(fd);
172 } else if(S_ISDIR(s.st_mode)) {
173 _eject(&s, out, olen, 0, 0);
174 _archive_dir(in, out, ilen, olen);
175 } else if(S_ISLNK(s.st_mode)) {
176 char buf[1024];
177 int size;
178 size = readlink(in, buf, 1024);
179 if(size < 0) die("cannot read symlink '%s'", in);
180 _eject(&s, out, olen, buf, size);
181 } else {
182 die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
183 }
184}
185
186void archive(const char *start, const char *prefix)
187{
188 char in[8192];
189 char out[8192];
190
191 strcpy(in, start);
192 strcpy(out, prefix);
193
194 _archive_dir(in, out, strlen(in), strlen(out));
195}
196
197int main(int argc, char *argv[])
198{
199 argc--;
200 argv++;
201
202 if(argc == 0) die("no directories to process?!");
203
204 while(argc-- > 0){
205 char *x = strchr(*argv, '=');
206 if(x != 0) {
207 *x++ = 0;
208 } else {
209 x = "";
210 }
211
212 archive(*argv, x);
213
214 argv++;
215 }
216
217 _eject_trailer();
218
219 return 0;
220}