diff options
author | The Android Open Source Project | 2009-03-03 21:32:55 -0600 |
---|---|---|
committer | The Android Open Source Project | 2009-03-03 21:32:55 -0600 |
commit | dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0 (patch) | |
tree | 2ba8d1a0846d69b18f623515e8d9b5d9fe38b590 /cpio | |
parent | e54eebbf1a908d65ee8cf80bab62821c05666d70 (diff) | |
download | platform-system-core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.tar.gz platform-system-core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.tar.xz platform-system-core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.zip |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'cpio')
-rw-r--r-- | cpio/Android.mk | 13 | ||||
-rw-r--r-- | cpio/mkbootfs.c | 261 |
2 files changed, 274 insertions, 0 deletions
diff --git a/cpio/Android.mk b/cpio/Android.mk new file mode 100644 index 000000000..8d01852b0 --- /dev/null +++ b/cpio/Android.mk | |||
@@ -0,0 +1,13 @@ | |||
1 | # Copyright 2005 The Android Open Source Project | ||
2 | |||
3 | LOCAL_PATH:= $(call my-dir) | ||
4 | include $(CLEAR_VARS) | ||
5 | |||
6 | LOCAL_SRC_FILES := \ | ||
7 | mkbootfs.c | ||
8 | |||
9 | LOCAL_MODULE := mkbootfs | ||
10 | |||
11 | include $(BUILD_HOST_EXECUTABLE) | ||
12 | |||
13 | $(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) | ||
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c new file mode 100644 index 000000000..f67233634 --- /dev/null +++ b/cpio/mkbootfs.c | |||
@@ -0,0 +1,261 @@ | |||
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 | |||
25 | void 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 | |||
37 | static int verbose = 0; | ||
38 | static int total_size = 0; | ||
39 | |||
40 | static 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 | |||
45 | static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize) | ||
46 | { | ||
47 | // Nothing is special about this value, just picked something in the | ||
48 | // approximate range that was being used already, and avoiding small | ||
49 | // values which may be special. | ||
50 | static unsigned next_inode = 300000; | ||
51 | |||
52 | while(total_size & 3) { | ||
53 | total_size++; | ||
54 | putchar(0); | ||
55 | } | ||
56 | |||
57 | fix_stat(out, s); | ||
58 | // fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode); | ||
59 | |||
60 | printf("%06x%08x%08x%08x%08x%08x%08x" | ||
61 | "%08x%08x%08x%08x%08x%08x%08x%s%c", | ||
62 | 0x070701, | ||
63 | next_inode++, // s.st_ino, | ||
64 | s->st_mode, | ||
65 | 0, // s.st_uid, | ||
66 | 0, // s.st_gid, | ||
67 | 1, // s.st_nlink, | ||
68 | 0, // s.st_mtime, | ||
69 | datasize, | ||
70 | 0, // volmajor | ||
71 | 0, // volminor | ||
72 | 0, // devmajor | ||
73 | 0, // devminor, | ||
74 | olen + 1, | ||
75 | 0, | ||
76 | out, | ||
77 | 0 | ||
78 | ); | ||
79 | |||
80 | total_size += 6 + 8*13 + olen + 1; | ||
81 | |||
82 | if(strlen(out) != olen) die("ACK!"); | ||
83 | |||
84 | while(total_size & 3) { | ||
85 | total_size++; | ||
86 | putchar(0); | ||
87 | } | ||
88 | |||
89 | if(datasize) { | ||
90 | fwrite(data, datasize, 1, stdout); | ||
91 | total_size += datasize; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static void _eject_trailer() | ||
96 | { | ||
97 | struct stat s; | ||
98 | memset(&s, 0, sizeof(s)); | ||
99 | _eject(&s, "TRAILER!!!", 10, 0, 0); | ||
100 | |||
101 | while(total_size & 0xff) { | ||
102 | total_size++; | ||
103 | putchar(0); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static void _archive(char *in, char *out, int ilen, int olen); | ||
108 | |||
109 | static int compare(const void* a, const void* b) { | ||
110 | return strcmp(*(const char**)a, *(const char**)b); | ||
111 | } | ||
112 | |||
113 | static void _archive_dir(char *in, char *out, int ilen, int olen) | ||
114 | { | ||
115 | int i, t; | ||
116 | DIR *d; | ||
117 | struct dirent *de; | ||
118 | |||
119 | if(verbose) { | ||
120 | fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n", | ||
121 | in, out, ilen, olen); | ||
122 | } | ||
123 | |||
124 | d = opendir(in); | ||
125 | if(d == 0) die("cannot open directory '%s'", in); | ||
126 | |||
127 | int size = 32; | ||
128 | int entries = 0; | ||
129 | char** names = malloc(size * sizeof(char*)); | ||
130 | if (names == NULL) { | ||
131 | fprintf(stderr, "failed to allocate dir names array (size %d)\n", size); | ||
132 | exit(1); | ||
133 | } | ||
134 | |||
135 | while((de = readdir(d)) != 0){ | ||
136 | /* xxx: feature? maybe some dotfiles are okay */ | ||
137 | if(de->d_name[0] == '.') continue; | ||
138 | |||
139 | /* xxx: hack. use a real exclude list */ | ||
140 | if(!strcmp(de->d_name, "root")) continue; | ||
141 | |||
142 | if (entries >= size) { | ||
143 | size *= 2; | ||
144 | names = realloc(names, size * sizeof(char*)); | ||
145 | if (names == NULL) { | ||
146 | fprintf(stderr, "failed to reallocate dir names array (size %d)\n", | ||
147 | size); | ||
148 | exit(1); | ||
149 | } | ||
150 | } | ||
151 | names[entries] = strdup(de->d_name); | ||
152 | if (names[entries] == NULL) { | ||
153 | fprintf(stderr, "failed to strdup name \"%s\"\n", | ||
154 | de->d_name); | ||
155 | exit(1); | ||
156 | } | ||
157 | ++entries; | ||
158 | } | ||
159 | |||
160 | qsort(names, entries, sizeof(char*), compare); | ||
161 | |||
162 | for (i = 0; i < entries; ++i) { | ||
163 | t = strlen(names[i]); | ||
164 | in[ilen] = '/'; | ||
165 | memcpy(in + ilen + 1, names[i], t + 1); | ||
166 | |||
167 | if(olen > 0) { | ||
168 | out[olen] = '/'; | ||
169 | memcpy(out + olen + 1, names[i], t + 1); | ||
170 | _archive(in, out, ilen + t + 1, olen + t + 1); | ||
171 | } else { | ||
172 | memcpy(out, names[i], t + 1); | ||
173 | _archive(in, out, ilen + t + 1, t); | ||
174 | } | ||
175 | |||
176 | in[ilen] = 0; | ||
177 | out[olen] = 0; | ||
178 | |||
179 | free(names[i]); | ||
180 | } | ||
181 | free(names); | ||
182 | } | ||
183 | |||
184 | static void _archive(char *in, char *out, int ilen, int olen) | ||
185 | { | ||
186 | struct stat s; | ||
187 | |||
188 | if(verbose) { | ||
189 | fprintf(stderr,"_archive('%s','%s',%d,%d)\n", | ||
190 | in, out, ilen, olen); | ||
191 | } | ||
192 | |||
193 | if(lstat(in, &s)) die("could not stat '%s'\n", in); | ||
194 | |||
195 | if(S_ISREG(s.st_mode)){ | ||
196 | char *tmp; | ||
197 | int fd; | ||
198 | |||
199 | fd = open(in, O_RDONLY); | ||
200 | if(fd < 0) die("cannot open '%s' for read", in); | ||
201 | |||
202 | tmp = (char*) malloc(s.st_size); | ||
203 | if(tmp == 0) die("cannot allocate %d bytes", s.st_size); | ||
204 | |||
205 | if(read(fd, tmp, s.st_size) != s.st_size) { | ||
206 | die("cannot read %d bytes", s.st_size); | ||
207 | } | ||
208 | |||
209 | _eject(&s, out, olen, tmp, s.st_size); | ||
210 | |||
211 | free(tmp); | ||
212 | close(fd); | ||
213 | } else if(S_ISDIR(s.st_mode)) { | ||
214 | _eject(&s, out, olen, 0, 0); | ||
215 | _archive_dir(in, out, ilen, olen); | ||
216 | } else if(S_ISLNK(s.st_mode)) { | ||
217 | char buf[1024]; | ||
218 | int size; | ||
219 | size = readlink(in, buf, 1024); | ||
220 | if(size < 0) die("cannot read symlink '%s'", in); | ||
221 | _eject(&s, out, olen, buf, size); | ||
222 | } else { | ||
223 | die("Unknown '%s' (mode %d)?\n", in, s.st_mode); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | void archive(const char *start, const char *prefix) | ||
228 | { | ||
229 | char in[8192]; | ||
230 | char out[8192]; | ||
231 | |||
232 | strcpy(in, start); | ||
233 | strcpy(out, prefix); | ||
234 | |||
235 | _archive_dir(in, out, strlen(in), strlen(out)); | ||
236 | } | ||
237 | |||
238 | int main(int argc, char *argv[]) | ||
239 | { | ||
240 | argc--; | ||
241 | argv++; | ||
242 | |||
243 | if(argc == 0) die("no directories to process?!"); | ||
244 | |||
245 | while(argc-- > 0){ | ||
246 | char *x = strchr(*argv, '='); | ||
247 | if(x != 0) { | ||
248 | *x++ = 0; | ||
249 | } else { | ||
250 | x = ""; | ||
251 | } | ||
252 | |||
253 | archive(*argv, x); | ||
254 | |||
255 | argv++; | ||
256 | } | ||
257 | |||
258 | _eject_trailer(); | ||
259 | |||
260 | return 0; | ||
261 | } | ||