10489 |
10489 |
return 0;
|
10490 |
10490 |
}
|
10491 |
10491 |
|
|
10492 |
#if defined __linux__ && defined __NR_copy_file_range
|
|
10493 |
# define USE_COPY_FILE_RANGE
|
|
10494 |
#endif
|
|
10495 |
|
|
10496 |
#ifdef USE_COPY_FILE_RANGE
|
|
10497 |
|
|
10498 |
static ssize_t
|
|
10499 |
simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
|
|
10500 |
{
|
|
10501 |
return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
|
|
10502 |
}
|
|
10503 |
|
|
10504 |
static int
|
|
10505 |
nogvl_copy_file_range(struct copy_stream_struct *stp)
|
|
10506 |
{
|
|
10507 |
struct stat src_stat, dst_stat;
|
|
10508 |
ssize_t ss;
|
|
10509 |
int ret;
|
|
10510 |
|
|
10511 |
off_t copy_length, src_offset, *src_offset_ptr;
|
|
10512 |
|
|
10513 |
ret = fstat(stp->src_fd, &src_stat);
|
|
10514 |
if (ret == -1) {
|
|
10515 |
stp->syserr = "fstat";
|
|
10516 |
stp->error_no = errno;
|
|
10517 |
return -1;
|
|
10518 |
}
|
|
10519 |
if (!S_ISREG(src_stat.st_mode))
|
|
10520 |
return 0;
|
|
10521 |
|
|
10522 |
ret = fstat(stp->dst_fd, &dst_stat);
|
|
10523 |
if (ret == -1) {
|
|
10524 |
stp->syserr = "fstat";
|
|
10525 |
stp->error_no = errno;
|
|
10526 |
return -1;
|
|
10527 |
}
|
|
10528 |
|
|
10529 |
src_offset = stp->src_offset;
|
|
10530 |
if (src_offset != (off_t)-1) {
|
|
10531 |
src_offset_ptr = &src_offset;
|
|
10532 |
}
|
|
10533 |
else {
|
|
10534 |
src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
|
|
10535 |
}
|
|
10536 |
|
|
10537 |
copy_length = stp->copy_length;
|
|
10538 |
if (copy_length == (off_t)-1) {
|
|
10539 |
if (src_offset == (off_t)-1) {
|
|
10540 |
off_t current_offset;
|
|
10541 |
errno = 0;
|
|
10542 |
current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
|
|
10543 |
if (current_offset == (off_t)-1 && errno) {
|
|
10544 |
stp->syserr = "lseek";
|
|
10545 |
stp->error_no = errno;
|
|
10546 |
return -1;
|
|
10547 |
}
|
|
10548 |
copy_length = src_stat.st_size - current_offset;
|
|
10549 |
}
|
|
10550 |
else {
|
|
10551 |
copy_length = src_stat.st_size - src_offset;
|
|
10552 |
}
|
|
10553 |
}
|
|
10554 |
|
|
10555 |
retry_copy_file_range:
|
|
10556 |
# if SIZEOF_OFF_T > SIZEOF_SIZE_T
|
|
10557 |
/* we are limited by the 32-bit ssize_t return value on 32-bit */
|
|
10558 |
ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
|
|
10559 |
# else
|
|
10560 |
ss = (ssize_t)copy_length;
|
|
10561 |
# endif
|
|
10562 |
ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
|
|
10563 |
if (0 < ss) {
|
|
10564 |
stp->total += ss;
|
|
10565 |
copy_length -= ss;
|
|
10566 |
if (0 < copy_length) {
|
|
10567 |
goto retry_copy_file_range;
|
|
10568 |
}
|
|
10569 |
}
|
|
10570 |
if (ss == -1) {
|
|
10571 |
if (maygvl_copy_stream_continue_p(0, stp)) {
|
|
10572 |
goto retry_copy_file_range;
|
|
10573 |
}
|
|
10574 |
switch (errno) {
|
|
10575 |
case EINVAL:
|
|
10576 |
#ifdef ENOSYS
|
|
10577 |
case ENOSYS:
|
|
10578 |
#endif
|
|
10579 |
#ifdef EXDEV
|
|
10580 |
case EXDEV: /* in_fd and out_fd are not on the same filesystem */
|
|
10581 |
#endif
|
|
10582 |
return 0;
|
|
10583 |
case EAGAIN:
|
|
10584 |
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
|
10585 |
case EWOULDBLOCK:
|
|
10586 |
#endif
|
|
10587 |
if (nogvl_copy_stream_wait_write(stp) == -1)
|
|
10588 |
return -1;
|
|
10589 |
goto retry_copy_file_range;
|
|
10590 |
}
|
|
10591 |
stp->syserr = "copy_file_range";
|
|
10592 |
stp->error_no = errno;
|
|
10593 |
return -1;
|
|
10594 |
}
|
|
10595 |
return 1;
|
|
10596 |
}
|
|
10597 |
#endif
|
|
10598 |
|
10492 |
10599 |
#ifdef HAVE_SENDFILE
|
10493 |
10600 |
|
10494 |
10601 |
# ifdef __linux__
|
... | ... | |
10787 |
10894 |
int ret;
|
10788 |
10895 |
#endif
|
10789 |
10896 |
|
|
10897 |
#ifdef USE_COPY_FILE_RANGE
|
|
10898 |
ret = nogvl_copy_file_range(stp);
|
|
10899 |
if (ret != 0)
|
|
10900 |
goto finish; /* error or success */
|
|
10901 |
#endif
|
|
10902 |
|
10790 |
10903 |
#ifdef USE_SENDFILE
|
10791 |
10904 |
ret = nogvl_copy_stream_sendfile(stp);
|
10792 |
10905 |
if (ret != 0)
|