<pre style='margin:0'>
Clemens Lang (neverpanic) pushed a commit to branch master
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/3b949ccfe7a309bce1cc7041cdf56871890b784d">https://github.com/macports/macports-base/commit/3b949ccfe7a309bce1cc7041cdf56871890b784d</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'> new 3b949ccf pextlib1.0: Fix mtime restore in lazy_copy()
</span>3b949ccf is described below
<span style='display:block; white-space:pre;color:#808000;'>commit 3b949ccfe7a309bce1cc7041cdf56871890b784d
</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>---
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(×[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>