mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Rollup merge of #126807 - devnexen:copy_file_macos_simpl, r=Mark-Simulacrum
std::unix::fs: copy simplification for apple. since we do support from macOs Sierra, we avoid the little runtime overhead with the fclonefileat symbol check.
This commit is contained in:
commit
21850f5bd8
@ -20,14 +20,14 @@ use crate::sys::time::SystemTime;
|
|||||||
use crate::sys::{cvt, cvt_r};
|
use crate::sys::{cvt, cvt_r};
|
||||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||||
|
|
||||||
#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
|
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||||
use crate::sys::weak::syscall;
|
use crate::sys::weak::syscall;
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
use crate::sys::weak::weak;
|
use crate::sys::weak::weak;
|
||||||
|
|
||||||
use libc::{c_int, mode_t};
|
use libc::{c_int, mode_t};
|
||||||
|
|
||||||
#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
|
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(target_os = "linux", not(target_env = "musl")),
|
all(target_os = "linux", not(target_env = "musl")),
|
||||||
@ -1891,8 +1891,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
|
|
||||||
#[cfg(target_vendor = "apple")]
|
#[cfg(target_vendor = "apple")]
|
||||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
|
const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
|
||||||
|
|
||||||
struct FreeOnDrop(libc::copyfile_state_t);
|
struct FreeOnDrop(libc::copyfile_state_t);
|
||||||
@ -1907,39 +1905,21 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MacOS prior to 10.12 don't support `fclonefileat`
|
|
||||||
// We store the availability in a global to avoid unnecessary syscalls
|
|
||||||
static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
|
|
||||||
syscall! {
|
|
||||||
// Mirrors `libc::fclonefileat`
|
|
||||||
fn fclonefileat(
|
|
||||||
srcfd: libc::c_int,
|
|
||||||
dst_dirfd: libc::c_int,
|
|
||||||
dst: *const c_char,
|
|
||||||
flags: libc::c_int
|
|
||||||
) -> libc::c_int
|
|
||||||
}
|
|
||||||
|
|
||||||
let (reader, reader_metadata) = open_from(from)?;
|
let (reader, reader_metadata) = open_from(from)?;
|
||||||
|
|
||||||
// Opportunistically attempt to create a copy-on-write clone of `from`
|
let clonefile_result = run_path_with_cstr(to, &|to| {
|
||||||
// using `fclonefileat`.
|
cvt(unsafe { libc::fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
|
||||||
if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {
|
});
|
||||||
let clonefile_result = run_path_with_cstr(to, &|to| {
|
match clonefile_result {
|
||||||
cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
|
Ok(_) => return Ok(reader_metadata.len()),
|
||||||
});
|
Err(e) => match e.raw_os_error() {
|
||||||
match clonefile_result {
|
// `fclonefileat` will fail on non-APFS volumes, if the
|
||||||
Ok(_) => return Ok(reader_metadata.len()),
|
// destination already exists, or if the source and destination
|
||||||
Err(err) => match err.raw_os_error() {
|
// are on different devices. In all these cases `fcopyfile`
|
||||||
// `fclonefileat` will fail on non-APFS volumes, if the
|
// should succeed.
|
||||||
// destination already exists, or if the source and destination
|
Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),
|
||||||
// are on different devices. In all these cases `fcopyfile`
|
_ => return Err(e),
|
||||||
// should succeed.
|
},
|
||||||
Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),
|
|
||||||
Some(libc::ENOSYS) => HAS_FCLONEFILEAT.store(false, Ordering::Relaxed),
|
|
||||||
_ => return Err(err),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to using `fcopyfile` if `fclonefileat` does not succeed.
|
// Fall back to using `fcopyfile` if `fclonefileat` does not succeed.
|
||||||
|
Loading…
Reference in New Issue
Block a user