diff --git a/SOURCES/cpio-2.11-recovery.patch b/SOURCES/cpio-2.11-recovery.patch new file mode 100644 index 0000000..1109bba --- /dev/null +++ b/SOURCES/cpio-2.11-recovery.patch @@ -0,0 +1,104 @@ +From 5e1e4fae6a9eab069866eb46b2f91d60fae34efe Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Thu, 11 Dec 2014 12:51:21 +0200 +Subject: [PATCH] Fix error recovery in copy-in mode + +(+ complete sync of symlink-bad-length.at test) + +* src/copyin.c (copyin_link): Fix null dereference. +(read_in_header): Fix error recovery (bug introduced by +27e0ae55). +* tests/symlink-bad-length.at: Test error recovery. +Catch various architecture-dependent error messages (suggested +by Pavel Raiskup). +--- + src/copyin.c | 10 ++++++---- + tests/symlink-bad-length.at | 16 ++++++++++++---- + 2 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/src/copyin.c b/src/copyin.c +index 29d0fb1..274bd49 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -655,7 +655,7 @@ copyin_device (struct cpio_file_stat* file_hdr) + } + + static void +-copyin_link(struct cpio_file_stat *file_hdr, int in_file_des) ++copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + { + char *link_name = NULL; /* Name of hard and symbolic links. */ + int res; /* Result of various function calls. */ +@@ -666,6 +666,8 @@ copyin_link(struct cpio_file_stat *file_hdr, int in_file_des) + if (archive_format != arf_tar && archive_format != arf_ustar) + { + link_name = get_link_name (file_hdr, in_file_des); ++ if (!link_name) ++ return; + } + else + { +@@ -1020,7 +1022,7 @@ read_in_header (struct cpio_file_stat *file_hdr, int in_des) + + file_hdr->c_tar_linkname = NULL; + +- tape_buffered_read (magic.str, in_des, 6L); ++ tape_buffered_read (magic.str, in_des, sizeof (magic.str)); + while (1) + { + if (append_flag) +@@ -1065,8 +1067,8 @@ read_in_header (struct cpio_file_stat *file_hdr, int in_des) + break; + } + bytes_skipped++; +- memmove (magic.str, magic.str + 1, 5); +- tape_buffered_read (magic.str, in_des, 1L); ++ memmove (magic.str, magic.str + 1, sizeof (magic.str) - 1); ++ tape_buffered_read (magic.str + sizeof (magic.str) - 1, in_des, 1L); + } + } + +diff --git a/tests/symlink-bad-length.at b/tests/symlink-bad-length.at +index 84123a4..fd2c87e 100644 +--- a/tests/symlink-bad-length.at ++++ b/tests/symlink-bad-length.at +@@ -1,5 +1,5 @@ + # Process this file with autom4te to create testsuite. -*- Autotest -*- +-# Copyright (C) 2014 Free Software Foundation, Inc. ++# Copyright (C) 2014-2015, 2017 Free Software Foundation, Inc. + + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -35,18 +35,26 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + ]) + ++# The exact error message and exit status depend on the host architecture, ++# therefore strderr is filtered out and error code is not checked. ++ ++# So far the only case when cpio would exit with code 0 is when it skips ++# several bytes and encounters a valid record header. Perhaps it should ++# exit with code 2 (non-critical error), if at least one byte was skipped, ++# but that could hurt backward compatibility. ++ + AT_CHECK([ + base64 -d ARCHIVE.base64 > ARCHIVE || AT_SKIP_TEST +-TZ=UTC cpio -ntv < ARCHIVE 2>stderr +-rc=$? ++TZ=UTC cpio -ntv < ARCHIVE 2>stderr + cat stderr | grep -v \ + -e 'stored filename length is out of range' \ + -e 'premature end of file' \ + -e 'archive header has reverse byte-order' \ + -e 'memory exhausted' \ ++ -e 'skipped [[0-9][0-9]*] bytes of junk' \ ++ -e '[[0-9][0-9]*] block' \ + >&2 + echo >&2 STDERR +-test "$rc" -ne 0 + ], + [0], + [-rw-rw-r-- 1 10029 10031 13 Nov 25 2014 FILE +-- +2.9.3 + diff --git a/SOURCES/cpio-2.11-reproducible.patch b/SOURCES/cpio-2.11-reproducible.patch new file mode 100644 index 0000000..705b772 --- /dev/null +++ b/SOURCES/cpio-2.11-reproducible.patch @@ -0,0 +1,395 @@ +From d249aaececed97d8ed78508ddec27fc73112601f Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Mon, 1 Dec 2014 15:02:38 +0200 +Subject: [PATCH 1/2] New options to create device and inode-independent + archives. + +* src/util.c (inode_val): New member trans_inode +(find_inode_val): New function. +(find_inode_file): Rewrite using the above. +(add_inode): Initialize the trans_inode member +depending on the value of renumber_inodes_option. +(get_inode_and_dev): New function. +(stat_to_cpio): Use get_inode_and_dev. +(arf_stores_inode_p): New function. +* src/extern.h (renumber_inodes_option) +(ignore_devno_option): New externs. +* src/global.c (renumber_inodes_option) +(ignore_devno_option): New variables. +* src/main.c: Add new options. + +* NEWS: Document changes. +* doc/cpio.1: Document new options. +* doc/cpio.texi: Likewise. +--- + NEWS | 14 +++++++++++ + doc/cpio.texi | 12 +++++++++ + src/extern.h | 8 ++++-- + src/global.c | 3 +++ + src/main.c | 34 +++++++++++++++++++++++-- + src/util.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 6 files changed, 138 insertions(+), 14 deletions(-) + +diff --git a/NEWS b/NEWS +index 1b068ba..c112d70 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,20 @@ See the end of file for copying conditions. + + Please send cpio bug reports to . + ++Downstream backports from newer versions ++* New options for copy-out mode: ++ ++** --ignore-devno ++Store 0 in the device number fields, instead of the actual device ++number. ++ ++** --renumber-inodes ++Renumber inodes when storing them in the archive. ++ ++** --device-independent or --reproducible ++Create reproducible archives. This is equivalent to ++--ignore-devno --renumber-inodes. ++ + Version 2.11 - Sergey Poznyakoff, 2010-03-10 + + * Fix mt build. +diff --git a/doc/cpio.texi b/doc/cpio.texi +index 1af808a..c9b62ee 100644 +--- a/doc/cpio.texi ++++ b/doc/cpio.texi +@@ -342,6 +342,11 @@ Set the I/O block size to @var{io-size} bytes. + @itemx --make-directories + Create leading directories where needed. + ++@item --device-independent ++@itemx --reproducible ++Create reproducible archives. This is equivalent to ++@option{--ignore-devno --renumber-inodes}. ++ + @item -E @var{file} + @itemx --pattern-file=@var{file} + Read additional patterns specifying filenames to extract or list from +@@ -419,6 +424,10 @@ of the remote host. The hostname can be preceded by a username and an @samp{@@} + access the remote tape drive as that user, if you have permission to do + so (typically an entry in that user's @file{~/.rhosts} file). + ++@item --ignore-devno ++Store 0 in the device number field of each archive member, instead of ++the actual device number. ++ + @item -k + Ignored; for compatibility with other versions of cpio. + +@@ -486,6 +495,9 @@ Do not print the number of blocks copied. + @itemx --rename + Interactively rename files. + ++@item --renumber-inodes ++Renumber inodes when storing them in the archive. ++ + @item -R @var{owner} + @itemx --owner @var{owner} + +diff --git a/src/extern.h b/src/extern.h +index 4f94d40..f3a6c47 100644 +--- a/src/extern.h ++++ b/src/extern.h +@@ -56,6 +56,8 @@ extern int only_verify_crc_flag; + extern int no_abs_paths_flag; + extern unsigned int warn_option; + extern mode_t newdir_umask; ++extern int renumber_inodes_option; ++extern int ignore_devno_option; + + /* Values for warn_option */ + #define CPIO_WARN_NONE 0 +@@ -171,8 +173,8 @@ void create_all_directories (char *name); + void prepare_append (int out_file_des); + char *find_inode_file (ino_t node_num, + unsigned long major_num, unsigned long minor_num); +-void add_inode (ino_t node_num, char *file_name, +- unsigned long major_num, unsigned long minor_num); ++struct inode_val *add_inode (ino_t node_num, char *file_name, ++ unsigned long major_num, unsigned long minor_num); + int open_archive (char *file); + void tape_offline (int tape_des); + void get_next_reel (int tape_des); +@@ -217,3 +219,5 @@ void delay_set_stat (char const *file_name, struct stat *st, + int repair_delayed_set_stat (struct cpio_file_stat *file_hdr); + void apply_delayed_set_stat (void); + ++int arf_stores_inode_p (enum archive_format arf); ++ +diff --git a/src/global.c b/src/global.c +index cff9720..fb074fb 100644 +--- a/src/global.c ++++ b/src/global.c +@@ -193,3 +193,6 @@ int (*xstat) (); + + /* Which copy operation to perform. (-i, -o, -p) */ + void (*copy_function) () = 0; ++ ++int renumber_inodes_option; ++int ignore_devno_option; +diff --git a/src/main.c b/src/main.c +index 9b9bf74..6945c7d 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -57,7 +57,10 @@ enum cpio_options { + FORCE_LOCAL_OPTION, + DEBUG_OPTION, + BLOCK_SIZE_OPTION, +- TO_STDOUT_OPTION ++ TO_STDOUT_OPTION, ++ RENUMBER_INODES_OPTION, ++ IGNORE_DEVNO_OPTION, ++ DEVICE_INDEPENDENT_OPTION + }; + + const char *program_authors[] = +@@ -175,6 +178,13 @@ static struct argp_option options[] = { + N_("Append to an existing archive."), 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, ++ N_("Renumber inodes") }, ++ {"ignore-devno", IGNORE_DEVNO_OPTION, NULL, 0, ++ N_("Don't store device numbers") }, ++ {"device-independent", DEVICE_INDEPENDENT_OPTION, NULL, 0, ++ N_("Create device-independent (reproducible) archives") }, ++ {"reproducible", 0, NULL, OPTION_ALIAS }, + #undef GRID + + /* ********** */ +@@ -432,7 +442,19 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg); + error (PAXEXIT_FAILURE, 0, _("Mode already defined")); + copy_function = process_copy_pass; + break; +- ++ ++ case IGNORE_DEVNO_OPTION: ++ ignore_devno_option = 1; ++ break; ++ ++ case RENUMBER_INODES_OPTION: ++ renumber_inodes_option = 1; ++ break; ++ ++ case DEVICE_INDEPENDENT_OPTION: ++ ignore_devno_option = renumber_inodes_option = 1; ++ break; ++ + case RSH_COMMAND_OPTION: + rsh_command_option = arg; + break; +@@ -575,6 +597,8 @@ process_args (int argc, char *argv[]) + CHECK_USAGE(xstat != lstat, "--dereference", "--extract"); + CHECK_USAGE(append_flag, "--append", "--extract"); + CHECK_USAGE(output_archive_name, "-O", "--extract"); ++ CHECK_USAGE (renumber_inodes_option, "--renumber-inodes", "--extract"); ++ CHECK_USAGE (ignore_devno_option, "--ignore-devno", "--extract"); + if (to_stdout_option) + { + CHECK_USAGE(create_dir_flag, "--make-directories", "--to-stdout"); +@@ -630,6 +654,9 @@ process_args (int argc, char *argv[]) + archive_format = arf_binary; + if (output_archive_name) + archive_name = output_archive_name; ++ ++ if (!arf_stores_inode_p (archive_format)) ++ renumber_inodes_option = ignore_devno_option = 0; + } + else + { +@@ -655,6 +682,9 @@ process_args (int argc, char *argv[]) + CHECK_USAGE(no_abs_paths_flag, "--absolute-pathnames", + "--pass-through"); + CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through"); ++ CHECK_USAGE (renumber_inodes_option, "--renumber-inodes", ++ "--pass-through"); ++ CHECK_USAGE (ignore_devno_option, "--ignore-devno", "--pass-through"); + + directory_name = argv[index]; + } +diff --git a/src/util.c b/src/util.c +index 2a821c7..ce45842 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -689,6 +689,7 @@ struct inode_val + ino_t inode; + unsigned long major_num; + unsigned long minor_num; ++ ino_t trans_inode; + char *file_name; + }; + +@@ -712,8 +713,8 @@ inode_val_compare (const void *val1, const void *val2) + && ival1->minor_num == ival2->minor_num; + } + +-char * +-find_inode_file (ino_t node_num, unsigned long major_num, ++static struct inode_val * ++find_inode_val (ino_t node_num, unsigned long major_num, + unsigned long minor_num) + { + struct inode_val sample; +@@ -725,32 +726,78 @@ find_inode_file (ino_t node_num, unsigned long major_num, + sample.inode = node_num; + sample.major_num = major_num; + sample.minor_num = minor_num; +- ival = hash_lookup (hash_table, &sample); ++ return hash_lookup (hash_table, &sample); ++} ++ ++char * ++find_inode_file (ino_t node_num, unsigned long major_num, ++ unsigned long minor_num) ++{ ++ struct inode_val *ival = find_inode_val (node_num, major_num, minor_num); + return ival ? ival->file_name : NULL; + } + + /* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ + +-void ++static ino_t next_inode; ++ ++struct inode_val * + add_inode (ino_t node_num, char *file_name, unsigned long major_num, + unsigned long minor_num) + { + struct inode_val *temp; +- struct inode_val *e; ++ struct inode_val *e = NULL; + + /* Create new inode record. */ + temp = (struct inode_val *) xmalloc (sizeof (struct inode_val)); + temp->inode = node_num; + temp->major_num = major_num; + temp->minor_num = minor_num; +- temp->file_name = xstrdup (file_name); ++ temp->file_name = file_name ? xstrdup (file_name) : NULL; ++ ++ if (renumber_inodes_option) ++ temp->trans_inode = next_inode++; ++ else ++ temp->trans_inode = temp->inode; + + if (!((hash_table + || (hash_table = hash_initialize (0, 0, inode_val_hasher, + inode_val_compare, 0))) + && (e = hash_insert (hash_table, temp)))) + xalloc_die (); +- /* FIXME: e is not used */ ++ return e; ++} ++ ++static ino_t ++get_inode_and_dev (struct cpio_file_stat *hdr, struct stat *st) ++{ ++ if (renumber_inodes_option) ++ { ++ if (st->st_nlink > 1) ++ { ++ struct inode_val *ival = find_inode_val (st->st_ino, ++ major (st->st_dev), ++ minor (st->st_dev)); ++ if (!ival) ++ ival = add_inode (st->st_ino, NULL, ++ major (st->st_dev), minor (st->st_dev)); ++ hdr->c_ino = ival->trans_inode; ++ } ++ else ++ hdr->c_ino = next_inode++; ++ } ++ else ++ hdr->c_ino = st->st_ino; ++ if (ignore_devno_option) ++ { ++ hdr->c_dev_maj = 0; ++ hdr->c_dev_min = 0; ++ } ++ else ++ { ++ hdr->c_dev_maj = major (st->st_dev); ++ hdr->c_dev_min = minor (st->st_dev); ++ } + } + + +@@ -1220,9 +1267,8 @@ sparse_write (int fildes, char *buf, unsigned int nbyte) + void + stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st) + { +- hdr->c_dev_maj = major (st->st_dev); +- hdr->c_dev_min = minor (st->st_dev); +- hdr->c_ino = st->st_ino; ++ get_inode_and_dev (hdr, st); ++ + /* For POSIX systems that don't define the S_IF macros, + we can't assume that S_ISfoo means the standard Unix + S_IFfoo bit(s) are set. So do it manually, with a +@@ -1618,3 +1664,18 @@ cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir) + return 0; + } + ++/* Return true if the archive format ARF stores inode numbers */ ++int ++arf_stores_inode_p (enum archive_format arf) ++{ ++ switch (arf) ++ { ++ case arf_tar: ++ case arf_ustar: ++ return 0; ++ ++ default: ++ break; ++ } ++ return 1; ++} +-- +2.9.3 + + +From 8d468d9c5134415b187dc5738a7fdaec17f87cf5 Mon Sep 17 00:00:00 2001 +From: Pavel Raiskup +Date: Mon, 6 Feb 2017 08:43:18 +0100 +Subject: [PATCH 2/2] build: lint warnings in --device-independent + +Complements: 3945f9db44c935608caa5f0 + +* src/util.c (find_inode_val): Drop unused variable. +(get_inode_and_dev): Function doesn't return any value, drop the +return value in definition. +--- + src/util.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/util.c b/src/util.c +index ce45842..f3efc6c 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -718,7 +718,6 @@ find_inode_val (ino_t node_num, unsigned long major_num, + unsigned long minor_num) + { + struct inode_val sample; +- struct inode_val *ival; + + if (!hash_table) + return NULL; +@@ -768,7 +767,7 @@ add_inode (ino_t node_num, char *file_name, unsigned long major_num, + return e; + } + +-static ino_t ++static void + get_inode_and_dev (struct cpio_file_stat *hdr, struct stat *st) + { + if (renumber_inodes_option) +-- +2.9.3 + diff --git a/SOURCES/cpio.1 b/SOURCES/cpio.1 index e6be6be..3449be9 100644 --- a/SOURCES/cpio.1 +++ b/SOURCES/cpio.1 @@ -115,6 +115,10 @@ Set the I/O block size to IO-SIZE bytes. `\fB\-d, \-\-make\-directories\fR' Create leading directories where needed. .TP +`\fB\-\-device\-independent, \-\-reproducible\fR' +Create reproducible archives. This is equivalent to \fB\-\-ignore\-devno +\-\-renumber\-inodes\fR. +.TP `\fB\-E \s-1FILE\s0, \-\-pattern\-file=FILE\fR' Read additional patterns specifying filenames to extract or list from \s-1FILE\s0. The lines of \s-1FILE\s0 are treated as if they had been @@ -181,6 +185,10 @@ username and an `\fB@\fR' to access the remote tape drive as that user, if you have permission to do so (typically an entry in that user's `\fB~/.rhosts\fR' file). .TP +`\fB\-\-ignore\-devno\fR' +Store 0 in the device number field of each archive member, instead of the +actual device number. +.TP `\fB\-k\fR' Ignored; for compatibility with other versions of cpio. .TP @@ -242,6 +250,9 @@ Do not print the number of blocks copied. `\fB\-r, \-\-rename\fR' Interactively rename files. .TP +`\fB\-\-renumber\-inodes\fR' +Renumber inodes when storing them in the archive. +.TP `\fB\-R [user][:.][group], \-\-owner [user][:.][group]\fR' Set the ownership of all files created to the specified user and/or group in copy-out and copy-pass modes. Either the user, the diff --git a/SPECS/cpio.spec b/SPECS/cpio.spec index 0531132..71e1e81 100644 --- a/SPECS/cpio.spec +++ b/SPECS/cpio.spec @@ -1,7 +1,7 @@ Summary: A GNU archiving program Name: cpio Version: 2.11 -Release: 25%{?dist} +Release: 27%{?dist} License: GPLv3+ Group: Applications/Archiving URL: http://www.gnu.org/software/cpio/ @@ -45,6 +45,14 @@ Patch13: cpio-2.11-testsuite-CVE-2014-9112.patch # ~> upstream ccec71ec318f Patch14: cpio-2.11-crc-big-files.patch +# Reproducible archives (rhbz#1386662) +# ~> upstream 3945f9db4 + small warning patch. +Patch15: cpio-2.11-reproducible.patch + +# Don't segfault during recovery +# ~> upstream fd262d116c4564c1796 +Patch16: cpio-2.11-recovery.patch + Requires(post): /sbin/install-info Requires(preun): /sbin/install-info Provides: bundled(gnulib) @@ -82,6 +90,8 @@ Install cpio if you need a program to manage file archives. %patch12 -p1 -b .CVE-2014-9112 %patch13 -p1 -b .CVE-2014-9112-test %patch14 -p1 -b .crc-big-files +%patch15 -p1 -b .reproducible +%patch16 -p1 -b .recovery autoreconf -v @@ -132,6 +142,12 @@ fi %{_infodir}/*.info* %changelog +* Mon Feb 06 2017 Pavel Raiskup - 2.11-27 +- don't segfault during recovery (rhbz#1318084) + +* Mon Feb 06 2017 Pavel Raiskup - 2.11-26 +- reproducible archives (rhbz#1386662) + * Mon Feb 06 2017 Pavel Raiskup - 2.11-25 - fix crc checksum for files ~200M+ (rhbz#1415081)