[前][次][番号順一覧][スレッド一覧]

ruby-changes:54713

From: glass <ko1@a...>
Date: Mon, 28 Jan 2019 05:55:31 +0900 (JST)
Subject: [ruby-changes:54713] glass:r66930 (trunk): io.c: use fcopyfile(3) in IO.copy_stream if available

glass	2019-01-28 05:55:26 +0900 (Mon, 28 Jan 2019)

  New Revision: 66930

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66930

  Log:
    io.c: use fcopyfile(3) in IO.copy_stream if available
    
    * io.c (nogvl_copy_stream_func): use fcopyfile(3) in IO.copy_stream if available
    
    * configure.ac: check copyfile.h and fcopyfile(3)

  Modified files:
    trunk/configure.ac
    trunk/io.c
Index: configure.ac
===================================================================
--- configure.ac	(revision 66929)
+++ configure.ac	(revision 66930)
@@ -1029,6 +1029,7 @@ AC_HEADER_SYS_WAIT https://github.com/ruby/ruby/blob/trunk/configure.ac#L1029
 
 AC_CHECK_HEADERS(a.out.h)
 AC_CHECK_HEADERS(atomic.h)
+AC_CHECK_HEADERS(copyfile.h)
 AC_CHECK_HEADERS(direct.h)
 AC_CHECK_HEADERS(grp.h)
 AC_CHECK_HEADERS(fcntl.h)
@@ -1806,6 +1807,7 @@ AC_CHECK_FUNCS(dup3) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1807
 AC_CHECK_FUNCS(eaccess)
 AC_CHECK_FUNCS(endgrent)
 AC_CHECK_FUNCS(eventfd)
+AC_CHECK_FUNCS(fcopyfile)
 AC_CHECK_FUNCS(fchmod)
 AC_CHECK_FUNCS(fchown)
 AC_CHECK_FUNCS(fcntl)
Index: io.c
===================================================================
--- io.c	(revision 66929)
+++ io.c	(revision 66930)
@@ -95,6 +95,10 @@ https://github.com/ruby/ruby/blob/trunk/io.c#L95
 # include <sys/wait.h>		/* for WNOHANG on BSD */
 #endif
 
+#ifdef HAVE_COPYFILE_H
+# include <copyfile.h>
+#endif
+
 #include "ruby/util.h"
 
 #ifndef O_ACCMODE
@@ -10699,6 +10703,9 @@ struct copy_stream_struct { https://github.com/ruby/ruby/blob/trunk/io.c#L10703
     const char *syserr;
     const char *notimp;
     VALUE th;
+#ifdef HAVE_FCOPYFILE
+    copyfile_state_t copyfile_state;
+#endif
 };
 
 static void *
@@ -10954,6 +10961,88 @@ nogvl_copy_file_range(struct copy_stream https://github.com/ruby/ruby/blob/trunk/io.c#L10961
 }
 #endif
 
+#ifdef HAVE_FCOPYFILE
+static int
+nogvl_fcopyfile(struct copy_stream_struct *stp)
+{
+    struct stat sb;
+    off_t src_size, cur, ss = 0;
+    int ret;
+
+    if (stp->copy_length >= (off_t)0) {
+	/* copy_length can't be specified in copyfile(3) */
+	return 0;
+    }
+
+    ret = fstat(stp->src_fd, &sb);
+    if (ret < 0) {
+        stp->syserr = "fstat";
+        stp->error_no = errno;
+        return ret;
+    }
+    if (!S_ISREG(sb.st_mode))
+        return 0;
+
+    src_size = sb.st_size;
+    ret = fstat(stp->dst_fd, &sb);
+    if (ret < 0) {
+        stp->syserr = "fstat";
+        stp->error_no = errno;
+        return ret;
+    }
+    if (!S_ISREG(sb.st_mode))
+        return 0;
+
+    if (stp->src_offset > (off_t)0) {
+        off_t r;
+
+	/* get current offset */
+	errno = 0;
+	cur = lseek(stp->src_fd, 0, SEEK_CUR);
+	if (cur < (off_t)0 && errno) {
+	    stp->error_no = errno;
+            return 1;
+	}
+
+	errno = 0;
+        r = lseek(stp->src_fd, stp->src_offset, SEEK_SET);
+        if (r < (off_t)0 && errno) {
+            stp->error_no = errno;
+            return 1;
+        }
+    }
+
+    stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
+    ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
+    copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
+
+    if (ret == 0) { /* success */
+	stp->total = ss;
+	if (stp->src_offset > (off_t)0) {
+	    off_t r;
+	    errno = 0;
+	    /* reset offset */
+	    r = lseek(stp->src_fd, cur, SEEK_SET);
+	    if (r < (off_t)0 && errno) {
+		stp->error_no = errno;
+		return 1;
+	    }
+	}
+    } else {
+        switch (errno) {
+	  case ENOTSUP:
+	  case EPERM:
+	  case EINVAL:
+            return 0;
+        }
+        stp->syserr = "fcopyfile";
+        stp->error_no = errno;
+        return (int)ret;
+    }
+    return 1;
+}
+#endif
+
 #ifdef HAVE_SENDFILE
 
 # ifdef __linux__
@@ -11263,6 +11352,12 @@ nogvl_copy_stream_func(void *arg) https://github.com/ruby/ruby/blob/trunk/io.c#L11352
 	goto finish; /* error or success */
 #endif
 
+#ifdef HAVE_FCOPYFILE
+    ret = nogvl_fcopyfile(stp);
+    if (ret != 0)
+	goto finish; /* error or success */
+#endif
+
 #ifdef USE_SENDFILE
     ret = nogvl_copy_stream_sendfile(stp);
     if (ret != 0)
@@ -11470,6 +11565,13 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/io.c#L11565
 copy_stream_finalize(VALUE arg)
 {
     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
+
+#ifdef HAVE_FCOPYFILE
+    if (stp->copyfile_state) {
+	copyfile_state_free(stp->copyfile_state);
+    }
+#endif
+
     if (stp->close_src) {
         rb_io_close_m(stp->src);
     }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]