14 * Original work by Jeff Garzik
16 * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
20 #define str(s) xstr(s)
22 static unsigned int offset
;
23 static unsigned int ino
= 721;
27 int (*handler
)(const char *line
);
30 static void push_string(const char *name
)
32 unsigned int name_len
= strlen(name
) + 1;
39 static void push_pad (void)
47 static void push_rest(const char *name
)
49 unsigned int name_len
= strlen(name
) + 1;
56 tmp_ofs
= name_len
+ 110;
64 static void push_hdr(const char *s
)
70 static void cpio_trailer(void)
73 const char name
[] = "TRAILER!!!";
75 sprintf(s
, "%s%08X%08X%08lX%08lX%08X%08lX"
76 "%08X%08X%08X%08X%08X%08X%08X",
89 (unsigned)strlen(name
)+1, /* namesize */
94 while (offset
% 512) {
100 static int cpio_mkslink(const char *name
, const char *target
,
101 unsigned int mode
, uid_t uid
, gid_t gid
)
104 time_t mtime
= time(NULL
);
106 sprintf(s
,"%s%08X%08X%08lX%08lX%08X%08lX"
107 "%08X%08X%08X%08X%08X%08X%08X",
108 "070701", /* magic */
110 S_IFLNK
| mode
, /* mode */
111 (long) uid
, /* uid */
112 (long) gid
, /* gid */
114 (long) mtime
, /* mtime */
115 (unsigned)strlen(target
)+1, /* filesize */
120 (unsigned)strlen(name
) + 1,/* namesize */
130 static int cpio_mkslink_line(const char *line
)
132 char name
[PATH_MAX
+ 1];
133 char target
[PATH_MAX
+ 1];
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
);
143 rc
= cpio_mkslink(name
, target
, mode
, uid
, gid
);
148 static int cpio_mkgeneric(const char *name
, unsigned int mode
,
149 uid_t uid
, gid_t gid
)
152 time_t mtime
= time(NULL
);
154 sprintf(s
,"%s%08X%08X%08lX%08lX%08X%08lX"
155 "%08X%08X%08X%08X%08X%08X%08X",
156 "070701", /* magic */
159 (long) uid
, /* uid */
160 (long) gid
, /* gid */
162 (long) mtime
, /* mtime */
168 (unsigned)strlen(name
) + 1,/* namesize */
181 struct generic_type
{
186 static struct generic_type generic_type_table
[] = {
201 static int cpio_mkgeneric_line(const char *line
, enum generic_types gt
)
203 char name
[PATH_MAX
+ 1];
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
);
214 mode
|= generic_type_table
[gt
].mode
;
215 rc
= cpio_mkgeneric(name
, mode
, uid
, gid
);
220 static int cpio_mkdir_line(const char *line
)
222 return cpio_mkgeneric_line(line
, GT_DIR
);
225 static int cpio_mkpipe_line(const char *line
)
227 return cpio_mkgeneric_line(line
, GT_PIPE
);
230 static int cpio_mksock_line(const char *line
)
232 return cpio_mkgeneric_line(line
, GT_SOCK
);
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
)
240 time_t mtime
= time(NULL
);
247 sprintf(s
,"%s%08X%08X%08lX%08lX%08X%08lX"
248 "%08X%08X%08X%08X%08X%08X%08X",
249 "070701", /* magic */
252 (long) uid
, /* uid */
253 (long) gid
, /* gid */
255 (long) mtime
, /* mtime */
261 (unsigned)strlen(name
) + 1,/* namesize */
268 static int cpio_mknod_line(const char *line
)
270 char name
[PATH_MAX
+ 1];
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
);
284 rc
= cpio_mknod(name
, mode
, uid
, gid
, dev_type
, maj
, min
);
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
)
294 char *filebuf
= NULL
;
302 retval
= stat (location
, &buf
);
304 fprintf (stderr
, "File %s could not be located\n", location
);
308 file
= open (location
, O_RDONLY
);
310 fprintf (stderr
, "File %s could not be opened for reading\n", location
);
314 filebuf
= malloc(buf
.st_size
);
316 fprintf (stderr
, "out of memory\n");
320 retval
= read (file
, filebuf
, buf
.st_size
);
322 fprintf (stderr
, "Can not read %s file\n", location
);
326 sprintf(s
,"%s%08X%08X%08lX%08lX%08X%08lX"
327 "%08X%08X%08X%08X%08X%08X%08X",
328 "070701", /* magic */
331 (long) uid
, /* uid */
332 (long) gid
, /* gid */
334 (long) buf
.st_mtime
, /* mtime */
335 (int) buf
.st_size
, /* filesize */
340 (unsigned)strlen(name
) + 1,/* namesize */
346 fwrite(filebuf
, buf
.st_size
, 1, stdout
);
347 offset
+= buf
.st_size
;
352 if (filebuf
) free(filebuf
);
353 if (file
>= 0) close(file
);
357 static int cpio_mkfile_line(const char *line
)
359 char name
[PATH_MAX
+ 1];
360 char location
[PATH_MAX
+ 1];
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
);
370 rc
= cpio_mkfile(name
, location
, mode
, uid
, gid
);
375 void usage(const char *prog
)
377 fprintf(stderr
, "Usage:\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"
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"
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"
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",
411 struct file_handler file_handler_table
[] = {
414 .handler
= cpio_mkfile_line
,
417 .handler
= cpio_mknod_line
,
420 .handler
= cpio_mkdir_line
,
423 .handler
= cpio_mkslink_line
,
426 .handler
= cpio_mkpipe_line
,
429 .handler
= cpio_mksock_line
,
436 #define LINE_SIZE (2 * PATH_MAX + 50)
438 int main (int argc
, char *argv
[])
441 char line
[LINE_SIZE
];
451 if (! (cpio_list
= fopen(argv
[1], "r"))) {
452 fprintf(stderr
, "ERROR: unable to open '%s': %s\n\n",
453 argv
[1], strerror(errno
));
458 while (fgets(line
, LINE_SIZE
, cpio_list
)) {
460 size_t slen
= strlen(line
);
465 /* comment - skip to next line */
469 if (! (type
= strtok(line
, " \t"))) {
471 "ERROR: incorrect format, could not locate file type line %d: '%s'\n",
481 if (slen
== strlen(type
)) {
482 /* must be an empty line */
486 if (! (args
= strtok(NULL
, "\n"))) {
488 "ERROR: incorrect format, newline required line %d: '%s'\n",
493 for (type_idx
= 0; file_handler_table
[type_idx
].type
; type_idx
++) {
495 if (! strcmp(line
, file_handler_table
[type_idx
].type
)) {
496 if ((rc
= file_handler_table
[type_idx
].handler(args
))) {
498 fprintf(stderr
, " line %d\n", line_nr
);
504 if (NULL
== file_handler_table
[type_idx
].type
) {
505 fprintf(stderr
, "unknown file type line %d: '%s'\n",