@@ -607,42 +607,48 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
607607 Ok ( 0 ) => return CopyResult :: Ended ( written) , // reached EOF
608608 Ok ( ret) => written += ret as u64 ,
609609 Err ( err) => {
610- let raw_os_error = match err. raw_os_error ( ) {
611- Some ( raw) => raw,
612- _ => return CopyResult :: Error ( err, written) ,
613- } ;
614- return match raw_os_error {
610+ return match err. raw_os_error ( ) {
615611 // when file offset + max_length > u64::MAX
616- EOVERFLOW => CopyResult :: Fallback ( written) ,
617- ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF if written == 0 => {
612+ Some ( EOVERFLOW ) => CopyResult :: Fallback ( written) ,
613+ Some ( raw_os_error @ ( ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF ) )
614+ if written == 0 =>
615+ {
618616 if !have_probed {
619- if raw_os_error == ENOSYS {
620- HAS_COPY_FILE_RANGE . store ( UNAVAILABLE , Ordering :: Relaxed ) ;
621- } else {
622- // EPERM can indicate seccomp filters or an
623- // immutable file. To distinguish these cases
624- // we probe with invalid file descriptors which
625- // should result in EBADF if the syscall is
626- // supported and some other error (ENOSYS or
627- // EPERM) if it's not available.
628- let result = unsafe {
629- cvt ( copy_file_range (
630- INVALID_FD ,
631- ptr:: null_mut ( ) ,
632- INVALID_FD ,
633- ptr:: null_mut ( ) ,
634- 1 ,
635- 0 ,
636- ) )
637- } ;
638-
639- if matches ! ( result. map_err( |e| e. raw_os_error( ) ) , Err ( Some ( EBADF ) ) )
640- {
641- HAS_COPY_FILE_RANGE . store ( AVAILABLE , Ordering :: Relaxed ) ;
642- } else {
643- HAS_COPY_FILE_RANGE . store ( UNAVAILABLE , Ordering :: Relaxed ) ;
617+ let available = match raw_os_error {
618+ EPERM => {
619+ // EPERM can indicate seccomp filters or an
620+ // immutable file. To distinguish these
621+ // cases we probe with invalid file
622+ // descriptors which should result in EBADF
623+ // if the syscall is supported and EPERM if
624+ // it's not available.
625+ match unsafe {
626+ cvt ( copy_file_range (
627+ INVALID_FD ,
628+ ptr:: null_mut ( ) ,
629+ INVALID_FD ,
630+ ptr:: null_mut ( ) ,
631+ 1 ,
632+ 0 ,
633+ ) )
634+ . map_err ( |e| e. raw_os_error ( ) )
635+ } {
636+ // The syscall can't fail with ENOSYS
637+ // if it previously returned a
638+ // different error.
639+ Err ( Some ( EPERM ) ) => UNAVAILABLE ,
640+ Err ( Some ( EBADF ) ) => AVAILABLE ,
641+ other => {
642+ panic ! (
643+ "unexpected copy_file_range probe result: {other:?}"
644+ ) ;
645+ }
646+ }
644647 }
645- }
648+ ENOSYS => UNAVAILABLE ,
649+ _ => AVAILABLE ,
650+ } ;
651+ HAS_COPY_FILE_RANGE . store ( available, Ordering :: Relaxed ) ;
646652 }
647653
648654 // Try fallback io::copy if either:
0 commit comments