On pátek 31. května 2019 20:00:07 CEST Pavel Raiskup wrote:
> On Thursday, August 23, 2018 3:33:02 PM CEST Pavel Raiskup wrote:
> > Gently ping, interlinking with another (upstream) report:
> > http://lists.gnu.org/archive/html/bug-cpio/2017-12/msg00005.html
> 
> Ping again, I'm continuously asked about this.  Can I do something
> with the patch to make it acceptable?

The previous patch was wrong, as we realized now in
https://src.fedoraproject.org/rpms/cpio/pull-request/19

I'm attaching a new version of this patch that doesn't break the
copypass mode, including a testcase.  I'm going to keep this patch
updated in https://github.com/praiskup/cpio/pull/1

Pavel
>From aad11bcf2059d2eca434715bcbc752bc78851243 Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <prais...@redhat.com>
Date: Wed, 17 May 2023 10:03:07 +0200
Subject: [PATCH] copyin, copypass: retain times for symlinks

Original report by Pat Riehecky at
https://bugzilla.redhat.com/1486364

* src/util.c (set_file_times): When the passed fd == -1, call lutimens()
instead of fdutimens() to actually affect the symlink.
* src/copyin.c (copyin_link): Call set_file_times to restore the symlink
times.
* src/copypass.c (process_copy_pass): Call set_file_times for symlinks,
as well as for other file types.
* tests/retain-times.at: New test file.
* tests/testsuite.at: Link the new test file.
---
 src/copyin.c          |  3 +++
 src/copypass.c        |  4 ++++
 src/util.c            |  6 +++--
 tests/retain-times.at | 53 +++++++++++++++++++++++++++++++++++++++++++
 tests/testsuite.at    |  1 +
 5 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100644 tests/retain-times.at

diff --git a/src/copyin.c b/src/copyin.c
index 2e72356..e2f5e03 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -798,6 +798,9 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des)
 	    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);
   free (link_name);
 }
 
diff --git a/src/copypass.c b/src/copypass.c
index a8280ae..b918896 100644
--- a/src/copypass.c
+++ b/src/copypass.c
@@ -300,6 +300,10 @@ 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);
 	  free (link_name);
 	}
 #endif
diff --git a/src/util.c b/src/util.c
index 7415e10..5c5f7e1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1250,8 +1250,10 @@ set_file_times (int fd,
   ts[1].tv_sec = mtime;
 
   /* 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)
+     timestamp if it's on a read-only filesystem.  When FD == -1, name
+     is a symlink */
+  if ((fd >= 0 ? fdutimens (fd, NULL, ts) : lutimens (name, ts)) < 0
+      && errno != EROFS)
     utime_error (name);
 }
 
diff --git a/tests/retain-times.at b/tests/retain-times.at
new file mode 100644
index 0000000..d40c4a6
--- /dev/null
+++ b/tests/retain-times.at
@@ -0,0 +1,53 @@
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA.
+
+AT_SETUP([retain-times])
+AT_KEYWORDS([symlink copyin copypass])
+
+AT_DATA([filelist],[file
+symlink
+])
+
+AT_CHECK([
+genfile --file file
+ln -s file symlink || AT_SKIP_TEST
+old_time=`stat --format=%Y file symlink` || AT_SKIP_TEST
+echo Creating the archive
+cpio --quiet -o < filelist > archive
+sleep 1
+echo Extracting the archive
+mkdir dir
+cd dir
+cpio -m --quiet -i < ../archive
+find . | sort
+new_time=`stat --format=%Y file symlink`
+test "$old_time" = "$new_time" || echo "copyin: symlink mtime differs"
+cd ..
+cpio -pmvd copypass < filelist 2>/dev/null
+new_time=`stat --format=%Y copypass/file copypass/symlink`
+test "$old_time" = "$new_time" || echo "copypass: symlink mtime differs"
+],
+[0],
+[Creating the archive
+Extracting the archive
+.
+./file
+./symlink
+],[])
+
+AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index c58cbb7..2e434e1 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -45,3 +45,4 @@ m4_include([big-block-size.at])
 
 m4_include([CVE-2015-1197.at])
 m4_include([CVE-2019-14866.at])
+m4_include([retain-times.at])
-- 
2.40.1

Reply via email to