io.c: reuse results of fstat(2) in copy functions

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66994 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
glass 2019-02-03 21:04:04 +00:00
parent 8cca079d3b
commit e3fd9fa403

77
io.c
View File

@ -10703,6 +10703,8 @@ struct copy_stream_struct {
const char *syserr; const char *syserr;
const char *notimp; const char *notimp;
VALUE th; VALUE th;
struct stat src_stat;
struct stat dst_stat;
#ifdef HAVE_FCOPYFILE #ifdef HAVE_FCOPYFILE
copyfile_state_t copyfile_state; copyfile_state_t copyfile_state;
#endif #endif
@ -10854,29 +10856,13 @@ simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offse
static int static int
nogvl_copy_file_range(struct copy_stream_struct *stp) nogvl_copy_file_range(struct copy_stream_struct *stp)
{ {
struct stat sb;
ssize_t ss; ssize_t ss;
off_t src_size; off_t src_size;
int ret;
off_t copy_length, src_offset, *src_offset_ptr; off_t copy_length, src_offset, *src_offset_ptr;
ret = fstat(stp->src_fd, &sb); if (!S_ISREG(stp->src_stat.st_mode))
if (ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return ret;
}
if (!S_ISREG(sb.st_mode))
return 0; 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;
}
src_offset = stp->src_offset; src_offset = stp->src_offset;
if (src_offset >= (off_t)0) { if (src_offset >= (off_t)0) {
src_offset_ptr = &src_offset; src_offset_ptr = &src_offset;
@ -10965,7 +10951,6 @@ nogvl_copy_file_range(struct copy_stream_struct *stp)
static int static int
nogvl_fcopyfile(struct copy_stream_struct *stp) nogvl_fcopyfile(struct copy_stream_struct *stp)
{ {
struct stat sb;
off_t src_size, cur, ss = 0; off_t src_size, cur, ss = 0;
int ret; int ret;
@ -10974,23 +10959,11 @@ nogvl_fcopyfile(struct copy_stream_struct *stp)
return 0; return 0;
} }
ret = fstat(stp->src_fd, &sb); if (!S_ISREG(stp->src_stat.st_mode))
if (ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return ret;
}
if (!S_ISREG(sb.st_mode))
return 0; return 0;
src_size = sb.st_size; src_size = stp->src_stat.st_size;
ret = fstat(stp->dst_fd, &sb); if (!S_ISREG(stp->dst_stat.st_mode))
if (ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return ret;
}
if (!S_ISREG(sb.st_mode))
return 0; return 0;
if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */ if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
return 0; return 0;
@ -11096,32 +11069,18 @@ simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
static int static int
nogvl_copy_stream_sendfile(struct copy_stream_struct *stp) nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
{ {
struct stat sb;
ssize_t ss; ssize_t ss;
int ret;
off_t src_size; off_t src_size;
off_t copy_length; off_t copy_length;
off_t src_offset; off_t src_offset;
int use_pread; int use_pread;
ret = fstat(stp->src_fd, &sb); if (!S_ISREG(stp->src_stat.st_mode))
if (ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return ret;
}
if (!S_ISREG(sb.st_mode))
return 0; return 0;
src_size = sb.st_size; src_size = stp->src_stat.st_size;
ret = fstat(stp->dst_fd, &sb);
if (ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return ret;
}
#ifndef __linux__ #ifndef __linux__
if ((sb.st_mode & S_IFMT) != S_IFSOCK) if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
return 0; return 0;
#endif #endif
@ -11470,6 +11429,7 @@ copy_stream_body(VALUE arg)
src_fd = -1; src_fd = -1;
} }
else { else {
int stat_ret;
VALUE tmp_io = rb_io_check_io(src_io); VALUE tmp_io = rb_io_check_io(src_io);
if (!NIL_P(tmp_io)) { if (!NIL_P(tmp_io)) {
src_io = tmp_io; src_io = tmp_io;
@ -11486,6 +11446,13 @@ copy_stream_body(VALUE arg)
GetOpenFile(src_io, src_fptr); GetOpenFile(src_io, src_fptr);
rb_io_check_byte_readable(src_fptr); rb_io_check_byte_readable(src_fptr);
src_fd = src_fptr->fd; src_fd = src_fptr->fd;
stat_ret = fstat(src_fd, &stp->src_stat);
if (stat_ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return Qnil;
}
} }
stp->src_fd = src_fd; stp->src_fd = src_fd;
@ -11496,7 +11463,8 @@ copy_stream_body(VALUE arg)
dst_fd = -1; dst_fd = -1;
} }
else { else {
VALUE tmp_io = rb_io_check_io(dst_io); int stat_ret;
VALUE tmp_io = rb_io_check_io(dst_io);
if (!NIL_P(tmp_io)) { if (!NIL_P(tmp_io)) {
dst_io = GetWriteIO(tmp_io); dst_io = GetWriteIO(tmp_io);
} }
@ -11517,6 +11485,13 @@ copy_stream_body(VALUE arg)
GetOpenFile(dst_io, dst_fptr); GetOpenFile(dst_io, dst_fptr);
rb_io_check_writable(dst_fptr); rb_io_check_writable(dst_fptr);
dst_fd = dst_fptr->fd; dst_fd = dst_fptr->fd;
stat_ret = fstat(dst_fd, &stp->dst_stat);
if (stat_ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return Qnil;
}
} }
stp->dst_fd = dst_fd; stp->dst_fd = dst_fd;