Auto merge of #123485 - madsmtm:use-libc-copyfile, r=joboet
macOS: Use `libc` definitions for copyfile `COPYFILE_ALL` is not yet exposed in `libc`, but the rest of what we need is, so use those definitions instead of manually defining them. The definitions were added in https://github.com/rust-lang/libc/pull/2667 and https://github.com/rust-lang/libc/pull/3346.
This commit is contained in:
commit
033becf83c
@ -1847,39 +1847,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
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};
|
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
const COPYFILE_ACL: u32 = 1 << 0;
|
const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
|
||||||
const COPYFILE_STAT: u32 = 1 << 1;
|
|
||||||
const COPYFILE_XATTR: u32 = 1 << 2;
|
|
||||||
const COPYFILE_DATA: u32 = 1 << 3;
|
|
||||||
|
|
||||||
const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
|
struct FreeOnDrop(libc::copyfile_state_t);
|
||||||
const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
|
|
||||||
const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
|
|
||||||
|
|
||||||
const COPYFILE_STATE_COPIED: u32 = 8;
|
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type copyfile_state_t = *mut libc::c_void;
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
type copyfile_flags_t = u32;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn fcopyfile(
|
|
||||||
from: libc::c_int,
|
|
||||||
to: libc::c_int,
|
|
||||||
state: copyfile_state_t,
|
|
||||||
flags: copyfile_flags_t,
|
|
||||||
) -> libc::c_int;
|
|
||||||
fn copyfile_state_alloc() -> copyfile_state_t;
|
|
||||||
fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
|
|
||||||
fn copyfile_state_get(
|
|
||||||
state: copyfile_state_t,
|
|
||||||
flag: u32,
|
|
||||||
dst: *mut libc::c_void,
|
|
||||||
) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FreeOnDrop(copyfile_state_t);
|
|
||||||
impl Drop for FreeOnDrop {
|
impl Drop for FreeOnDrop {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// The code below ensures that `FreeOnDrop` is never a null pointer
|
// The code below ensures that `FreeOnDrop` is never a null pointer
|
||||||
@ -1887,7 +1857,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
// `copyfile_state_free` returns -1 if the `to` or `from` files
|
// `copyfile_state_free` returns -1 if the `to` or `from` files
|
||||||
// cannot be closed. However, this is not considered this an
|
// cannot be closed. However, this is not considered this an
|
||||||
// error.
|
// error.
|
||||||
copyfile_state_free(self.0);
|
libc::copyfile_state_free(self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1896,6 +1866,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
// We store the availability in a global to avoid unnecessary syscalls
|
// We store the availability in a global to avoid unnecessary syscalls
|
||||||
static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
|
static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
|
||||||
syscall! {
|
syscall! {
|
||||||
|
// Mirrors `libc::fclonefileat`
|
||||||
fn fclonefileat(
|
fn fclonefileat(
|
||||||
srcfd: libc::c_int,
|
srcfd: libc::c_int,
|
||||||
dst_dirfd: libc::c_int,
|
dst_dirfd: libc::c_int,
|
||||||
@ -1932,22 +1903,22 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||||||
// We ensure that `FreeOnDrop` never contains a null pointer so it is
|
// We ensure that `FreeOnDrop` never contains a null pointer so it is
|
||||||
// always safe to call `copyfile_state_free`
|
// always safe to call `copyfile_state_free`
|
||||||
let state = unsafe {
|
let state = unsafe {
|
||||||
let state = copyfile_state_alloc();
|
let state = libc::copyfile_state_alloc();
|
||||||
if state.is_null() {
|
if state.is_null() {
|
||||||
return Err(crate::io::Error::last_os_error());
|
return Err(crate::io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
FreeOnDrop(state)
|
FreeOnDrop(state)
|
||||||
};
|
};
|
||||||
|
|
||||||
let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { COPYFILE_DATA };
|
let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { libc::COPYFILE_DATA };
|
||||||
|
|
||||||
cvt(unsafe { fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
|
cvt(unsafe { libc::fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
|
||||||
|
|
||||||
let mut bytes_copied: libc::off_t = 0;
|
let mut bytes_copied: libc::off_t = 0;
|
||||||
cvt(unsafe {
|
cvt(unsafe {
|
||||||
copyfile_state_get(
|
libc::copyfile_state_get(
|
||||||
state.0,
|
state.0,
|
||||||
COPYFILE_STATE_COPIED,
|
libc::COPYFILE_STATE_COPIED as u32,
|
||||||
core::ptr::addr_of_mut!(bytes_copied) as *mut libc::c_void,
|
core::ptr::addr_of_mut!(bytes_copied) as *mut libc::c_void,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user