Lift the probe code of copy_file_range
into a function · model-checking/verify-rust-std@7a6ddb3 (original) (raw)
`@@ -577,6 +577,23 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
`
577
577
`) -> libc::ssize_t
`
578
578
`}
`
579
579
``
``
580
`+
fn probe_copy_file_range_support() -> u8 {
`
``
581
`+
// In some cases, we cannot determine availability from the first
`
``
582
`` +
// copy_file_range
call. In this case, we probe with an invalid file
``
``
583
`+
// descriptor so that the results are easily interpretable.
`
``
584
`+
match unsafe {
`
``
585
`+
cvt(copy_file_range(INVALID_FD, ptr::null_mut(), INVALID_FD, ptr::null_mut(), 1, 0))
`
``
586
`+
.map_err(|e| e.raw_os_error())
`
``
587
`+
} {
`
``
588
`+
Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,
`
``
589
`+
Err(Some(EBADF)) => AVAILABLE,
`
``
590
`+
Ok(_) => panic!("unexpected copy_file_range probe success"),
`
``
591
`+
// Treat other errors as the syscall
`
``
592
`+
// being unavailable.
`
``
593
`+
Err(_) => UNAVAILABLE,
`
``
594
`+
}
`
``
595
`+
}
`
``
596
+
580
597
`let mut written = 0u64;
`
581
598
`while written < max_len {
`
582
599
`let bytes_to_copy = cmp::min(max_len - written, usize::MAX as u64);
`
`@@ -614,35 +631,20 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
`
614
631
`if written == 0 =>
`
615
632
`{
`
616
633
`if !have_probed {
`
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 or
`
624
``
`-
// ENOSYS if 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
``
`-
Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,
`
637
``
`-
Err(Some(EBADF)) => AVAILABLE,
`
638
``
`-
Ok(_) => panic!("unexpected copy_file_range probe success"),
`
639
``
`-
// Treat other errors as the syscall
`
640
``
`-
// being unavailable.
`
641
``
`-
Err(_) => UNAVAILABLE,
`
642
``
`-
}
`
643
``
`-
}
`
644
``
`-
ENOSYS => UNAVAILABLE,
`
645
``
`-
_ => AVAILABLE,
`
``
634
`+
let available = if matches!(raw_os_error, ENOSYS | EOPNOTSUPP | EPERM) {
`
``
635
`+
// EPERM can indicate seccomp filters or an
`
``
636
`+
// immutable file. To distinguish these
`
``
637
`+
// cases we probe with invalid file
`
``
638
`+
// descriptors which should result in EBADF
`
``
639
`+
// if the syscall is supported and EPERM or
`
``
640
`+
// ENOSYS if it's not available.
`
``
641
`+
//
`
``
642
`+
// For EOPNOTSUPP, see below. In the case of
`
``
643
`+
// ENOSYS, we try to cover for faulty FUSE
`
``
644
`+
// drivers.
`
``
645
`+
probe_copy_file_range_support()
`
``
646
`+
} else {
`
``
647
`+
AVAILABLE
`
646
648
`};
`
647
649
`HAS_COPY_FILE_RANGE.store(available, Ordering::Relaxed);
`
648
650
`}
`