Subject: [PATCH] filesys.c: Use scm_sendfile to copy files.

From: Tomas Volf <[email-masked]>
Date: Fri, 28 Feb 2025 02:10:18 +0100

Use scm_sendfile instead of read-write loop.  This moves the work into
the kernel, improving performance.  This implements Ludovic's suggestion
from bug 68504.

* libguile/filesys.c (scm_copy_file2): Use scm_sendfile.
---
 libguile/filesys.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/libguile/filesys.c b/libguile/filesys.c
index 3bfa5eb91..8a05f066f 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1,7 +1,7 @@
 /* Copyright 1996-2002,2004,2006,2009-2019,2021
      Free Software Foundation, Inc.
    Copyright 2021 Maxime Devos <[email-masked]>
-   Copyright 2024 Tomas Volf <[email-masked]>
+   Copyright 2024, 2025 Tomas Volf <[email-masked]>
 
    This file is part of Guile.
 
@@ -1354,13 +1354,18 @@ SCM_DEFINE (scm_copy_file2, "copy-file", 2, 0, 1,
     scm_syserror ("copy-file: copy-on-write failed");
 
   if (clone_res)
-    while ((n = read (oldfd, buf, sizeof buf)) > 0)
-      if (write (newfd, buf, n) != n)
-        {
-          close (oldfd);
-          close (newfd);
-          SCM_SYSERROR;
-        }
+    {
+      off_t end;
+      if ((end = lseek_or_lseek64 (oldfd, 0, SEEK_END)) < 0)
+        SCM_SYSERROR;
+      if (lseek_or_lseek64 (oldfd, 0, SEEK_SET) < 0)
+        SCM_SYSERROR;
+
+      scm_sendfile (scm_from_int (newfd),
+                    scm_from_int (oldfd),
+                    scm_from_off_t (end),
+                    SCM_UNDEFINED);
+    }
   close (oldfd);
   if (close (newfd) == -1)
     SCM_SYSERROR;
-- 
2.48.1