aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuciano Rocha <strange@nsk.no-ip.org>2007-02-10 04:44:45 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:25 -0500
commit24fa50961451b7b21081e4d16836952b17eb5fb3 (patch)
treed40f2474ffd9046f0978bc5132a9ff4ef3140c00
parent67d38229dfa64cf9a75f83746dde345f47bbd8dc (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.c122
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... */
290static int cpio_mkfile(const char *name, const char *location, 290static 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
351error: 367error:
@@ -357,18 +373,51 @@ error:
357static int cpio_mkfile_line(const char *line) 373static 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"