mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66930 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
42921458ff
commit
bd670062c4
2 changed files with 104 additions and 0 deletions
|
@ -1029,6 +1029,7 @@ AC_HEADER_SYS_WAIT
|
||||||
|
|
||||||
AC_CHECK_HEADERS(a.out.h)
|
AC_CHECK_HEADERS(a.out.h)
|
||||||
AC_CHECK_HEADERS(atomic.h)
|
AC_CHECK_HEADERS(atomic.h)
|
||||||
|
AC_CHECK_HEADERS(copyfile.h)
|
||||||
AC_CHECK_HEADERS(direct.h)
|
AC_CHECK_HEADERS(direct.h)
|
||||||
AC_CHECK_HEADERS(grp.h)
|
AC_CHECK_HEADERS(grp.h)
|
||||||
AC_CHECK_HEADERS(fcntl.h)
|
AC_CHECK_HEADERS(fcntl.h)
|
||||||
|
@ -1806,6 +1807,7 @@ AC_CHECK_FUNCS(dup3)
|
||||||
AC_CHECK_FUNCS(eaccess)
|
AC_CHECK_FUNCS(eaccess)
|
||||||
AC_CHECK_FUNCS(endgrent)
|
AC_CHECK_FUNCS(endgrent)
|
||||||
AC_CHECK_FUNCS(eventfd)
|
AC_CHECK_FUNCS(eventfd)
|
||||||
|
AC_CHECK_FUNCS(fcopyfile)
|
||||||
AC_CHECK_FUNCS(fchmod)
|
AC_CHECK_FUNCS(fchmod)
|
||||||
AC_CHECK_FUNCS(fchown)
|
AC_CHECK_FUNCS(fchown)
|
||||||
AC_CHECK_FUNCS(fcntl)
|
AC_CHECK_FUNCS(fcntl)
|
||||||
|
|
102
io.c
102
io.c
|
@ -95,6 +95,10 @@
|
||||||
# include <sys/wait.h> /* for WNOHANG on BSD */
|
# include <sys/wait.h> /* for WNOHANG on BSD */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_COPYFILE_H
|
||||||
|
# include <copyfile.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ruby/util.h"
|
#include "ruby/util.h"
|
||||||
|
|
||||||
#ifndef O_ACCMODE
|
#ifndef O_ACCMODE
|
||||||
|
@ -10699,6 +10703,9 @@ struct copy_stream_struct {
|
||||||
const char *syserr;
|
const char *syserr;
|
||||||
const char *notimp;
|
const char *notimp;
|
||||||
VALUE th;
|
VALUE th;
|
||||||
|
#ifdef HAVE_FCOPYFILE
|
||||||
|
copyfile_state_t copyfile_state;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -10954,6 +10961,88 @@ nogvl_copy_file_range(struct copy_stream_struct *stp)
|
||||||
}
|
}
|
||||||
#endif
|
#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 HAVE_SENDFILE
|
||||||
|
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
|
@ -11263,6 +11352,12 @@ nogvl_copy_stream_func(void *arg)
|
||||||
goto finish; /* error or success */
|
goto finish; /* error or success */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FCOPYFILE
|
||||||
|
ret = nogvl_fcopyfile(stp);
|
||||||
|
if (ret != 0)
|
||||||
|
goto finish; /* error or success */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SENDFILE
|
#ifdef USE_SENDFILE
|
||||||
ret = nogvl_copy_stream_sendfile(stp);
|
ret = nogvl_copy_stream_sendfile(stp);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
@ -11470,6 +11565,13 @@ static VALUE
|
||||||
copy_stream_finalize(VALUE arg)
|
copy_stream_finalize(VALUE arg)
|
||||||
{
|
{
|
||||||
struct copy_stream_struct *stp = (struct copy_stream_struct *)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) {
|
if (stp->close_src) {
|
||||||
rb_io_close_m(stp->src);
|
rb_io_close_m(stp->src);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue