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

`}

`