Commit 24fa50961451b7b21081e4d16836952b17eb5fb3
Committed by
Linus Torvalds
1 parent
67d38229df
Exists in
master
and in
39 other branches
[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>
Showing 1 changed file with 86 additions and 36 deletions Side-by-side Diff
usr/gen_init_cpio.c
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | * Original work by Jeff Garzik |
15 | 15 | * |
16 | 16 | * External file lists, symlink, pipe and fifo support by Thayne Harbaugh |
17 | + * Hard link support by Luciano Rocha | |
17 | 18 | */ |
18 | 19 | |
19 | 20 | #define xstr(s) #s |
20 | 21 | |
21 | 22 | |
22 | 23 | |
... | ... | @@ -286,16 +287,19 @@ |
286 | 287 | return rc; |
287 | 288 | } |
288 | 289 | |
289 | -/* Not marked static to keep the compiler quiet, as no one uses this yet... */ | |
290 | 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 | 294 | char s[256]; |
294 | 295 | char *filebuf = NULL; |
295 | 296 | struct stat buf; |
297 | + long size; | |
296 | 298 | int file = -1; |
297 | 299 | int retval; |
298 | 300 | int rc = -1; |
301 | + int namesize; | |
302 | + int i; | |
299 | 303 | |
300 | 304 | mode |= S_IFREG; |
301 | 305 | |
302 | 306 | |
... | ... | @@ -323,29 +327,41 @@ |
323 | 327 | goto error; |
324 | 328 | } |
325 | 329 | |
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(); | |
330 | + size = 0; | |
331 | + for (i = 1; i <= nlinks; i++) { | |
332 | + /* data goes on last link */ | |
333 | + if (i == nlinks) size = buf.st_size; | |
345 | 334 | |
346 | - fwrite(filebuf, buf.st_size, 1, stdout); | |
347 | - offset += buf.st_size; | |
348 | - push_pad(); | |
335 | + namesize = strlen(name) + 1; | |
336 | + sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" | |
337 | + "%08lX%08X%08X%08X%08X%08X%08X", | |
338 | + "070701", /* magic */ | |
339 | + ino, /* ino */ | |
340 | + mode, /* mode */ | |
341 | + (long) uid, /* uid */ | |
342 | + (long) gid, /* gid */ | |
343 | + nlinks, /* nlink */ | |
344 | + (long) buf.st_mtime, /* mtime */ | |
345 | + size, /* filesize */ | |
346 | + 3, /* major */ | |
347 | + 1, /* minor */ | |
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 | + } | |
361 | + | |
362 | + name += namesize; | |
363 | + } | |
364 | + ino++; | |
349 | 365 | rc = 0; |
350 | 366 | |
351 | 367 | error: |
352 | 368 | |
353 | 369 | |
354 | 370 | |
355 | 371 | |
... | ... | @@ -357,18 +373,51 @@ |
357 | 373 | static int cpio_mkfile_line(const char *line) |
358 | 374 | { |
359 | 375 | char name[PATH_MAX + 1]; |
376 | + char *dname = NULL; /* malloc'ed buffer for hard links */ | |
360 | 377 | char location[PATH_MAX + 1]; |
361 | 378 | unsigned int mode; |
362 | 379 | int uid; |
363 | 380 | int gid; |
381 | + int nlinks = 1; | |
382 | + int end = 0, dname_len = 0; | |
364 | 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 | 388 | fprintf(stderr, "Unrecognized file format '%s'", line); |
368 | 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 | 419 | fail: |
420 | + if (dname_len) free(dname); | |
372 | 421 | return rc; |
373 | 422 | } |
374 | 423 | |
375 | 424 | |
... | ... | @@ -381,22 +430,23 @@ |
381 | 430 | "describe the files to be included in the initramfs archive:\n" |
382 | 431 | "\n" |
383 | 432 | "# a comment\n" |
384 | - "file <name> <location> <mode> <uid> <gid>\n" | |
433 | + "file <name> <location> <mode> <uid> <gid> [<hard links>]\n" | |
385 | 434 | "dir <name> <mode> <uid> <gid>\n" |
386 | 435 | "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n" |
387 | 436 | "slink <name> <target> <mode> <uid> <gid>\n" |
388 | 437 | "pipe <name> <mode> <uid> <gid>\n" |
389 | 438 | "sock <name> <mode> <uid> <gid>\n" |
390 | 439 | "\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" | |
440 | + "<name> name of the file/dir/nod/etc in the archive\n" | |
441 | + "<location> location of the file in the current filesystem\n" | |
442 | + "<target> link target\n" | |
443 | + "<mode> mode/permissions of the file\n" | |
444 | + "<uid> user id (0=root)\n" | |
445 | + "<gid> group id (0=root)\n" | |
446 | + "<dev_type> device type (b=block, c=character)\n" | |
447 | + "<maj> major number of nod\n" | |
448 | + "<min> minor number of nod\n" | |
449 | + "<hard links> space separated list of other links to file\n" | |
400 | 450 | "\n" |
401 | 451 | "example:\n" |
402 | 452 | "# A simple initramfs\n" |