--chain can be used with copy-out mode to append to an existing output file. Unlike --append, the existing output file is left as-is, with the new cpio archive being appended after any previous trailer.
This functionality is particularly useful for Linux kernel initramfs image generation, where a CPU microcode cpio archive is commonly placed before subsequent cpio archives providing initramfs filesystem contents. Signed-off-by: David Disseldorp <[email protected]> --- src/extern.h | 1 + src/global.c | 3 +++ src/main.c | 29 +++++++++++++++++++++++++++-- src/util.c | 9 ++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/extern.h b/src/extern.h index 5365a8b..3b59053 100644 --- a/src/extern.h +++ b/src/extern.h @@ -41,6 +41,7 @@ extern int link_flag; extern int retain_time_flag; extern int crc_i_flag; extern int append_flag; +extern int chain_flag; extern int swap_bytes_flag; extern int swap_halfwords_flag; extern int swapping_bytes; diff --git a/src/global.c b/src/global.c index cbc35cd..21981fb 100644 --- a/src/global.c +++ b/src/global.c @@ -68,6 +68,9 @@ int crc_i_flag = false; /* If true, append to end of archive. (-A) */ int append_flag = false; +/* If true, append to end of output archive file. (--chain) */ +int chain_flag = false; + /* If true, swap bytes of each file during cpio -i. */ int swap_bytes_flag = false; diff --git a/src/main.c b/src/main.c index 9d6a394..3611daf 100644 --- a/src/main.c +++ b/src/main.c @@ -60,7 +60,8 @@ enum cpio_options { TO_STDOUT_OPTION, RENUMBER_INODES_OPTION, IGNORE_DEVNO_OPTION, - DEVICE_INDEPENDENT_OPTION + DEVICE_INDEPENDENT_OPTION, + CHAIN_OPTION }; const char *program_authors[] = @@ -190,6 +191,8 @@ static struct argp_option options[] = { N_("Operation modifiers valid only in copy-out mode:"), GRID }, {"append", 'A', 0, 0, N_("Append to an existing archive."), GRID+1 }, + {"chain", CHAIN_OPTION, 0, 0, + N_("Chain to the end of an existing file."), GRID+1 }, {NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0, N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 }, {"renumber-inodes", RENUMBER_INODES_OPTION, NULL, 0, @@ -306,9 +309,17 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case 'A': /* Append to the archive. */ + if (chain_flag) + USAGE_ERROR ((0, 0, _("--append is incompatible with --chain"))); append_flag = true; break; + case CHAIN_OPTION: /* Append a new archive to the end of a file */ + if (append_flag) + USAGE_ERROR ((0, 0, _("--append is incompatible with --chain"))); + chain_flag = true; + break; + case 'b': /* Swap bytes and halfwords. */ swap_bytes_flag = true; swap_halfwords_flag = true; @@ -605,6 +616,7 @@ process_args (int argc, char *argv[]) CHECK_USAGE (reset_time_flag, "--reset", "--extract"); CHECK_USAGE (xstat != lstat, "--dereference", "--extract"); CHECK_USAGE (append_flag, "--append", "--extract"); + CHECK_USAGE (chain_flag, "--chain", "--extract"); CHECK_USAGE (output_archive_name, "-O", "--extract"); CHECK_USAGE (renumber_inodes_option, "--renumber-inodes", "--extract"); CHECK_USAGE (ignore_devno_option, "--ignore-devno", "--extract"); @@ -655,6 +667,11 @@ process_args (int argc, char *argv[]) _("--append is used but no archive file name " "is given (use -F or -O options)"))); + if (chain_flag && !(archive_name || output_archive_name)) + USAGE_ERROR ((0, 0, + _("--chain is used but no archive file name " + "is given (use -F or -O options)"))); + CHECK_USAGE (rename_batch_file, "--rename-batch-file", "--create"); CHECK_USAGE (input_archive_name, "-I", "--create"); if (archive_name && output_archive_name) @@ -688,6 +705,7 @@ process_args (int argc, char *argv[]) CHECK_USAGE (table_flag, "--list", "--pass-through"); CHECK_USAGE (rename_flag, "--rename", "--pass-through"); CHECK_USAGE (append_flag, "--append", "--pass-through"); + CHECK_USAGE (chain_flag, "--chain", "--pass-through"); CHECK_USAGE (rename_batch_file, "--rename-batch-file", "--pass-through"); CHECK_USAGE (no_abs_paths_flag, "--no-absolute-pathnames", "--pass-through"); @@ -706,12 +724,19 @@ process_args (int argc, char *argv[]) if (copy_function != process_copy_in && copy_function != process_copy_out) error (PAXEXIT_FAILURE, 0, _("-F can be used only with --create or --extract")); + if (chain_flag) + { + if (copy_function != process_copy_out) + error (PAXEXIT_FAILURE, 0, + _("--chain can only be used with --create")); + } archive_des = open_archive (archive_name); if (archive_des < 0) error (PAXEXIT_FAILURE, errno, _("Cannot open %s"), quotearg_colon (archive_name)); + } - + /* Prevent SysV non-root users from giving away files inadvertantly. This happens automatically on BSD, where only root can give away files. */ diff --git a/src/util.c b/src/util.c index 346ced7..d81ef30 100644 --- a/src/util.c +++ b/src/util.c @@ -804,7 +804,14 @@ open_archive (char *file) fd = rmtopen (file, O_RDONLY | O_BINARY | O_NONBLOCK, MODE_RW, rsh_command_option); else { - if (!append_flag) + if (chain_flag) + { + fd = rmtopen (file, O_WRONLY | O_BINARY | O_NONBLOCK, MODE_RW, + rsh_command_option); + if (fd >= 0 && lseek (fd, 0, SEEK_END) < 0) + error (PAXEXIT_FAILURE, errno, _("failed to seek for --chain")); + } + else if (!append_flag) fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NONBLOCK, MODE_RW, rsh_command_option); else -- 2.26.2
