<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch release-2.7
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/5b7b37cacfa1f43c31767ccf734f5c98e29df5ee">https://github.com/macports/macports-base/commit/5b7b37cacfa1f43c31767ccf734f5c98e29df5ee</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 5b7b37cacfa1f43c31767ccf734f5c98e29df5ee
</span>Author: Clemens Lang <cal@macports.org>
AuthorDate: Fri Jan 28 19:02:08 2022 +0100

<span style='display:block; white-space:pre;color:#404040;'>    pextlib1.0: Fix mtime restore in lazy_copy()
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    On newer versions of macOS, Apple's implementation of copyfile(3) no
</span><span style='display:block; white-space:pre;color:#404040;'>    longer restores the file's modification time when copying
</span><span style='display:block; white-space:pre;color:#404040;'>    a SIP-protected file with COPYFILE_STAT (or COPYFILE_ALL, which should
</span><span style='display:block; white-space:pre;color:#404040;'>    include COPYFILE_STAT). I have not tested whether this is a general
</span><span style='display:block; white-space:pre;color:#404040;'>    problem with copyfile(3), or just a problem when copying SIP-protected
</span><span style='display:block; white-space:pre;color:#404040;'>    files.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Because lazy_copy() uses the destination file's mtime to determine
</span><span style='display:block; white-space:pre;color:#404040;'>    whether a new copy of the file is needed, this meant that recently every
</span><span style='display:block; white-space:pre;color:#404040;'>    single invocation of lazy_copy() did in fact make a new copy of the
</span><span style='display:block; white-space:pre;color:#404040;'>    file. This caused trace mode to jump to much higher overhead between
</span><span style='display:block; white-space:pre;color:#404040;'>    6 and 9 times of the normal runtime.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Switch copyfile(3) to explicitly not copying the file's stat information
</span><span style='display:block; white-space:pre;color:#404040;'>    and invoke fchmod(2) and futimes(2) after the copy has been made to
</span><span style='display:block; white-space:pre;color:#404040;'>    ensure that the file modification times are copied as expected.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    (cherry picked from commit 3b949ccfe7a309bce1cc7041cdf56871890b784d)
</span>---
 src/pextlib1.0/sip_copy_proc.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/sip_copy_proc.c b/src/pextlib1.0/sip_copy_proc.c
</span><span style='display:block; white-space:pre;color:#808080;'>index b329ee78..ed8953a9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/sip_copy_proc.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/sip_copy_proc.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -17,7 +17,7 @@
</span>  * 3. Neither the name of The MacPorts Project nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span>  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -342,10 +342,32 @@ static char *lazy_copy(const char *path, struct stat *in_st) {
</span>     // we can safely copy the source file with all metadata.
     // This cannot use COPYFILE_CLONE as it does not follow symlinks,
     // see https://trac.macports.org/ticket/55575
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (copyfile(path, target_path_temp, NULL, COPYFILE_ALL) != 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (copyfile(path, target_path_temp, NULL, COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA | COPYFILE_EXCL) != 0) {
</span>         fprintf(stderr, "sip_copy_proc: copyfile(%s, %s): %s\n", path, target_path_temp, strerror(errno));
         goto lazy_copy_out;
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // Re-open the copied file in outfd, because copyfile(3) with COPYFILE_ALL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // (or COPYFILE_STAT, for that matter) does not seem to copy the file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // creation time correctly, so we need another futimes(2) to fix that.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef O_CLOEXEC
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == (outfd = open(target_path_temp, O_RDWR | O_CLOEXEC))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "sip_copy_proc: open(%s, O_RDWR | O_CLOEXEC): %s\n", target_path_temp, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == (outfd = open(target_path_temp, O_RDWR))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "sip_copy_proc: open(%s, O_RDWR): %s\n", target_path_temp, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        goto lazy_copy_out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // Since we removed COPYFILE_STAT from the copyfile(3) invocation above, we
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // need to restore the permissions on the copy. Note that the futimes(2)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // later on should still succeed even if we remove write permissions here,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    // because we already have a file descriptor open.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == fchmod(outfd, in_st->st_mode)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "sip_copy_proc: fchmod(%s, %o): %s\n", target_path_temp, in_st->st_mode, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        goto lazy_copy_out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span> #else /* !HAVE_COPYFILE */
     // create temporary file to copy into and then later atomically replace
     // target file
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -406,6 +428,7 @@ static char *lazy_copy(const char *path, struct stat *in_st) {
</span>     if (bytes_read < 0 || bytes_written < 0) {
         goto lazy_copy_out;
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* HAVE_COPYFILE */
</span> 
     struct timeval times[2];
     TIMESPEC_TO_TIMEVAL(&times[0], &in_st->st_mtimespec);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -414,7 +437,6 @@ static char *lazy_copy(const char *path, struct stat *in_st) {
</span>         fprintf(stderr, "sip_copy_proc: futimes(%s): %s\n", target_path_temp, strerror(errno));
         goto lazy_copy_out;
     }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#endif /* HAVE_COPYFILE */
</span> 
     if (-1 == rename(target_path_temp, target_path)) {
         fprintf(stderr, "sip_copy_proc: rename(%s, %s): %s\n", target_path_temp, target_path, strerror(errno));
</pre><pre style='margin:0'>

</pre>