ruby-changes:54717
From: glass <ko1@a...>
Date: Mon, 28 Jan 2019 14:04:22 +0900 (JST)
Subject: [ruby-changes:54717] glass:r66934 (trunk): io.c: use fcopyfile(3) in IO.copy_stream if available
glass 2019-01-28 14:04:17 +0900 (Mon, 28 Jan 2019) New Revision: 66934 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66934 Log: io.c: use fcopyfile(3) in IO.copy_stream if available fixed r66930. * 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 66933) +++ configure.ac (revision 66934) @@ -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 66933) +++ io.c (revision 66934) @@ -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,90 @@ 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 (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */ + 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 +11354,12 @@ nogvl_copy_stream_func(void *arg) https://github.com/ruby/ruby/blob/trunk/io.c#L11354 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) @@ -11471,6 +11568,12 @@ copy_stream_finalize(VALUE arg) https://github.com/ruby/ruby/blob/trunk/io.c#L11568 { 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/