}
n, err := copyFileRange(dst, src, int(max))
switch err {
- case syscall.ENOSYS:
- // copy_file_range(2) was introduced in Linux 4.5.
- // Go supports Linux >= 2.6.33, so the system call
- // may not be present.
- //
- // If we see ENOSYS, we have certainly not transferred
- // any data, so we can tell the caller that we
- // couldn't handle the transfer and let them fall
- // back to more generic code.
- return 0, false, nil
- case syscall.EXDEV, syscall.EINVAL, syscall.EIO, syscall.EOPNOTSUPP, syscall.EPERM:
- // Prior to Linux 5.3, it was not possible to
- // copy_file_range across file systems. Similarly to
- // the ENOSYS case above, if we see EXDEV, we have
- // not transferred any data, and we can let the caller
- // fall back to generic code.
- //
- // As for EINVAL, that is what we see if, for example,
- // dst or src refer to a pipe rather than a regular
+ case syscall.EINVAL, syscall.EIO, syscall.EOPNOTSUPP, syscall.EPERM:
+ // EINVAL is what we see if, for example,
+ // dst or src refers to a pipe rather than a regular
// file. This is another case where no data has been
// transferred, so we consider it unhandled.
//
// See issue #40731.
//
// If the process is running inside a Docker container,
- // we might see EPERM instead of ENOSYS. See issue
- // #40893. Since EPERM might also be a legitimate error,
- // don't mark copy_file_range(2) as unsupported.
+ // we might see EPERM instead of ENOSYS. See issue #40893.
+ // Since EPERM might also be a legitimate error: operation not permitted,
+ // we should still keep this error even if we have the previous kernel version 5.3 check
+ // and don't mark copy_file_range(2) as unsupported.
return 0, false, nil
case nil:
if n == 0 {
if written == 0 {
return 0, false, nil
}
- // Otherwise src is at EOF, which means
+ // Otherwise, src is at EOF, which means
// we are done.
return written, true, nil
}