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

</pre>
<p><a href="https://github.com/macports/macports-base/commit/a2cd63474d55226d343633074b4dd2bd9a1b789c">https://github.com/macports/macports-base/commit/a2cd63474d55226d343633074b4dd2bd9a1b789c</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit a2cd63474d55226d343633074b4dd2bd9a1b789c
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Tue Oct 8 02:25:05 2024 +1100

<span style='display:block; white-space:pre;color:#404040;'>    Attempt to work around lseek SEEK_HOLE bug
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Closes: https://trac.macports.org/ticket/67336
</span><span style='display:block; white-space:pre;color:#404040;'>    (cherry picked from commit af49e244c2e0d33e08fc32058efc90c29f299170)
</span>---
 src/pextlib1.0/Pextlib.c     | 49 ++++++++++++++++++++++++++++++++++++++++++++
 src/port1.0/portdestroot.tcl | 17 +++++++++++++++
 2 files changed, 66 insertions(+)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/Pextlib.c b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 4d0ccadcc..7326ef0ba 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1150,6 +1150,54 @@ int ClonefileCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl
</span>     return TCL_ERROR;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static int fileIsSparseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef SEEK_HOLE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const char *path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat st;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    off_t end_offset;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    off_t hole_offset;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (objc != 2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_WrongNumArgs(interp, 1, objv, "filename");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</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;'>+    path = Tcl_GetString(objv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == lstat(path, &st)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* an error occurred */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetErrno(errno);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_ResetResult(interp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_AppendResult(interp, "lstat(", path, "):", (char *)Tcl_PosixError(interp), NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!S_ISREG(st.st_mode)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* not a regular file, haven't seen directories which are sparse yet */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((fd = open(path, O_RDONLY)) < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetErrno(errno);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_ResetResult(interp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_AppendResult(interp, "open(", path, "): ", (char *)Tcl_PosixError(interp), NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</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;'>+    lseek(fd, 0, SEEK_SET);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    hole_offset = lseek(fd, 0, SEEK_HOLE);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    end_offset = lseek(fd, 0, SEEK_END);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    close(fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (hole_offset >= 0 && end_offset >= 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        && hole_offset < end_offset) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* SEEK_HOLE */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> int Pextlib_Init(Tcl_Interp *interp)
 {
     if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1184,6 +1232,7 @@ int Pextlib_Init(Tcl_Interp *interp)
</span> #ifdef __MACH__
     Tcl_CreateObjCommand(interp, "fileIsBinary", fileIsBinaryCmd, NULL, NULL);
 #endif
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    Tcl_CreateObjCommand(interp, "fileIsSparse", fileIsSparseCmd, NULL, NULL);
</span> 
     Tcl_CreateObjCommand(interp, "readline", ReadlineCmd, NULL, NULL);
     Tcl_CreateObjCommand(interp, "rl_history", RLHistoryCmd, NULL, NULL);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/port1.0/portdestroot.tcl b/src/port1.0/portdestroot.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 0ebf48732..872b61e3b 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/port1.0/portdestroot.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/port1.0/portdestroot.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -371,6 +371,23 @@ proc portdestroot::destroot_finish {args} {
</span>         ui_warn "[format [msgcat::mc "%s installs files outside the common directory structure."] $subport]"
     }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    # Work around apparent filesystem bug.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # https://trac.macports.org/ticket/67336
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[fs_clone_capable $destroot]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        global workpath
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ui_debug "Applying sparse file lseek bug workaround"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fs-traverse -depth fullpath [list $destroot] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[file type $fullpath] eq "file" && [fileIsSparse $fullpath]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ui_debug "Cloning $fullpath for workaround"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                clonefile $fullpath ${workpath}/.macports-sparse-workaround
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                file delete ${workpath}/.macports-sparse-workaround
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {![fileIsSparse $fullpath]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ui_debug "$fullpath is no longer sparse"
</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;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     # Restore umask
     umask $oldmask
 
</pre><pre style='margin:0'>

</pre>