std::unix::fs: copy simplification for apple. · model-checking/verify-rust-std@d688595

@@ -20,14 +20,14 @@ use crate::sys::time::SystemTime;

2020

use crate::sys::{cvt, cvt_r};

2121

use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

222223-

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]

23+

#[cfg(all(target_os = "linux", target_env = "gnu"))]

2424

use crate::sys::weak::syscall;

2525

#[cfg(target_os = "android")]

2626

use crate::sys::weak::weak;

27272828

use libc::{c_int, mode_t};

292930-

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]

30+

#[cfg(all(target_os = "linux", target_env = "gnu"))]

3131

use libc::c_char;

3232

#[cfg(any(

3333

all(target_os = "linux", not(target_env = "musl")),

@@ -1891,8 +1891,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {

1891189118921892

#[cfg(target_vendor = "apple")]

18931893

pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {

1894-

use crate::sync::atomic::{AtomicBool, Ordering};

1895-18961894

const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;

1897189518981896

struct FreeOnDrop(libc::copyfile_state_t);

@@ -1907,39 +1905,21 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {

19071905

}

19081906

}

190919071910-

// MacOS prior to 10.12 don't support `fclonefileat`

1911-

// We store the availability in a global to avoid unnecessary syscalls

1912-

static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);

1913-

syscall! {

1914-

// Mirrors `libc::fclonefileat`

1915-

fn fclonefileat(

1916-

srcfd: libc::c_int,

1917-

dst_dirfd: libc::c_int,

1918-

dst: *const c_char,

1919-

flags: libc::c_int

1920-

) -> libc::c_int

1921-

}

1922-19231908

let (reader, reader_metadata) = open_from(from)?;

192419091925-

// Opportunistically attempt to create a copy-on-write clone of `from`

1926-

// using `fclonefileat`.

1927-

if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {

1928-

let clonefile_result = run_path_with_cstr(to, &|to| {

1929-

cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })

1930-

});

1931-

match clonefile_result {

1932-

Ok(_) => return Ok(reader_metadata.len()),

1933-

Err(err) => match err.raw_os_error() {

1934-

// `fclonefileat` will fail on non-APFS volumes, if the

1935-

// destination already exists, or if the source and destination

1936-

// are on different devices. In all these cases `fcopyfile`

1937-

// should succeed.

1938-

Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),

1939-

Some(libc::ENOSYS) => HAS_FCLONEFILEAT.store(false, Ordering::Relaxed),

1940-

_ => return Err(err),

1941-

},

1942-

}

1910+

let clonefile_result = run_path_with_cstr(to, &|to| {

1911+

cvt(unsafe { libc::fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })

1912+

});

1913+

match clonefile_result {

1914+

Ok(_) => return Ok(reader_metadata.len()),

1915+

Err(e) => match e.raw_os_error() {

1916+

// `fclonefileat` will fail on non-APFS volumes, if the

1917+

// destination already exists, or if the source and destination

1918+

// are on different devices. In all these cases `fcopyfile`

1919+

// should succeed.

1920+

Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),

1921+

_ => return Err(e),

1922+

},

19431923

}

1944192419451925

// Fall back to using `fcopyfile` if `fclonefileat` does not succeed.