File 0001-add-chain-option.patch of Package cpio

From 86a5bc861192cc87d0e9197ef86cfce32ebb945c Mon Sep 17 00:00:00 2001
From: David Disseldorp <ddiss@suse.de>
Date: Mon, 1 Mar 2021 01:38:21 +0100
Subject: [PATCH 1/7] add --chain option

--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 <ddiss@suse.de>
---
 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
openSUSE Build Service is sponsored by