Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/usr/gen_init_cpio.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 10587 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 10587 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <sys/types.h> |
4 | #include <sys/stat.h> |
5 | #include <string.h> |
6 | #include <unistd.h> |
7 | #include <time.h> |
8 | #include <fcntl.h> |
9 | #include <errno.h> |
10 | #include <ctype.h> |
11 | #include <limits.h> |
12 | |
13 | /* |
14 | * Original work by Jeff Garzik |
15 | * |
16 | * External file lists, symlink, pipe and fifo support by Thayne Harbaugh |
17 | */ |
18 | |
19 | #define xstr(s) #s |
20 | #define str(s) xstr(s) |
21 | |
22 | static unsigned int offset; |
23 | static unsigned int ino = 721; |
24 | |
25 | struct file_handler { |
26 | const char *type; |
27 | int (*handler)(const char *line); |
28 | }; |
29 | |
30 | static void push_string(const char *name) |
31 | { |
32 | unsigned int name_len = strlen(name) + 1; |
33 | |
34 | fputs(name, stdout); |
35 | putchar(0); |
36 | offset += name_len; |
37 | } |
38 | |
39 | static void push_pad (void) |
40 | { |
41 | while (offset & 3) { |
42 | putchar(0); |
43 | offset++; |
44 | } |
45 | } |
46 | |
47 | static void push_rest(const char *name) |
48 | { |
49 | unsigned int name_len = strlen(name) + 1; |
50 | unsigned int tmp_ofs; |
51 | |
52 | fputs(name, stdout); |
53 | putchar(0); |
54 | offset += name_len; |
55 | |
56 | tmp_ofs = name_len + 110; |
57 | while (tmp_ofs & 3) { |
58 | putchar(0); |
59 | offset++; |
60 | tmp_ofs++; |
61 | } |
62 | } |
63 | |
64 | static void push_hdr(const char *s) |
65 | { |
66 | fputs(s, stdout); |
67 | offset += 110; |
68 | } |
69 | |
70 | static void cpio_trailer(void) |
71 | { |
72 | char s[256]; |
73 | const char name[] = "TRAILER!!!"; |
74 | |
75 | sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX" |
76 | "%08X%08X%08X%08X%08X%08X%08X", |
77 | "070701", /* magic */ |
78 | 0, /* ino */ |
79 | 0, /* mode */ |
80 | (long) 0, /* uid */ |
81 | (long) 0, /* gid */ |
82 | 1, /* nlink */ |
83 | (long) 0, /* mtime */ |
84 | 0, /* filesize */ |
85 | 0, /* major */ |
86 | 0, /* minor */ |
87 | 0, /* rmajor */ |
88 | 0, /* rminor */ |
89 | (unsigned)strlen(name)+1, /* namesize */ |
90 | 0); /* chksum */ |
91 | push_hdr(s); |
92 | push_rest(name); |
93 | |
94 | while (offset % 512) { |
95 | putchar(0); |
96 | offset++; |
97 | } |
98 | } |
99 | |
100 | static int cpio_mkslink(const char *name, const char *target, |
101 | unsigned int mode, uid_t uid, gid_t gid) |
102 | { |
103 | char s[256]; |
104 | time_t mtime = time(NULL); |
105 | |
106 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" |
107 | "%08X%08X%08X%08X%08X%08X%08X", |
108 | "070701", /* magic */ |
109 | ino++, /* ino */ |
110 | S_IFLNK | mode, /* mode */ |
111 | (long) uid, /* uid */ |
112 | (long) gid, /* gid */ |
113 | 1, /* nlink */ |
114 | (long) mtime, /* mtime */ |
115 | (unsigned)strlen(target)+1, /* filesize */ |
116 | 3, /* major */ |
117 | 1, /* minor */ |
118 | 0, /* rmajor */ |
119 | 0, /* rminor */ |
120 | (unsigned)strlen(name) + 1,/* namesize */ |
121 | 0); /* chksum */ |
122 | push_hdr(s); |
123 | push_string(name); |
124 | push_pad(); |
125 | push_string(target); |
126 | push_pad(); |
127 | return 0; |
128 | } |
129 | |
130 | static int cpio_mkslink_line(const char *line) |
131 | { |
132 | char name[PATH_MAX + 1]; |
133 | char target[PATH_MAX + 1]; |
134 | unsigned int mode; |
135 | int uid; |
136 | int gid; |
137 | int rc = -1; |
138 | |
139 | if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) { |
140 | fprintf(stderr, "Unrecognized dir format '%s'", line); |
141 | goto fail; |
142 | } |
143 | rc = cpio_mkslink(name, target, mode, uid, gid); |
144 | fail: |
145 | return rc; |
146 | } |
147 | |
148 | static int cpio_mkgeneric(const char *name, unsigned int mode, |
149 | uid_t uid, gid_t gid) |
150 | { |
151 | char s[256]; |
152 | time_t mtime = time(NULL); |
153 | |
154 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" |
155 | "%08X%08X%08X%08X%08X%08X%08X", |
156 | "070701", /* magic */ |
157 | ino++, /* ino */ |
158 | mode, /* mode */ |
159 | (long) uid, /* uid */ |
160 | (long) gid, /* gid */ |
161 | 2, /* nlink */ |
162 | (long) mtime, /* mtime */ |
163 | 0, /* filesize */ |
164 | 3, /* major */ |
165 | 1, /* minor */ |
166 | 0, /* rmajor */ |
167 | 0, /* rminor */ |
168 | (unsigned)strlen(name) + 1,/* namesize */ |
169 | 0); /* chksum */ |
170 | push_hdr(s); |
171 | push_rest(name); |
172 | return 0; |
173 | } |
174 | |
175 | enum generic_types { |
176 | GT_DIR, |
177 | GT_PIPE, |
178 | GT_SOCK |
179 | }; |
180 | |
181 | struct generic_type { |
182 | const char *type; |
183 | mode_t mode; |
184 | }; |
185 | |
186 | static struct generic_type generic_type_table[] = { |
187 | [GT_DIR] = { |
188 | .type = "dir", |
189 | .mode = S_IFDIR |
190 | }, |
191 | [GT_PIPE] = { |
192 | .type = "pipe", |
193 | .mode = S_IFIFO |
194 | }, |
195 | [GT_SOCK] = { |
196 | .type = "sock", |
197 | .mode = S_IFSOCK |
198 | } |
199 | }; |
200 | |
201 | static int cpio_mkgeneric_line(const char *line, enum generic_types gt) |
202 | { |
203 | char name[PATH_MAX + 1]; |
204 | unsigned int mode; |
205 | int uid; |
206 | int gid; |
207 | int rc = -1; |
208 | |
209 | if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) { |
210 | fprintf(stderr, "Unrecognized %s format '%s'", |
211 | line, generic_type_table[gt].type); |
212 | goto fail; |
213 | } |
214 | mode |= generic_type_table[gt].mode; |
215 | rc = cpio_mkgeneric(name, mode, uid, gid); |
216 | fail: |
217 | return rc; |
218 | } |
219 | |
220 | static int cpio_mkdir_line(const char *line) |
221 | { |
222 | return cpio_mkgeneric_line(line, GT_DIR); |
223 | } |
224 | |
225 | static int cpio_mkpipe_line(const char *line) |
226 | { |
227 | return cpio_mkgeneric_line(line, GT_PIPE); |
228 | } |
229 | |
230 | static int cpio_mksock_line(const char *line) |
231 | { |
232 | return cpio_mkgeneric_line(line, GT_SOCK); |
233 | } |
234 | |
235 | static int cpio_mknod(const char *name, unsigned int mode, |
236 | uid_t uid, gid_t gid, char dev_type, |
237 | unsigned int maj, unsigned int min) |
238 | { |
239 | char s[256]; |
240 | time_t mtime = time(NULL); |
241 | |
242 | if (dev_type == 'b') |
243 | mode |= S_IFBLK; |
244 | else |
245 | mode |= S_IFCHR; |
246 | |
247 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" |
248 | "%08X%08X%08X%08X%08X%08X%08X", |
249 | "070701", /* magic */ |
250 | ino++, /* ino */ |
251 | mode, /* mode */ |
252 | (long) uid, /* uid */ |
253 | (long) gid, /* gid */ |
254 | 1, /* nlink */ |
255 | (long) mtime, /* mtime */ |
256 | 0, /* filesize */ |
257 | 3, /* major */ |
258 | 1, /* minor */ |
259 | maj, /* rmajor */ |
260 | min, /* rminor */ |
261 | (unsigned)strlen(name) + 1,/* namesize */ |
262 | 0); /* chksum */ |
263 | push_hdr(s); |
264 | push_rest(name); |
265 | return 0; |
266 | } |
267 | |
268 | static int cpio_mknod_line(const char *line) |
269 | { |
270 | char name[PATH_MAX + 1]; |
271 | unsigned int mode; |
272 | int uid; |
273 | int gid; |
274 | char dev_type; |
275 | unsigned int maj; |
276 | unsigned int min; |
277 | int rc = -1; |
278 | |
279 | if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u", |
280 | name, &mode, &uid, &gid, &dev_type, &maj, &min)) { |
281 | fprintf(stderr, "Unrecognized nod format '%s'", line); |
282 | goto fail; |
283 | } |
284 | rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min); |
285 | fail: |
286 | return rc; |
287 | } |
288 | |
289 | /* Not marked static to keep the compiler quiet, as no one uses this yet... */ |
290 | static int cpio_mkfile(const char *name, const char *location, |
291 | unsigned int mode, uid_t uid, gid_t gid) |
292 | { |
293 | char s[256]; |
294 | char *filebuf = NULL; |
295 | struct stat buf; |
296 | int file = -1; |
297 | int retval; |
298 | int rc = -1; |
299 | |
300 | mode |= S_IFREG; |
301 | |
302 | retval = stat (location, &buf); |
303 | if (retval) { |
304 | fprintf (stderr, "File %s could not be located\n", location); |
305 | goto error; |
306 | } |
307 | |
308 | file = open (location, O_RDONLY); |
309 | if (file < 0) { |
310 | fprintf (stderr, "File %s could not be opened for reading\n", location); |
311 | goto error; |
312 | } |
313 | |
314 | filebuf = malloc(buf.st_size); |
315 | if (!filebuf) { |
316 | fprintf (stderr, "out of memory\n"); |
317 | goto error; |
318 | } |
319 | |
320 | retval = read (file, filebuf, buf.st_size); |
321 | if (retval < 0) { |
322 | fprintf (stderr, "Can not read %s file\n", location); |
323 | goto error; |
324 | } |
325 | |
326 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" |
327 | "%08X%08X%08X%08X%08X%08X%08X", |
328 | "070701", /* magic */ |
329 | ino++, /* ino */ |
330 | mode, /* mode */ |
331 | (long) uid, /* uid */ |
332 | (long) gid, /* gid */ |
333 | 1, /* nlink */ |
334 | (long) buf.st_mtime, /* mtime */ |
335 | (int) buf.st_size, /* filesize */ |
336 | 3, /* major */ |
337 | 1, /* minor */ |
338 | 0, /* rmajor */ |
339 | 0, /* rminor */ |
340 | (unsigned)strlen(name) + 1,/* namesize */ |
341 | 0); /* chksum */ |
342 | push_hdr(s); |
343 | push_string(name); |
344 | push_pad(); |
345 | |
346 | fwrite(filebuf, buf.st_size, 1, stdout); |
347 | offset += buf.st_size; |
348 | push_pad(); |
349 | rc = 0; |
350 | |
351 | error: |
352 | if (filebuf) free(filebuf); |
353 | if (file >= 0) close(file); |
354 | return rc; |
355 | } |
356 | |
357 | static int cpio_mkfile_line(const char *line) |
358 | { |
359 | char name[PATH_MAX + 1]; |
360 | char location[PATH_MAX + 1]; |
361 | unsigned int mode; |
362 | int uid; |
363 | int gid; |
364 | int rc = -1; |
365 | |
366 | if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, location, &mode, &uid, &gid)) { |
367 | fprintf(stderr, "Unrecognized file format '%s'", line); |
368 | goto fail; |
369 | } |
370 | rc = cpio_mkfile(name, location, mode, uid, gid); |
371 | fail: |
372 | return rc; |
373 | } |
374 | |
375 | void usage(const char *prog) |
376 | { |
377 | fprintf(stderr, "Usage:\n" |
378 | "\t%s <cpio_list>\n" |
379 | "\n" |
380 | "<cpio_list> is a file containing newline separated entries that\n" |
381 | "describe the files to be included in the initramfs archive:\n" |
382 | "\n" |
383 | "# a comment\n" |
384 | "file <name> <location> <mode> <uid> <gid>\n" |
385 | "dir <name> <mode> <uid> <gid>\n" |
386 | "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n" |
387 | "slink <name> <target> <mode> <uid> <gid>\n" |
388 | "pipe <name> <mode> <uid> <gid>\n" |
389 | "sock <name> <mode> <uid> <gid>\n" |
390 | "\n" |
391 | "<name> name of the file/dir/nod/etc in the archive\n" |
392 | "<location> location of the file in the current filesystem\n" |
393 | "<target> link target\n" |
394 | "<mode> mode/permissions of the file\n" |
395 | "<uid> user id (0=root)\n" |
396 | "<gid> group id (0=root)\n" |
397 | "<dev_type> device type (b=block, c=character)\n" |
398 | "<maj> major number of nod\n" |
399 | "<min> minor number of nod\n" |
400 | "\n" |
401 | "example:\n" |
402 | "# A simple initramfs\n" |
403 | "dir /dev 0755 0 0\n" |
404 | "nod /dev/console 0600 0 0 c 5 1\n" |
405 | "dir /root 0700 0 0\n" |
406 | "dir /sbin 0755 0 0\n" |
407 | "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n", |
408 | prog); |
409 | } |
410 | |
411 | struct file_handler file_handler_table[] = { |
412 | { |
413 | .type = "file", |
414 | .handler = cpio_mkfile_line, |
415 | }, { |
416 | .type = "nod", |
417 | .handler = cpio_mknod_line, |
418 | }, { |
419 | .type = "dir", |
420 | .handler = cpio_mkdir_line, |
421 | }, { |
422 | .type = "slink", |
423 | .handler = cpio_mkslink_line, |
424 | }, { |
425 | .type = "pipe", |
426 | .handler = cpio_mkpipe_line, |
427 | }, { |
428 | .type = "sock", |
429 | .handler = cpio_mksock_line, |
430 | }, { |
431 | .type = NULL, |
432 | .handler = NULL, |
433 | } |
434 | }; |
435 | |
436 | #define LINE_SIZE (2 * PATH_MAX + 50) |
437 | |
438 | int main (int argc, char *argv[]) |
439 | { |
440 | FILE *cpio_list; |
441 | char line[LINE_SIZE]; |
442 | char *args, *type; |
443 | int ec = 0; |
444 | int line_nr = 0; |
445 | |
446 | if (2 != argc) { |
447 | usage(argv[0]); |
448 | exit(1); |
449 | } |
450 | |
451 | if (! (cpio_list = fopen(argv[1], "r"))) { |
452 | fprintf(stderr, "ERROR: unable to open '%s': %s\n\n", |
453 | argv[1], strerror(errno)); |
454 | usage(argv[0]); |
455 | exit(1); |
456 | } |
457 | |
458 | while (fgets(line, LINE_SIZE, cpio_list)) { |
459 | int type_idx; |
460 | size_t slen = strlen(line); |
461 | |
462 | line_nr++; |
463 | |
464 | if ('#' == *line) { |
465 | /* comment - skip to next line */ |
466 | continue; |
467 | } |
468 | |
469 | if (! (type = strtok(line, " \t"))) { |
470 | fprintf(stderr, |
471 | "ERROR: incorrect format, could not locate file type line %d: '%s'\n", |
472 | line_nr, line); |
473 | ec = -1; |
474 | } |
475 | |
476 | if ('\n' == *type) { |
477 | /* a blank line */ |
478 | continue; |
479 | } |
480 | |
481 | if (slen == strlen(type)) { |
482 | /* must be an empty line */ |
483 | continue; |
484 | } |
485 | |
486 | if (! (args = strtok(NULL, "\n"))) { |
487 | fprintf(stderr, |
488 | "ERROR: incorrect format, newline required line %d: '%s'\n", |
489 | line_nr, line); |
490 | ec = -1; |
491 | } |
492 | |
493 | for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) { |
494 | int rc; |
495 | if (! strcmp(line, file_handler_table[type_idx].type)) { |
496 | if ((rc = file_handler_table[type_idx].handler(args))) { |
497 | ec = rc; |
498 | fprintf(stderr, " line %d\n", line_nr); |
499 | } |
500 | break; |
501 | } |
502 | } |
503 | |
504 | if (NULL == file_handler_table[type_idx].type) { |
505 | fprintf(stderr, "unknown file type line %d: '%s'\n", |
506 | line_nr, line); |
507 | } |
508 | } |
509 | cpio_trailer(); |
510 | |
511 | exit(ec); |
512 | } |