diff options
author | Luciano Rocha <strange@nsk.no-ip.org> | 2007-02-10 04:44:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:25 -0500 |
commit | 24fa50961451b7b21081e4d16836952b17eb5fb3 (patch) | |
tree | d40f2474ffd9046f0978bc5132a9ff4ef3140c00 | |
parent | 67d38229dfa64cf9a75f83746dde345f47bbd8dc (diff) |
[PATCH] usr/gen_init_cpio.c: support for hard links
Extend usr/gen_init_cpio.c "file" entry, adding support for hard links.
Previous format:
file <name> <location> <mode> <uid> <gid>
New format:
file <name> <location> <mode> <uid> <gid> [<hard links>]
The hard links specification is optional, keeping the previous
behaviour.
All hard links are defined sequentially in the resulting cpio and the
file data is present only in the last link. This is the behaviour of
GNU's cpio and is supported by the kernel initramfs extractor.
Signed-off-by: Luciano Rocha <strange@nsk.no-ip.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | usr/gen_init_cpio.c | 122 |
1 files changed, 86 insertions, 36 deletions
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index 83acd6cc0b3c..8365db6cfe06 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * Original work by Jeff Garzik | 14 | * Original work by Jeff Garzik |
15 | * | 15 | * |
16 | * External file lists, symlink, pipe and fifo support by Thayne Harbaugh | 16 | * External file lists, symlink, pipe and fifo support by Thayne Harbaugh |
17 | * Hard link support by Luciano Rocha | ||
17 | */ | 18 | */ |
18 | 19 | ||
19 | #define xstr(s) #s | 20 | #define xstr(s) #s |
@@ -286,16 +287,19 @@ static int cpio_mknod_line(const char *line) | |||
286 | return rc; | 287 | return rc; |
287 | } | 288 | } |
288 | 289 | ||
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, | 290 | static int cpio_mkfile(const char *name, const char *location, |
291 | unsigned int mode, uid_t uid, gid_t gid) | 291 | unsigned int mode, uid_t uid, gid_t gid, |
292 | unsigned int nlinks) | ||
292 | { | 293 | { |
293 | char s[256]; | 294 | char s[256]; |
294 | char *filebuf = NULL; | 295 | char *filebuf = NULL; |
295 | struct stat buf; | 296 | struct stat buf; |
297 | long size; | ||
296 | int file = -1; | 298 | int file = -1; |
297 | int retval; | 299 | int retval; |
298 | int rc = -1; | 300 | int rc = -1; |
301 | int namesize; | ||
302 | int i; | ||
299 | 303 | ||
300 | mode |= S_IFREG; | 304 | mode |= S_IFREG; |
301 | 305 | ||
@@ -323,29 +327,41 @@ static int cpio_mkfile(const char *name, const char *location, | |||
323 | goto error; | 327 | goto error; |
324 | } | 328 | } |
325 | 329 | ||
326 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" | 330 | size = 0; |
327 | "%08X%08X%08X%08X%08X%08X%08X", | 331 | for (i = 1; i <= nlinks; i++) { |
328 | "070701", /* magic */ | 332 | /* data goes on last link */ |
329 | ino++, /* ino */ | 333 | if (i == nlinks) size = buf.st_size; |
330 | mode, /* mode */ | 334 | |
331 | (long) uid, /* uid */ | 335 | namesize = strlen(name) + 1; |
332 | (long) gid, /* gid */ | 336 | sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" |
333 | 1, /* nlink */ | 337 | "%08lX%08X%08X%08X%08X%08X%08X", |
334 | (long) buf.st_mtime, /* mtime */ | 338 | "070701", /* magic */ |
335 | (int) buf.st_size, /* filesize */ | 339 | ino, /* ino */ |
336 | 3, /* major */ | 340 | mode, /* mode */ |
337 | 1, /* minor */ | 341 | (long) uid, /* uid */ |
338 | 0, /* rmajor */ | 342 | (long) gid, /* gid */ |
339 | 0, /* rminor */ | 343 | nlinks, /* nlink */ |
340 | (unsigned)strlen(name) + 1,/* namesize */ | 344 | (long) buf.st_mtime, /* mtime */ |
341 | 0); /* chksum */ | 345 | size, /* filesize */ |
342 | push_hdr(s); | 346 | 3, /* major */ |
343 | push_string(name); | 347 | 1, /* minor */ |
344 | push_pad(); | 348 | 0, /* rmajor */ |
349 | 0, /* rminor */ | ||
350 | namesize, /* namesize */ | ||
351 | 0); /* chksum */ | ||
352 | push_hdr(s); | ||
353 | push_string(name); | ||
354 | push_pad(); | ||
355 | |||
356 | if (size) { | ||
357 | fwrite(filebuf, size, 1, stdout); | ||
358 | offset += size; | ||
359 | push_pad(); | ||
360 | } | ||
345 | 361 | ||
346 | fwrite(filebuf, buf.st_size, 1, stdout); | 362 | name += namesize; |
347 | offset += buf.st_size; | 363 | } |
348 | push_pad(); | 364 | ino++; |
349 | rc = 0; | 365 | rc = 0; |
350 | 366 | ||
351 | error: | 367 | error: |
@@ -357,18 +373,51 @@ error: | |||
357 | static int cpio_mkfile_line(const char *line) | 373 | static int cpio_mkfile_line(const char *line) |
358 | { | 374 | { |
359 | char name[PATH_MAX + 1]; | 375 | char name[PATH_MAX + 1]; |
376 | char *dname = NULL; /* malloc'ed buffer for hard links */ | ||
360 | char location[PATH_MAX + 1]; | 377 | char location[PATH_MAX + 1]; |
361 | unsigned int mode; | 378 | unsigned int mode; |
362 | int uid; | 379 | int uid; |
363 | int gid; | 380 | int gid; |
381 | int nlinks = 1; | ||
382 | int end = 0, dname_len = 0; | ||
364 | int rc = -1; | 383 | int rc = -1; |
365 | 384 | ||
366 | if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, location, &mode, &uid, &gid)) { | 385 | if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) |
386 | "s %o %d %d %n", | ||
387 | name, location, &mode, &uid, &gid, &end)) { | ||
367 | fprintf(stderr, "Unrecognized file format '%s'", line); | 388 | fprintf(stderr, "Unrecognized file format '%s'", line); |
368 | goto fail; | 389 | goto fail; |
369 | } | 390 | } |
370 | rc = cpio_mkfile(name, location, mode, uid, gid); | 391 | if (end && isgraph(line[end])) { |
392 | int len; | ||
393 | int nend; | ||
394 | |||
395 | dname = malloc(strlen(line)); | ||
396 | if (!dname) { | ||
397 | fprintf (stderr, "out of memory (%d)\n", dname_len); | ||
398 | goto fail; | ||
399 | } | ||
400 | |||
401 | dname_len = strlen(name) + 1; | ||
402 | memcpy(dname, name, dname_len); | ||
403 | |||
404 | do { | ||
405 | nend = 0; | ||
406 | if (sscanf(line + end, "%" str(PATH_MAX) "s %n", | ||
407 | name, &nend) < 1) | ||
408 | break; | ||
409 | len = strlen(name) + 1; | ||
410 | memcpy(dname + dname_len, name, len); | ||
411 | dname_len += len; | ||
412 | nlinks++; | ||
413 | end += nend; | ||
414 | } while (isgraph(line[end])); | ||
415 | } else { | ||
416 | dname = name; | ||
417 | } | ||
418 | rc = cpio_mkfile(dname, location, mode, uid, gid, nlinks); | ||
371 | fail: | 419 | fail: |
420 | if (dname_len) free(dname); | ||
372 | return rc; | 421 | return rc; |
373 | } | 422 | } |
374 | 423 | ||
@@ -381,22 +430,23 @@ void usage(const char *prog) | |||
381 | "describe the files to be included in the initramfs archive:\n" | 430 | "describe the files to be included in the initramfs archive:\n" |
382 | "\n" | 431 | "\n" |
383 | "# a comment\n" | 432 | "# a comment\n" |
384 | "file <name> <location> <mode> <uid> <gid>\n" | 433 | "file <name> <location> <mode> <uid> <gid> [<hard links>]\n" |
385 | "dir <name> <mode> <uid> <gid>\n" | 434 | "dir <name> <mode> <uid> <gid>\n" |
386 | "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n" | 435 | "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n" |
387 | "slink <name> <target> <mode> <uid> <gid>\n" | 436 | "slink <name> <target> <mode> <uid> <gid>\n" |
388 | "pipe <name> <mode> <uid> <gid>\n" | 437 | "pipe <name> <mode> <uid> <gid>\n" |
389 | "sock <name> <mode> <uid> <gid>\n" | 438 | "sock <name> <mode> <uid> <gid>\n" |
390 | "\n" | 439 | "\n" |
391 | "<name> name of the file/dir/nod/etc in the archive\n" | 440 | "<name> name of the file/dir/nod/etc in the archive\n" |
392 | "<location> location of the file in the current filesystem\n" | 441 | "<location> location of the file in the current filesystem\n" |
393 | "<target> link target\n" | 442 | "<target> link target\n" |
394 | "<mode> mode/permissions of the file\n" | 443 | "<mode> mode/permissions of the file\n" |
395 | "<uid> user id (0=root)\n" | 444 | "<uid> user id (0=root)\n" |
396 | "<gid> group id (0=root)\n" | 445 | "<gid> group id (0=root)\n" |
397 | "<dev_type> device type (b=block, c=character)\n" | 446 | "<dev_type> device type (b=block, c=character)\n" |
398 | "<maj> major number of nod\n" | 447 | "<maj> major number of nod\n" |
399 | "<min> minor number of nod\n" | 448 | "<min> minor number of nod\n" |
449 | "<hard links> space separated list of other links to file\n" | ||
400 | "\n" | 450 | "\n" |
401 | "example:\n" | 451 | "example:\n" |
402 | "# A simple initramfs\n" | 452 | "# A simple initramfs\n" |