From 955b315761363083fee038fc049d513fbb143500 Mon Sep 17 00:00:00 2001 From: Lukas Javorsky Date: Tue, 16 May 2023 12:46:58 +0000 Subject: [PATCH] Rebase to version 2.14 Patches applied: cpio-2.13-mutiple-definition.patch cpio-2.13-reset-gid-uid.patch Other patches partly applied or not at all New patch applied from http://git.savannah.gnu.org/cgit/cpio.git/commit/?id=a3eb338a40750ecfd73de7054d44e69008866621 Resolves: CVE-2015-1197 --- cpio-2.11-retain-symlink-times.patch | 94 -- cpio-2.13-mutiple-definition.patch | 13 - cpio-2.13-reset-gid-uid.patch | 63 -- cpio-2.13-revert-CVE-2015-1197-fix.patch | 91 -- ...number.patch => cpio-2.14-dev_number.patch | 6 +- ...exitCode.patch => cpio-2.14-exitCode.patch | 12 +- ...atch => cpio-2.14-patternnamesigsegv.patch | 43 +- ...s-and-modification-times-of-symlinks.patch | 981 ++++++++++++++++++ cpio-2.9-rh.patch => cpio-2.14-rh.patch | 16 +- cpio.spec | 29 +- sources | 2 +- 11 files changed, 1025 insertions(+), 325 deletions(-) delete mode 100644 cpio-2.11-retain-symlink-times.patch delete mode 100644 cpio-2.13-mutiple-definition.patch delete mode 100644 cpio-2.13-reset-gid-uid.patch delete mode 100644 cpio-2.13-revert-CVE-2015-1197-fix.patch rename cpio-2.13-dev_number.patch => cpio-2.14-dev_number.patch (88%) rename cpio-2.13-exitCode.patch => cpio-2.14-exitCode.patch (78%) rename cpio-2.10-patternnamesigsegv.patch => cpio-2.14-patternnamesigsegv.patch (53%) create mode 100644 cpio-2.14-restore-access-and-modification-times-of-symlinks.patch rename cpio-2.9-rh.patch => cpio-2.14-rh.patch (87%) diff --git a/cpio-2.11-retain-symlink-times.patch b/cpio-2.11-retain-symlink-times.patch deleted file mode 100644 index 1aeb174..0000000 --- a/cpio-2.11-retain-symlink-times.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 8bce60df53f93c9cbfb18274c6700c143a0092c6 Mon Sep 17 00:00:00 2001 -From: Pavel Raiskup -Date: Fri, 3 Jul 2020 13:00:18 +0200 -Subject: [PATCH] Extract: retain times for symlinks - -Original report by Pat Riehecky at -https://bugzilla.redhat.com/1486364 - -* src/copyin.c (copyin_device): Don't check for retain_time_flag -global, it's done by set_file_times. -(copyin_link): Call set_file_times to restore symlink times. -* src/util.c (set_perms): Don't check for retain_time_flag global, -done by set_file_times call. -(set_file_times): Do nothing if retain_time_flag global is false. -* src/copypass.c (process_copy_pass): Call set_file_times for -symlinks. ---- - src/copyin.c | 5 ++--- - src/copypass.c | 2 ++ - src/util.c | 8 +++++--- - 3 files changed, 9 insertions(+), 6 deletions(-) - -diff --git a/src/copyin.c b/src/copyin.c -index bf3b0a8..93b006a 100644 ---- a/src/copyin.c -+++ b/src/copyin.c -@@ -615,9 +615,7 @@ copyin_device (struct cpio_file_stat* file_hdr) - /* chown may have turned off some permissions we wanted. */ - if (chmod (file_hdr->c_name, file_hdr->c_mode) < 0) - chmod_error_details (file_hdr->c_name, file_hdr->c_mode); -- if (retain_time_flag) -- set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, -- file_hdr->c_mtime); -+ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, file_hdr->c_mtime); - } - - static void -@@ -668,6 +666,7 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) - && errno != EPERM) - chown_error_details (file_hdr->c_name, uid, gid); - } -+ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, file_hdr->c_mtime); - free (link_name); - } - -diff --git a/src/copypass.c b/src/copypass.c -index dc13b5b..a5f9b7b 100644 ---- a/src/copypass.c -+++ b/src/copypass.c -@@ -306,6 +306,8 @@ process_copy_pass () - && errno != EPERM) - chown_error_details (output_name.ds_string, uid, gid); - } -+ set_file_times (-1, output_name.ds_string, -+ in_file_stat.st_atime, in_file_stat.st_mtime); - free (link_name); - } - #endif -diff --git a/src/util.c b/src/util.c -index 4421b20..0e8d88c 100644 ---- a/src/util.c -+++ b/src/util.c -@@ -1230,8 +1230,7 @@ set_perms (int fd, struct cpio_file_stat *header) - /* chown may have turned off some permissions we wanted. */ - if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0) - chmod_error_details (header->c_name, header->c_mode); -- if (retain_time_flag) -- set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime); -+ set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime); - } - - void -@@ -1239,6 +1238,8 @@ set_file_times (int fd, - const char *name, unsigned long atime, unsigned long mtime) - { - struct timespec ts[2]; -+ if (!retain_time_flag) -+ return; - - memset (&ts, 0, sizeof ts); - -@@ -1247,7 +1248,8 @@ set_file_times (int fd, - - /* Silently ignore EROFS because reading the file won't have upset its - timestamp if it's on a read-only filesystem. */ -- if (fdutimens (fd, name, ts) < 0 && errno != EROFS) -+ if ((fd >= 0 ? fdutimens (fd, NULL, ts) : lutimens (name, ts)) < 0 -+ && errno != EROFS) - utime_error (name); - } - --- -2.24.1 - diff --git a/cpio-2.13-mutiple-definition.patch b/cpio-2.13-mutiple-definition.patch deleted file mode 100644 index ac97b81..0000000 --- a/cpio-2.13-mutiple-definition.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up cpio-2.13/src/global.c.me cpio-2.13/src/global.c ---- cpio-2.13/src/global.c.me 2020-01-30 17:17:42.015259283 +0100 -+++ cpio-2.13/src/global.c 2020-01-30 17:24:12.680794025 +0100 -@@ -184,9 +184,6 @@ unsigned int warn_option = 0; - /* Extract to standard output? */ - bool to_stdout_option = false; - --/* The name this program was run with. */ --char *program_name; -- - /* A pointer to either lstat or stat, depending on whether - dereferencing of symlinks is done for input files. */ - int (*xstat) (); diff --git a/cpio-2.13-reset-gid-uid.patch b/cpio-2.13-reset-gid-uid.patch deleted file mode 100644 index 56f720d..0000000 --- a/cpio-2.13-reset-gid-uid.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 5913893d6f3de65b16e1ad294b88893305efb20f Mon Sep 17 00:00:00 2001 -From: Ondrej Dubaj -Date: Thu, 18 Feb 2021 09:59:31 +0100 -Subject: [PATCH] * lib/system.h (ERRNO_IS_EACCES): Remove. Not used anymore. - (sys_reset_uid_gid): Re-initialize supplementary groups when switching - privileges. Fix ordering of setgid and setuid calls. - ---- - lib/system.h | 32 +++++++++++++++++++++++++------- - 1 file changed, 25 insertions(+), 7 deletions(-) - -diff --git a/lib/system.h b/lib/system.h -index 1c1a5d0..4fd3ce9 100644 ---- a/lib/system.h -+++ b/lib/system.h -@@ -470,19 +470,37 @@ char *getenv (); - #if MSDOS - # include - # define SET_BINARY_MODE(arc) setmode(arc, O_BINARY) --# define ERRNO_IS_EACCES errno == EACCES - # define mkdir(file, mode) (mkdir) (file) - # define TTY_NAME "con" - # define sys_reset_uid_gid() - #else - # define SET_BINARY_MODE(arc) --# define ERRNO_IS_EACCES 0 - # define TTY_NAME "/dev/tty" --# define sys_reset_uid_gid() \ -- do { \ -- if (! (setuid (getuid ()) == 0 && setgid (getgid ()) == 0)) \ -- abort (); \ -- } while (0) -+# include -+static inline void -+sys_reset_uid_gid (void) -+{ -+ struct passwd *pw; -+ uid_t uid = getuid (); -+ gid_t gid = getgid (); -+ -+ if ((pw = getpwuid (uid)) == NULL) -+ { -+ FATAL_ERROR ((0, errno, "%s(%lu)", "getpwuid", (unsigned long)uid)); -+ } -+ if (initgroups (pw->pw_name, getgid ())) -+ { -+ FATAL_ERROR ((0, errno, "%s", "initgroups")); -+ } -+ if (gid != getegid () && setgid (gid) && errno != EPERM) -+ { -+ FATAL_ERROR ((0, errno, "%s", "setgid")); -+ } -+ if (uid != geteuid () && setuid (uid) && errno != EPERM) -+ { -+ FATAL_ERROR ((0, errno, "%s", "setuid")); -+ } -+} - #endif - - #if XENIX --- -2.26.0 - diff --git a/cpio-2.13-revert-CVE-2015-1197-fix.patch b/cpio-2.13-revert-CVE-2015-1197-fix.patch deleted file mode 100644 index 1106ac7..0000000 --- a/cpio-2.13-revert-CVE-2015-1197-fix.patch +++ /dev/null @@ -1,91 +0,0 @@ -revert fix for CVE-2015-1197 as it causes shutdown issues - -revert suggested as a workaround by upstream: -https://lists.gnu.org/archive/html/bug-cpio/2019-11/msg00016.html - ---- b/src/copyin.c -+++ a/src/copyin.c -@@ -645,14 +645,13 @@ - link_name = xstrdup (file_hdr->c_tar_linkname); - } - -- cpio_safer_name_suffix (link_name, true, !no_abs_paths_flag, false); -- - res = UMASKED_SYMLINK (link_name, file_hdr->c_name, - file_hdr->c_mode); - if (res < 0 && create_dir_flag) - { - create_all_directories (file_hdr->c_name); -+ res = UMASKED_SYMLINK (link_name, file_hdr->c_name, -+ file_hdr->c_mode); -- res = UMASKED_SYMLINK (link_name, file_hdr->c_name, file_hdr->c_mode); - } - if (res < 0) - { ---- b/tests/CVE-2015-1197.at -+++ /dev/null -@@ -1,43 +0,0 @@ --# Process this file with autom4te to create testsuite. -*- Autotest -*- --# Copyright (C) 2009-2019 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 --# the Free Software Foundation; either version 3, or (at your option) --# any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program. If not, see . -- --AT_SETUP([CVE-2015-1197 (--no-absolute-filenames for symlinks)]) --AT_CHECK([ --tempdir=$(pwd)/tmp --mkdir $tempdir --touch $tempdir/file --ln -s $tempdir dir --AT_DATA([filelist], --[dir --dir/file --]) --ln -s /tmp dir --touch /tmp/file --cpio -o < filelist > test.cpio --rm dir /tmp/file --cpio --no-absolute-filenames -iv < test.cpio --], --[2], --[], --[1 block --cpio: Removing leading `/' from hard link targets --dir --cpio: dir/file: Cannot open: No such file or directory --dir/file --1 block --]) --AT_CLEANUP -- ---- b/tests/Makefile.am -+++ a/tests/Makefile.am -@@ -56,9 +56,8 @@ - symlink-long.at\ - symlink-to-stdout.at\ - version.at\ - big-block-size.at\ -- CVE-2015-1197.at\ - CVE-2019-14866.at - - TESTSUITE = $(srcdir)/testsuite - ---- b/tests/testsuite.at -+++ a/tests/testsuite.at -@@ -43,6 +43,5 @@ - m4_include([setstat04.at]) - m4_include([setstat05.at]) - m4_include([big-block-size.at]) - --m4_include([CVE-2015-1197.at]) - m4_include([CVE-2019-14866.at]) diff --git a/cpio-2.13-dev_number.patch b/cpio-2.14-dev_number.patch similarity index 88% rename from cpio-2.13-dev_number.patch rename to cpio-2.14-dev_number.patch index 20943a3..4a115e2 100644 --- a/cpio-2.13-dev_number.patch +++ b/cpio-2.14-dev_number.patch @@ -3,10 +3,10 @@ Date: Mon, 14 Sep 2015 09:37:15 +0200 Subject: [PATCH 3/7] Support major/minor device numbers over 127 (bz#450109) diff --git a/src/copyin.c b/src/copyin.c -index b29f348..1142d6a 100644 +index 2e72356..5d88a23 100644 --- a/src/copyin.c +++ b/src/copyin.c -@@ -1123,15 +1123,15 @@ read_in_binary (struct cpio_file_stat *file_hdr, +@@ -1287,15 +1287,15 @@ read_in_binary (struct cpio_file_stat *file_hdr, swab_array ((char *) short_hdr, 13); } @@ -24,5 +24,5 @@ index b29f348..1142d6a 100644 + file_hdr->c_rdev_maj = major ((unsigned short)short_hdr->c_rdev); + file_hdr->c_rdev_min = minor ((unsigned short)short_hdr->c_rdev); file_hdr->c_mtime = (unsigned long) short_hdr->c_mtimes[0] << 16 - | short_hdr->c_mtimes[1]; + | short_hdr->c_mtimes[1]; file_hdr->c_filesize = (unsigned long) short_hdr->c_filesizes[0] << 16 diff --git a/cpio-2.13-exitCode.patch b/cpio-2.14-exitCode.patch similarity index 78% rename from cpio-2.13-exitCode.patch rename to cpio-2.14-exitCode.patch index 4af7736..8c300a5 100644 --- a/cpio-2.13-exitCode.patch +++ b/cpio-2.14-exitCode.patch @@ -2,10 +2,10 @@ Subject: [PATCH 2/7] set exit code to 1 when cpio fails to store file > 4GB (#183224) diff --git a/src/copyout.c b/src/copyout.c -index 8b0beb6..4b7336b 100644 +index fa999bd..6e82f4c 100644 --- a/src/copyout.c +++ b/src/copyout.c -@@ -290,7 +290,7 @@ field_width_error (const char *filename, const char *fieldname, +@@ -287,7 +287,7 @@ field_width_error (const char *filename, const char *fieldname, { char valbuf[UINTMAX_STRSIZE_BOUND + 1]; char maxbuf[UINTMAX_STRSIZE_BOUND + 1]; @@ -15,7 +15,7 @@ index 8b0beb6..4b7336b 100644 STRINGIFY_BIGINT (value, valbuf), STRINGIFY_BIGINT (MAX_VAL_WITH_DIGITS (width - nul, LG_8), diff --git a/tests/CVE-2019-14866.at b/tests/CVE-2019-14866.at -index e877b39..50ad60b 100644 +index 530365a..5a4e15c 100644 --- a/tests/CVE-2019-14866.at +++ b/tests/CVE-2019-14866.at @@ -30,6 +30,5 @@ fi @@ -26,13 +26,13 @@ index e877b39..50ad60b 100644 ]) AT_CLEANUP diff --git a/tests/testsuite b/tests/testsuite -index b45c731..fd8454d 100755 +index 10531d1..d69dad9 100755 --- a/tests/testsuite +++ b/tests/testsuite -@@ -2885,7 +2885,6 @@ fi +@@ -2927,7 +2927,6 @@ fi at_status=$? at_failed=false $at_check_filter - echo >>"$at_stderr"; $as_echo "cpio: file: value size 17179869184 out of allowed range 0..8589934591 + echo >>"$at_stderr"; printf "%s\n" "cpio: file: value size 17179869184 out of allowed range 0..8589934591 -2 blocks " | \ $at_diff - "$at_stderr" || at_failed=: diff --git a/cpio-2.10-patternnamesigsegv.patch b/cpio-2.14-patternnamesigsegv.patch similarity index 53% rename from cpio-2.10-patternnamesigsegv.patch rename to cpio-2.14-patternnamesigsegv.patch index 27e3742..6e3ac1d 100644 --- a/cpio-2.10-patternnamesigsegv.patch +++ b/cpio-2.14-patternnamesigsegv.patch @@ -4,43 +4,34 @@ Subject: [PATCH 5/7] fix segfault with nonexisting file with patternnames (#567022) diff --git a/src/copyin.c b/src/copyin.c -index 12bd27c..183b5b5 100644 +index 5d88a23..f2babb7 100644 --- a/src/copyin.c +++ b/src/copyin.c -@@ -870,21 +870,24 @@ read_pattern_file () +@@ -948,21 +948,24 @@ read_pattern_file (void) pattern_fp = fopen (pattern_file_name, "r"); if (pattern_fp == NULL) - open_fatal (pattern_file_name); - while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL) -- { -- if (new_num_patterns >= max_new_patterns) -- { -- max_new_patterns += 1; -- new_save_patterns = (char **) -- xrealloc ((char *) new_save_patterns, -- max_new_patterns * sizeof (char *)); -- } -- new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string); -- ++new_num_patterns; -- } -- if (ferror (pattern_fp) || fclose (pattern_fp) == EOF) -- close_error (pattern_file_name); + open_error (pattern_file_name); + else + { + while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL) -+ { -+ if (new_num_patterns >= max_new_patterns) -+ { -+ max_new_patterns += 1; -+ new_save_patterns = (char **) -+ xrealloc ((char *) new_save_patterns, -+ max_new_patterns * sizeof (char *)); -+ } -+ new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string); -+ ++new_num_patterns; -+ } + { + if (new_num_patterns == max_new_patterns) +- new_save_patterns = x2nrealloc (new_save_patterns, ++ new_save_patterns = x2nrealloc (new_save_patterns, + &max_new_patterns, + sizeof (new_save_patterns[0])); + new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string); + ++new_num_patterns; + } + +- ds_free (&pattern_name); ++ ds_free (&pattern_name); + +- if (ferror (pattern_fp) || fclose (pattern_fp) == EOF) +- close_error (pattern_file_name); + if (ferror (pattern_fp) || fclose (pattern_fp) == EOF) + close_error (pattern_file_name); + } diff --git a/cpio-2.14-restore-access-and-modification-times-of-symlinks.patch b/cpio-2.14-restore-access-and-modification-times-of-symlinks.patch new file mode 100644 index 0000000..bbafe98 --- /dev/null +++ b/cpio-2.14-restore-access-and-modification-times-of-symlinks.patch @@ -0,0 +1,981 @@ +From a3eb338a40750ecfd73de7054d44e69008866621 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Wed, 17 May 2023 18:59:58 +0300 +Subject: [PATCH] Restore access and modification times of symlinks in copy-in + and copy-pass modes. + +* src/copyin.c: Update calls to set_file_times. +(copyin_link,replace_symlink_placeholders): Call set_file_times if needed. +* src/copyout.c: Update calls to set_file_times. +* src/copypass.c (process_copy_pass): Update calls to set_file_times. +Call set_file_times to restore times of extracted symlinks. +* src/extern.h (set_file_times): Take additional argument. +* src/util.c +(set_file_times): Take additional argument. Use fdutimensat to do the +job. +* tests/linktime.at: New file. +* tests/linktime01.at: New file. +* tests/Makefile.am: Add new files. +* tests/testsuite.at: Include new tests. +--- + src/copyin.c | 24 ++++++++++++----- + src/copyout.c | 4 +-- + src/copypass.c | 11 ++++++-- + src/extern.h | 2 +- + src/util.c | 7 ++--- + tests/Makefile.am | 4 ++- + tests/linktime.at | 63 +++++++++++++++++++++++++++++++++++++++++++++ + tests/linktime01.at | 51 ++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 3 +++ + 11 files changed, 155 insertions(+), 18 deletions(-) + create mode 100644 tests/linktime.at + create mode 100644 tests/linktime01.at + +diff --git a/gnu/Makefile.am b/gnu/Makefile.am +index d63397e..a208b30 100644 +--- a/gnu/Makefile.am ++++ b/gnu/Makefile.am +@@ -42,6 +42,7 @@ + # configmake \ + # dirname \ + # error \ ++# fdutimensat \ + # fileblocks \ + # fnmatch-gnu \ + # fseeko \ +@@ -71,7 +72,6 @@ + # strtoumax \ + # timespec \ + # unlocked-io \ +-# utimens \ + # utimensat \ + # version-etc-fsf \ + # xalloc \ +@@ -683,6 +683,14 @@ EXTRA_DIST += dirent-private.h + + ## end gnulib module fdopendir + ++## begin gnulib module fdutimensat ++ ++libgnu_a_SOURCES += fdutimensat.c ++ ++EXTRA_DIST += utimens.h ++ ++## end gnulib module fdutimensat ++ + ## begin gnulib module fileblocks + + if GL_COND_OBJ_FILEBLOCKS +@@ -863,6 +871,14 @@ libgnu_a_SOURCES += full-write.h full-write.c + + ## end gnulib module full-write + ++## begin gnulib module futimens ++ ++if GL_COND_OBJ_FUTIMENS ++libgnu_a_SOURCES += futimens.c ++endif ++ ++## end gnulib module futimens ++ + ## begin gnulib module gen-header + + # In 'sed', replace the pattern space with a "DO NOT EDIT" comment. +diff --git a/src/copyin.c b/src/copyin.c +index f2babb7..29ac764 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -344,7 +344,7 @@ create_defered_links_to_skipped (struct cpio_file_stat *file_hdr, + empty links that are still on the deferments list. */ + + static void +-create_final_defers () ++create_final_defers (void) + { + struct deferment *d; + int link_res; +@@ -619,7 +619,7 @@ copyin_device (struct cpio_file_stat* file_hdr) + chmod_error_details (file_hdr->c_name, file_hdr->c_mode); + if (retain_time_flag) + set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, +- file_hdr->c_mtime); ++ file_hdr->c_mtime, 0); + } + + struct delayed_link +@@ -737,12 +737,18 @@ replace_symlink_placeholders (void) + } + if (res < 0) + symlink_error (dl->source, dl->target); +- else if (!no_chown_flag) ++ else + { +- uid_t uid = set_owner_flag ? set_owner : dl->uid; +- gid_t gid = set_group_flag ? set_group : dl->gid; +- if (lchown (dl->target, uid, gid) < 0 && errno != EPERM) +- chown_error_details (dl->target, uid, gid); ++ if (!no_chown_flag) ++ { ++ uid_t uid = set_owner_flag ? set_owner : dl->uid; ++ gid_t gid = set_group_flag ? set_group : dl->gid; ++ if (lchown (dl->target, uid, gid) < 0 && errno != EPERM) ++ chown_error_details (dl->target, uid, gid); ++ } ++ if (retain_time_flag) ++ set_file_times (-1, dl->target, dl->mtime, dl->mtime, ++ AT_SYMLINK_NOFOLLOW); + } + } + } +@@ -797,6 +803,10 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) + if (lchown (file_hdr->c_name, uid, gid) < 0 && errno != EPERM) + chown_error_details (file_hdr->c_name, uid, gid); + } ++ ++ if (retain_time_flag) ++ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime, ++ file_hdr->c_mtime, AT_SYMLINK_NOFOLLOW); + } + free (link_name); + } +diff --git a/src/copyout.c b/src/copyout.c +index 6e82f4c..8fae895 100644 +--- a/src/copyout.c ++++ b/src/copyout.c +@@ -227,7 +227,7 @@ writeout_defered_file (struct cpio_file_stat *header, int out_file_des) + + if (reset_time_flag) + set_file_times (in_file_des, file_hdr.c_name, file_hdr.c_mtime, +- file_hdr.c_mtime); ++ file_hdr.c_mtime, 0); + if (close (in_file_des) < 0) + close_error (header->c_name); + } +@@ -725,7 +725,7 @@ process_copy_out (void) + if (reset_time_flag) + set_file_times (in_file_des, + orig_file_name, +- file_stat.st_atime, file_stat.st_mtime); ++ file_stat.st_atime, file_stat.st_mtime, 0); + if (close (in_file_des) < 0) + close_error (orig_file_name); + break; +diff --git a/src/copypass.c b/src/copypass.c +index a8280ae..09ffebb 100644 +--- a/src/copypass.c ++++ b/src/copypass.c +@@ -193,11 +193,13 @@ process_copy_pass (void) + set_file_times (in_file_des, + input_name.ds_string, + in_file_stat.st_atime, +- in_file_stat.st_mtime); ++ in_file_stat.st_mtime, ++ 0); + set_file_times (out_file_des, + output_name.ds_string, + in_file_stat.st_atime, +- in_file_stat.st_mtime); ++ in_file_stat.st_mtime, ++ 0); + } + + if (close (in_file_des) < 0) +@@ -300,6 +302,11 @@ process_copy_pass (void) + && errno != EPERM) + chown_error_details (output_name.ds_string, uid, gid); + } ++ ++ if (retain_time_flag) ++ set_file_times (-1, output_name.ds_string, ++ in_file_stat.st_atime, in_file_stat.st_mtime, ++ AT_SYMLINK_NOFOLLOW); + free (link_name); + } + #endif +diff --git a/src/extern.h b/src/extern.h +index 6afbdd2..d7c31b4 100644 +--- a/src/extern.h ++++ b/src/extern.h +@@ -204,7 +204,7 @@ void write_nuls_to_file (off_t num_bytes, int out_des, + + void set_perms (int fd, struct cpio_file_stat *header); + void set_file_times (int fd, const char *name, unsigned long atime, +- unsigned long mtime); ++ unsigned long mtime, int atflag); + void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st); + void cpio_to_stat (struct stat *st, struct cpio_file_stat *hdr); + void cpio_safer_name_suffix (char *name, bool link_target, +diff --git a/src/util.c b/src/util.c +index 7415e10..bc1ffb8 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -1235,12 +1235,13 @@ set_perms (int fd, struct cpio_file_stat *header) + if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0) + chmod_error_details (header->c_name, header->c_mode); + if (retain_time_flag) +- set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime); ++ set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime, 0); + } + + void + set_file_times (int fd, +- const char *name, unsigned long atime, unsigned long mtime) ++ const char *name, unsigned long atime, unsigned long mtime, ++ int atflag) + { + struct timespec ts[2]; + +@@ -1251,7 +1252,7 @@ set_file_times (int fd, + + /* Silently ignore EROFS because reading the file won't have upset its + timestamp if it's on a read-only filesystem. */ +- if (fdutimens (fd, name, ts) < 0 && errno != EROFS) ++ if (fdutimensat (fd, AT_FDCWD, name, ts, atflag) < 0 && errno != EROFS) + utime_error (name); + } + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 52503c9..28e259e 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -57,7 +57,9 @@ TESTSUITE_AT = \ + version.at\ + big-block-size.at\ + CVE-2015-1197.at\ +- CVE-2019-14866.at ++ CVE-2019-14866.at\ ++ linktime.at\ ++ linktime01.at + + TESTSUITE = $(srcdir)/testsuite + +diff --git a/tests/testsuite.at b/tests/testsuite.at +index c58cbb7..4dd2afc 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -45,3 +45,6 @@ m4_include([big-block-size.at]) + + m4_include([CVE-2015-1197.at]) + m4_include([CVE-2019-14866.at]) ++ ++m4_include([linktime.at]) ++m4_include([linktime01.at]) +diff --git a/m4/futimens.m4 b/m4/futimens.m4 +new file mode 100644 +index 0000000..dc0b21b +--- /dev/null ++++ b/m4/futimens.m4 +@@ -0,0 +1,69 @@ ++# serial 11 ++# See if we need to provide futimens replacement. ++ ++dnl Copyright (C) 2009-2023 Free Software Foundation, Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++# Written by Eric Blake. ++ ++AC_DEFUN([gl_FUNC_FUTIMENS], ++[ ++ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) ++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles ++ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) ++ gl_CHECK_FUNCS_ANDROID([futimens], [[#include ]]) ++ if test $ac_cv_func_futimens = no; then ++ HAVE_FUTIMENS=0 ++ case "$gl_cv_onwards_func_futimens" in ++ future*) REPLACE_FUTIMENS=1 ;; ++ esac ++ else ++ AC_CACHE_CHECK([whether futimens works], ++ [gl_cv_func_futimens_works], ++ [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ ++#include ++#include ++#include ++#include ++]GL_MDA_DEFINES], ++ [[struct timespec ts[2]; ++ int fd = creat ("conftest.file", 0600); ++ struct stat st; ++ if (fd < 0) return 1; ++ ts[0].tv_sec = 1; ++ ts[0].tv_nsec = UTIME_OMIT; ++ ts[1].tv_sec = 1; ++ ts[1].tv_nsec = UTIME_NOW; ++ errno = 0; ++ if (futimens (AT_FDCWD, NULL) == 0) return 2; ++ if (errno != EBADF) return 3; ++ if (futimens (fd, ts)) return 4; ++ sleep (1); ++ ts[0].tv_nsec = UTIME_NOW; ++ ts[1].tv_nsec = UTIME_OMIT; ++ if (futimens (fd, ts)) return 5; ++ if (fstat (fd, &st)) return 6; ++ if (st.st_ctime < st.st_atime) return 7; ++ ]])], ++ [gl_cv_func_futimens_works=yes], ++ [gl_cv_func_futimens_works=no], ++ [case "$host_os" in ++ # Guess no on glibc systems. ++ *-gnu* | gnu*) gl_cv_func_futimens_works="guessing no" ;; ++ # Guess no on musl systems. ++ *-musl*) gl_cv_func_futimens_works="guessing no" ;; ++ # Guess yes otherwise. ++ *) gl_cv_func_futimens_works="guessing yes" ;; ++ esac ++ ]) ++ rm -f conftest.file]) ++ case "$gl_cv_func_futimens_works" in ++ *yes) ;; ++ *) ++ REPLACE_FUTIMENS=1 ++ ;; ++ esac ++ fi ++]) +diff --git a/tests/linktime.at b/tests/linktime.at +new file mode 100644 +index 0000000..bcee241 +--- /dev/null ++++ b/tests/linktime.at +@@ -0,0 +1,63 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Copyright (C) 2023 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 ++# the Free Software Foundation; either version 3, or (at your option) ++# any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License along ++# with this program. If not, see . ++ ++AT_SETUP([restoring symlink times]) ++AT_KEYWORDS([linktime copyin copypass]) ++ ++AT_DATA([filelist],[file ++symlink ++]) ++ ++AT_DATA([filelist_rev],[symlink ++file ++]) ++ ++AT_CHECK( ++[mkdir dir ++cd dir ++genfile --file file ++ln -s file symlink || AT_SKIP_TEST ++genfile -th --date '2 days ago' symlink || AT_SKIP_TEST ++cd .. ++]) ++ ++AT_CHECK( ++[time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++]) ++ ++AT_CHECK( ++[time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist_rev > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++]) ++ ++AT_CHECK( ++[time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir -m --quiet -p . < filelist ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++]) ++ ++AT_CLEANUP +diff --git a/tests/linktime01.at b/tests/linktime01.at +new file mode 100644 +index 0000000..9caa58f +--- /dev/null ++++ b/tests/linktime01.at +@@ -0,0 +1,51 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Copyright (C) 2023 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 ++# the Free Software Foundation; either version 3, or (at your option) ++# any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License along ++# with this program. If not, see . ++ ++AT_SETUP([restoring delayed symlink times]) ++AT_KEYWORDS([linktime copyin]) ++ ++AT_CHECK( ++[mkdir dir ++genfile --file dir/file1 ++ln -s dir dirlink || AT_SKIP_TEST ++genfile -th --date '2 days ago' dirlink || AT_SKIP_TEST ++]) ++ ++AT_DATA([filelist], ++[dir ++dir/file1 ++dirlink ++]) ++ ++AT_CHECK( ++[time_orig=$(genfile -h -Smtime dirlink) ++cpio --quiet -o < filelist > arc.cpio ++mkdir extr ++cpio -D extr --quiet --no-absolute-filenames -m -i < arc.cpio ++find extr | sort ++time=$(genfile -h -Smtime extr/dirlink) ++test "$time" -eq "$time_orig" ++], ++[0], ++[extr ++extr/dir ++extr/dir/file1 ++extr/dirlink ++]) ++ ++AT_CLEANUP ++ ++ +diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 +index ad10592..fa0c93e 100644 +--- a/m4/gnulib-comp.m4 ++++ b/m4/gnulib-comp.m4 +@@ -98,6 +98,7 @@ AC_DEFUN([gl_EARLY], + # Code from module fd-hook: + # Code from module fd-safer-flag: + # Code from module fdopendir: ++ # Code from module fdutimensat: + # Code from module fileblocks: + # Code from module filename: + # Code from module filenamecat-lgpl: +@@ -114,6 +115,7 @@ AC_DEFUN([gl_EARLY], + # Code from module fstat: + # Code from module fstatat: + # Code from module full-write: ++ # Code from module futimens: + # Code from module gen-header: + # Code from module getcwd: + # Code from module getcwd-lgpl: +@@ -411,6 +413,7 @@ AC_DEFUN([gl_INIT], + [test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1]) + gl_DIRENT_MODULE_INDICATOR([fdopendir]) + gl_MODULE_INDICATOR([fdopendir]) ++ gl_MODULE_INDICATOR([fdutimensat]) + gl_FILEBLOCKS + gl_CONDITIONAL([GL_COND_OBJ_FILEBLOCKS], + [test $ac_cv_member_struct_stat_st_blocks = no]) +@@ -475,6 +478,10 @@ AC_DEFUN([gl_INIT], + gl_CONDITIONAL([GL_COND_OBJ_FSTATAT], + [test $HAVE_FSTATAT = 0 || test $REPLACE_FSTATAT = 1]) + gl_SYS_STAT_MODULE_INDICATOR([fstatat]) ++ gl_FUNC_FUTIMENS ++ gl_CONDITIONAL([GL_COND_OBJ_FUTIMENS], ++ [test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1]) ++ gl_SYS_STAT_MODULE_INDICATOR([futimens]) + gl_FUNC_GETCWD + gl_CONDITIONAL([GL_COND_OBJ_GETCWD], [test $REPLACE_GETCWD = 1]) + AM_COND_IF([GL_COND_OBJ_GETCWD], [ +@@ -1278,6 +1285,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/fd-safer-flag.c + lib/fd-safer.c + lib/fdopendir.c ++ lib/fdutimensat.c + lib/fileblocks.c + lib/filename.h + lib/filenamecat-lgpl.c +@@ -1298,6 +1306,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/fstatat.c + lib/full-write.c + lib/full-write.h ++ lib/futimens.c + lib/getcwd-lgpl.c + lib/getcwd.c + lib/getdelim.c +@@ -1556,6 +1565,7 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/fseeko.m4 + m4/fstat.m4 + m4/fstatat.m4 ++ m4/futimens.m4 + m4/getcwd-abort-bug.m4 + m4/getcwd-path-max.m4 + m4/getcwd.m4 +diff --git a/aclocal.m4 b/aclocal.m4 +index ce55bc1..d5bd65f 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -1241,6 +1241,7 @@ m4_include([m4/fseek.m4]) + m4_include([m4/fseeko.m4]) + m4_include([m4/fstat.m4]) + m4_include([m4/fstatat.m4]) ++m4_include([m4/futimens.m4]) + m4_include([m4/getcwd-abort-bug.m4]) + m4_include([m4/getcwd-path-max.m4]) + m4_include([m4/getcwd.m4]) +diff --git a/gnu/fdutimensat.c b/gnu/fdutimensat.c +new file mode 100644 +index 0000000..5b801e0 +--- /dev/null ++++ b/gnu/fdutimensat.c +@@ -0,0 +1,57 @@ ++/* Set file access and modification times. ++ ++ Copyright (C) 2009-2023 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 the ++ Free Software Foundation, either version 3 of the License, or any ++ later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Eric Blake. */ ++ ++/* derived from a function in utimens.c */ ++ ++#include ++ ++#include "utimens.h" ++ ++#include ++#include ++#include ++ ++/* Set the access and modification timestamps of FD (a.k.a. FILE) to be ++ TIMESPEC[0] and TIMESPEC[1], respectively; relative to directory DIR. ++ FD must be either negative -- in which case it is ignored -- ++ or a file descriptor that is open on FILE. ++ If FD is nonnegative, then FILE can be NULL, which means ++ use just futimes (or equivalent) instead of utimes (or equivalent), ++ and fail if on an old system without futimes (or equivalent). ++ If TIMESPEC is null, set the timestamps to the current time. ++ ATFLAG is passed to utimensat if FD is negative or futimens was ++ unsupported, which can allow operation on FILE as a symlink. ++ Return 0 on success, -1 (setting errno) on failure. */ ++ ++int ++fdutimensat (int fd, int dir, char const *file, struct timespec const ts[2], ++ int atflag) ++{ ++ int result = 1; ++ if (0 <= fd) ++ result = futimens (fd, ts); ++ if (file && (fd < 0 || (result == -1 && errno == ENOSYS))) ++ result = utimensat (dir, file, ts, atflag); ++ if (result == 1) ++ { ++ errno = EBADF; ++ result = -1; ++ } ++ return result; ++} +diff --git a/gnu/futimens.c b/gnu/futimens.c +new file mode 100644 +index 0000000..5bb3049 +--- /dev/null ++++ b/gnu/futimens.c +@@ -0,0 +1,37 @@ ++/* Set the access and modification time of an open fd. ++ Copyright (C) 2009-2023 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation, either version 3 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* written by Eric Blake */ ++ ++#include ++ ++#include ++ ++#include "utimens.h" ++ ++/* Set the access and modification timestamps of FD to be ++ TIMESPEC[0] and TIMESPEC[1], respectively. ++ Fail with ENOSYS on systems without futimes (or equivalent). ++ If TIMESPEC is null, set the timestamps to the current time. ++ Return 0 on success, -1 (setting errno) on failure. */ ++int ++futimens (int fd, struct timespec const times[2]) ++{ ++ /* fdutimens also works around bugs in native futimens, when running ++ with glibc compiled against newer headers but on a Linux kernel ++ older than 2.6.32. */ ++ return fdutimens (fd, NULL, times); ++} +diff --git a/tests/genfile.c b/tests/genfile.c +index be4a2d3..0074c5c 100644 +--- a/tests/genfile.c ++++ b/tests/genfile.c +@@ -77,7 +77,8 @@ enum genfile_mode + mode_generate, + mode_sparse, + mode_stat, +- mode_exec ++ mode_exec, ++ mode_set_times + }; + + enum genfile_mode mode = mode_generate; +@@ -106,6 +107,9 @@ int verbose; + /* Quiet mode */ + int quiet; + ++/* Don't dereference symlinks (for --stat) */ ++int no_dereference_option; ++ + const char *argp_program_version = "genfile (" PACKAGE ") " VERSION; + const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; + static char doc[] = N_("genfile manipulates data files for GNU paxutils test suite.\n" +@@ -155,6 +159,14 @@ static struct argp_option options[] = { + N_("Print contents of struct stat for each given file. Default FORMAT is: ") + DEFAULT_STAT_FORMAT, + GRP+1 }, ++ {"no-dereference", 'h', NULL, 0, ++ N_("stat symbolic links instead of referenced files"), ++ GRP+1 }, ++ ++ {"set-times", 't', NULL, 0, ++ N_("Set access and modification times of the files to the time supplied" ++ " by --date option"), ++ GRP+1 }, + + #undef GRP + #define GRP 20 +@@ -348,6 +360,14 @@ parse_opt (int key, char *arg, struct argp_state *state) + stat_format = arg; + break; + ++ case 't': ++ mode = mode_set_times; ++ break; ++ ++ case 'h': ++ no_dereference_option = 1; ++ break; ++ + case 'r': + mode = mode_exec; + checkpoint_granularity = arg ? arg : "1"; +@@ -647,7 +667,7 @@ print_stat (const char *name) + char *fmt, *p; + struct stat st; + +- if (stat (name, &st)) ++ if ((no_dereference_option ? lstat : stat) (name, &st)) + { + error (0, errno, _("stat(%s) failed"), name); + return; +@@ -725,6 +745,17 @@ print_stat (const char *name) + free (fmt); + } + ++void ++set_times (char const *name) ++{ ++ struct timespec ts[2]; ++ ++ ts[0] = ts[1] = touch_time; ++ if (utimensat (AT_FDCWD, name, ts, no_dereference_option ? AT_SYMLINK_NOFOLLOW : 0) != 0) ++ { ++ error (EXIT_FAILURE, errno, _("cannot set time on `%s'"), name); ++ } ++} + + /* Exec Mode */ + +@@ -740,7 +771,7 @@ exec_checkpoint (struct action *p) + struct timespec ts[2]; + + ts[0] = ts[1] = p->ts; +- if (utimensat (AT_FDCWD, p->name, ts, 0) != 0) ++ if (utimensat (AT_FDCWD, p->name, ts, no_dereference_option ? AT_SYMLINK_NOFOLLOW : 0) != 0) + { + error (0, errno, _("cannot set time on `%s'"), p->name); + break; +@@ -987,6 +1018,14 @@ main (int argc, char **argv) + print_stat (*argv++); + break; + ++ case mode_set_times: ++ if (argc == 0) ++ error (EXIT_USAGE, 0, _("--set-times requires file names")); ++ ++ while (argc--) ++ set_times (*argv++); ++ break; ++ + case mode_sparse: + generate_sparse_file (argc, argv); + verify_file (file_name); +diff --git a/tests/testsuite b/tests/testsuite +index 10531d1..442ab00 100755 +--- a/tests/testsuite ++++ b/tests/testsuite +@@ -625,6 +625,8 @@ at_help_all="1;version.at:19;cpio version;; + 13;big-block-size.at:17;big block size;block integer overflow; + 14;CVE-2015-1197.at:17;CVE-2015-1197 (--no-absolute-filenames for symlinks);; + 15;CVE-2019-14866.at:17;CVE-2019-14866 (tar header size overflow);; ++16;linktime.at:17;restoring symlink times;linktime copyin copypass; ++17;linktime01.at:17;restoring delayed symlink times;linktime copyin; + " + # List of the all the test groups. + at_groups_all=`printf "%s\n" "$at_help_all" | sed 's/;.*//'` +@@ -638,7 +640,7 @@ at_fn_validate_ranges () + for at_grp + do + eval at_value=\$$at_grp +- if test $at_value -lt 1 || test $at_value -gt 15; then ++ if test $at_value -lt 1 || test $at_value -gt 17; then + printf "%s\n" "invalid test group: $at_value" >&2 + exit 1 + fi +@@ -2940,3 +2942,209 @@ $at_traceon; } + ) 5>&1 2>&1 7>&- | eval $at_tee_pipe + read at_status <"$at_status_file" + #AT_STOP_15 ++#AT_START_16 ++at_fn_group_banner 16 'linktime.at:17' \ ++ "restoring symlink times" " " ++at_xfail=no ++( ++ printf "%s\n" "16. $at_setup_line: testing $at_desc ..." ++ $at_traceon ++ ++ ++ ++cat >filelist <<'_ATEOF' ++file ++symlink ++_ATEOF ++ ++ ++cat >filelist_rev <<'_ATEOF' ++symlink ++file ++_ATEOF ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime.at:28: mkdir dir ++cd dir ++genfile --file file ++ln -s file symlink || exit 77 ++genfile -th --date '2 days ago' symlink || exit 77 ++cd .. ++" ++at_fn_check_prepare_notrace 'an embedded newline' "linktime.at:28" ++( $at_check_trace; mkdir dir ++cd dir ++genfile --file file ++ln -s file symlink || exit 77 ++genfile -th --date '2 days ago' symlink || exit 77 ++cd .. ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++at_fn_diff_devnull "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime.at:28" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime.at:37: time_orig=\$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=\$(genfile -h -Smtime symlink) ++test \"\$time\" -eq \"\$time_orig\" ++" ++at_fn_check_prepare_notrace 'a $(...) command substitution' "linktime.at:37" ++( $at_check_trace; time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++at_fn_diff_devnull "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime.at:37" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime.at:46: time_orig=\$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist_rev > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=\$(genfile -h -Smtime symlink) ++test \"\$time\" -eq \"\$time_orig\" ++" ++at_fn_check_prepare_notrace 'a $(...) command substitution' "linktime.at:46" ++( $at_check_trace; time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir --quiet -o < filelist_rev > arc.cpio ++cpio -m --quiet -i < arc.cpio ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++at_fn_diff_devnull "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime.at:46" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime.at:55: time_orig=\$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir -m --quiet -p . < filelist ++time=\$(genfile -h -Smtime symlink) ++test \"\$time\" -eq \"\$time_orig\" ++" ++at_fn_check_prepare_notrace 'a $(...) command substitution' "linktime.at:55" ++( $at_check_trace; time_orig=$(genfile -h -Smtime dir/symlink) ++rm -f file symlink ++cpio -D dir -m --quiet -p . < filelist ++time=$(genfile -h -Smtime symlink) ++test "$time" -eq "$time_orig" ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++at_fn_diff_devnull "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime.at:55" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++ set +x ++ $at_times_p && times >"$at_times_file" ++) 5>&1 2>&1 7>&- | eval $at_tee_pipe ++read at_status <"$at_status_file" ++#AT_STOP_16 ++#AT_START_17 ++at_fn_group_banner 17 'linktime01.at:17' \ ++ "restoring delayed symlink times" " " ++at_xfail=no ++( ++ printf "%s\n" "17. $at_setup_line: testing $at_desc ..." ++ $at_traceon ++ ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime01.at:20: mkdir dir ++genfile --file dir/file1 ++ln -s dir dirlink || exit 77 ++genfile -th --date '2 days ago' dirlink || exit 77 ++" ++at_fn_check_prepare_notrace 'an embedded newline' "linktime01.at:20" ++( $at_check_trace; mkdir dir ++genfile --file dir/file1 ++ln -s dir dirlink || exit 77 ++genfile -th --date '2 days ago' dirlink || exit 77 ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++at_fn_diff_devnull "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime01.at:20" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++cat >filelist <<'_ATEOF' ++dir ++dir/file1 ++dirlink ++_ATEOF ++ ++ ++{ set +x ++printf "%s\n" "$at_srcdir/linktime01.at:33: time_orig=\$(genfile -h -Smtime dirlink) ++cpio --quiet -o < filelist > arc.cpio ++mkdir extr ++cpio -D extr --quiet --no-absolute-filenames -m -i < arc.cpio ++find extr | sort ++time=\$(genfile -h -Smtime extr/dirlink) ++test \"\$time\" -eq \"\$time_orig\" ++" ++at_fn_check_prepare_notrace 'a $(...) command substitution' "linktime01.at:33" ++( $at_check_trace; time_orig=$(genfile -h -Smtime dirlink) ++cpio --quiet -o < filelist > arc.cpio ++mkdir extr ++cpio -D extr --quiet --no-absolute-filenames -m -i < arc.cpio ++find extr | sort ++time=$(genfile -h -Smtime extr/dirlink) ++test "$time" -eq "$time_orig" ++ ++) >>"$at_stdout" 2>>"$at_stderr" 5>&- ++at_status=$? at_failed=false ++$at_check_filter ++at_fn_diff_devnull "$at_stderr" || at_failed=: ++echo >>"$at_stdout"; printf "%s\n" "extr ++extr/dir ++extr/dir/file1 ++extr/dirlink ++" | \ ++ $at_diff - "$at_stdout" || at_failed=: ++at_fn_check_status 0 $at_status "$at_srcdir/linktime01.at:33" ++$at_failed && at_fn_log_failure ++$at_traceon; } ++ ++ ++ set +x ++ $at_times_p && times >"$at_times_file" ++) 5>&1 2>&1 7>&- | eval $at_tee_pipe ++read at_status <"$at_status_file" ++#AT_STOP_17 diff --git a/cpio-2.9-rh.patch b/cpio-2.14-rh.patch similarity index 87% rename from cpio-2.9-rh.patch rename to cpio-2.14-rh.patch index 23d70db..ff4c7cd 100644 --- a/cpio-2.9-rh.patch +++ b/cpio-2.14-rh.patch @@ -3,10 +3,10 @@ Date: Mon, 14 Sep 2015 09:27:21 +0200 Subject: [PATCH 1/7] make '-c' equivalent to '-H newc' diff --git a/doc/cpio.texi b/doc/cpio.texi -index e631934..a788b5d 100644 +index edf0c12..bef7ba5 100644 --- a/doc/cpio.texi +++ b/doc/cpio.texi -@@ -261,7 +261,8 @@ Sets the I/O block size to @var{block-size} * 512 bytes. +@@ -271,7 +271,8 @@ Sets the I/O block size to @var{block-size} * 512 bytes. @item -B Set the I/O block size to 5120 bytes. @item -c @@ -16,7 +16,7 @@ index e631934..a788b5d 100644 @item -C @var{number} @itemx --io-size=@var{number} Set the I/O block size to the given @var{number} of bytes. -@@ -343,7 +344,8 @@ Equivalent to @option{-sS}. +@@ -354,7 +355,8 @@ Equivalent to @option{-sS}. @item -B Set the I/O block size to 5120 bytes. @item -c @@ -26,7 +26,7 @@ index e631934..a788b5d 100644 @item -C @var{number} @itemx --io-size=@var{number} Set the I/O block size to the given @var{number} of bytes. -@@ -454,7 +456,8 @@ Sets the I/O block size to @var{block-size} * 512 bytes. +@@ -465,7 +467,8 @@ Sets the I/O block size to @var{block-size} * 512 bytes. @item -B Set the I/O block size to 5120 bytes. @item -c @@ -36,7 +36,7 @@ index e631934..a788b5d 100644 @item -C @var{number} @itemx --io-size=@var{number} Set the I/O block size to the given @var{number} of bytes. -@@ -600,7 +603,8 @@ block size is 512 bytes. +@@ -614,7 +617,8 @@ block size is 512 bytes. @item -c [@ref{copy-in},@ref{copy-out},@ref{copy-pass}] @@ -47,7 +47,7 @@ index e631934..a788b5d 100644 @item -C @var{io-size} @itemx --io-size=@var{io-size} diff --git a/src/main.c b/src/main.c -index a13861f..a875a13 100644 +index b27bd17..542a71f 100644 --- a/src/main.c +++ b/src/main.c @@ -124,7 +124,7 @@ static struct argp_option options[] = { @@ -56,10 +56,10 @@ index a13861f..a875a13 100644 {NULL, 'c', NULL, 0, - N_("Use the old portable (ASCII) archive format"), GRID+1 }, + N_("Identical to \"-H newc\", use the new (SVR4) portable format. If you wish the old portable (ASCII) archive format, use \"-H odc\" instead."), GRID+1 }, - {"dot", 'V', NULL, 0, + {"dot", 'V', NULL, 0, N_("Print a \".\" for each file processed"), GRID+1 }, {"io-size", 'C', N_("NUMBER"), 0, -@@ -329,6 +329,7 @@ parse_opt (int key, char *arg, struct argp_state *state) +@@ -331,6 +331,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'c': /* Use the old portable ASCII format. */ if (archive_format != arf_unknown) USAGE_ERROR ((0, 0, _("Archive format multiply defined"))); diff --git a/cpio.spec b/cpio.spec index 91a5136..4dc5b7b 100644 --- a/cpio.spec +++ b/cpio.spec @@ -1,7 +1,7 @@ Summary: A GNU archiving program Name: cpio -Version: 2.13 -Release: 14%{?dist} +Version: 2.14 +Release: 1%{?dist} License: GPL-3.0-or-later URL: https://www.gnu.org/software/cpio/ Source: https://ftp.gnu.org/gnu/cpio/cpio-%{version}.tar.bz2 @@ -10,16 +10,16 @@ Source: https://ftp.gnu.org/gnu/cpio/cpio-%{version}.tar.bz2 Source1: cpio.1 # We use SVR4 portable format as default. -Patch1: cpio-2.9-rh.patch +Patch1: cpio-2.14-rh.patch # fix warn_if_file_changed() and set exit code to 1 when cpio fails to store # file > 4GB (#183224) # http://lists.gnu.org/archive/html/bug-cpio/2006-11/msg00000.html -Patch2: cpio-2.13-exitCode.patch +Patch2: cpio-2.14-exitCode.patch # Support major/minor device numbers over 127 (bz#450109) # http://lists.gnu.org/archive/html/bug-cpio/2008-07/msg00000.html -Patch3: cpio-2.13-dev_number.patch +Patch3: cpio-2.14-dev_number.patch # Define default remote shell as /usr/bin/ssh (#452904) Patch4: cpio-2.9.90-defaultremoteshell.patch @@ -27,7 +27,7 @@ Patch4: cpio-2.9.90-defaultremoteshell.patch # Fix segfault with nonexisting file with patternnames (#567022) # http://savannah.gnu.org/bugs/index.php?28954 # We have slightly different solution than upstream. -Patch5: cpio-2.10-patternnamesigsegv.patch +Patch5: cpio-2.14-patternnamesigsegv.patch # Fix bad file name splitting while creating ustar archive (#866467) # (fix backported from tar's source) @@ -36,21 +36,10 @@ Patch7: cpio-2.10-longnames-split.patch # Cpio does Sum32 checksum, not CRC (downstream) Patch8: cpio-2.11-crc-fips-nit.patch -# Fix multiple definition of `program_name' -Patch9: cpio-2.13-mutiple-definition.patch - -# Revert fix for CVE-2015-1197 (#1797163) -# reverts upstream commit 45b0ee2b4 -Patch10: cpio-2.13-revert-CVE-2015-1197-fix.patch - -# Extract: retain times for symlinks -# downstream patch (#1486364) +# Restore access and modification times of symlinks in copy-in and copy-pass modes +# Upstream patch # https://www.mail-archive.com/bug-cpio@gnu.org/msg00605.html -Patch11: cpio-2.11-retain-symlink-times.patch - -# Properly drop priviledges for remote command -# http://git.savannah.gnu.org/cgit/paxutils.git/commit/?id=d247e3c2809a37b6d0c3067251d96bb7f12555e7 -Patch12: cpio-2.13-reset-gid-uid.patch +Patch11: cpio-2.14-restore-access-and-modification-times-of-symlinks.patch Provides: bundled(gnulib) Provides: bundled(paxutils) diff --git a/sources b/sources index 58af22f..be165ed 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (cpio-2.13.tar.bz2) = 459398e69f7f48201c04d1080218c50f75edcf114ffcbb236644ff6fcade5fcc566929bdab2ebe9be5314828d6902e43b348a8adf28351df978c8989590e93a3 +SHA512 (cpio-2.14.tar.bz2) = 2dc93a81e31b6fb7ff9976243d22ca7a84bb396c7ad09e0abfb5d5efae1164ebb319fb89be45045797f8c604b3e3d2ea0746e3cfe559aa86282ea4ec9a17da28