diff options
-rw-r--r-- | cpio/mkbootfs.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c index f67233634..b7eb8c9f8 100644 --- a/cpio/mkbootfs.c +++ b/cpio/mkbootfs.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <unistd.h> | 4 | #include <unistd.h> |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <ctype.h> | ||
6 | 7 | ||
7 | #include <sys/types.h> | 8 | #include <sys/types.h> |
8 | #include <sys/stat.h> | 9 | #include <sys/stat.h> |
@@ -34,12 +35,47 @@ void die(const char *why, ...) | |||
34 | exit(1); | 35 | exit(1); |
35 | } | 36 | } |
36 | 37 | ||
38 | struct fs_config_entry { | ||
39 | char* name; | ||
40 | int uid, gid, mode; | ||
41 | }; | ||
42 | |||
43 | static struct fs_config_entry* canned_config = NULL; | ||
44 | |||
45 | /* Each line in the canned file should be a path plus three ints (uid, | ||
46 | * gid, mode). */ | ||
47 | #define CANNED_LINE_LENGTH (PATH_MAX+100) | ||
48 | |||
37 | static int verbose = 0; | 49 | static int verbose = 0; |
38 | static int total_size = 0; | 50 | static int total_size = 0; |
39 | 51 | ||
40 | static void fix_stat(const char *path, struct stat *s) | 52 | static void fix_stat(const char *path, struct stat *s) |
41 | { | 53 | { |
42 | fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode); | 54 | if (canned_config) { |
55 | // Use the list of file uid/gid/modes loaded from the file | ||
56 | // given with -f. | ||
57 | |||
58 | struct fs_config_entry* empty_path_config = NULL; | ||
59 | struct fs_config_entry* p; | ||
60 | for (p = canned_config; p->name; ++p) { | ||
61 | if (!p->name[0]) { | ||
62 | empty_path_config = p; | ||
63 | } | ||
64 | if (strcmp(p->name, path) == 0) { | ||
65 | s->st_uid = p->uid; | ||
66 | s->st_gid = p->gid; | ||
67 | s->st_mode = p->mode | (s->st_mode & ~07777); | ||
68 | return; | ||
69 | } | ||
70 | } | ||
71 | s->st_uid = empty_path_config->uid; | ||
72 | s->st_gid = empty_path_config->gid; | ||
73 | s->st_mode = empty_path_config->mode | (s->st_mode & ~07777); | ||
74 | } else { | ||
75 | // Use the compiled-in fs_config() function. | ||
76 | |||
77 | fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode); | ||
78 | } | ||
43 | } | 79 | } |
44 | 80 | ||
45 | static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize) | 81 | static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize) |
@@ -79,7 +115,7 @@ static void _eject(struct stat *s, char *out, int olen, char *data, unsigned dat | |||
79 | 115 | ||
80 | total_size += 6 + 8*13 + olen + 1; | 116 | total_size += 6 + 8*13 + olen + 1; |
81 | 117 | ||
82 | if(strlen(out) != olen) die("ACK!"); | 118 | if(strlen(out) != (unsigned int)olen) die("ACK!"); |
83 | 119 | ||
84 | while(total_size & 3) { | 120 | while(total_size & 3) { |
85 | total_size++; | 121 | total_size++; |
@@ -235,11 +271,61 @@ void archive(const char *start, const char *prefix) | |||
235 | _archive_dir(in, out, strlen(in), strlen(out)); | 271 | _archive_dir(in, out, strlen(in), strlen(out)); |
236 | } | 272 | } |
237 | 273 | ||
274 | static void read_canned_config(char* filename) | ||
275 | { | ||
276 | int allocated = 8; | ||
277 | int used = 0; | ||
278 | |||
279 | canned_config = | ||
280 | (struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry)); | ||
281 | |||
282 | char line[CANNED_LINE_LENGTH]; | ||
283 | FILE* f = fopen(filename, "r"); | ||
284 | if (f == NULL) die("failed to open canned file"); | ||
285 | |||
286 | while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) { | ||
287 | if (!line[0]) break; | ||
288 | if (used >= allocated) { | ||
289 | allocated *= 2; | ||
290 | canned_config = (struct fs_config_entry*)realloc( | ||
291 | canned_config, allocated * sizeof(struct fs_config_entry)); | ||
292 | } | ||
293 | |||
294 | struct fs_config_entry* cc = canned_config + used; | ||
295 | |||
296 | if (isspace(line[0])) { | ||
297 | cc->name = strdup(""); | ||
298 | cc->uid = atoi(strtok(line, " \n")); | ||
299 | } else { | ||
300 | cc->name = strdup(strtok(line, " \n")); | ||
301 | cc->uid = atoi(strtok(NULL, " \n")); | ||
302 | } | ||
303 | cc->gid = atoi(strtok(NULL, " \n")); | ||
304 | cc->mode = strtol(strtok(NULL, " \n"), NULL, 8); | ||
305 | ++used; | ||
306 | } | ||
307 | if (used >= allocated) { | ||
308 | ++allocated; | ||
309 | canned_config = (struct fs_config_entry*)realloc( | ||
310 | canned_config, allocated * sizeof(struct fs_config_entry)); | ||
311 | } | ||
312 | canned_config[used].name = NULL; | ||
313 | |||
314 | fclose(f); | ||
315 | } | ||
316 | |||
317 | |||
238 | int main(int argc, char *argv[]) | 318 | int main(int argc, char *argv[]) |
239 | { | 319 | { |
240 | argc--; | 320 | argc--; |
241 | argv++; | 321 | argv++; |
242 | 322 | ||
323 | if (argc > 1 && strcmp(argv[0], "-f") == 0) { | ||
324 | read_canned_config(argv[1]); | ||
325 | argc -= 2; | ||
326 | argv += 2; | ||
327 | } | ||
328 | |||
243 | if(argc == 0) die("no directories to process?!"); | 329 | if(argc == 0) die("no directories to process?!"); |
244 | 330 | ||
245 | while(argc-- > 0){ | 331 | while(argc-- > 0){ |