Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,20 @@ pub fn copy_leaf(
} else {
match reflink_copy::reflink_or_copy(src, dest) {
Ok(_) => {
// Preserve file permissions (especially the execute bit).
// Preserve file permissions (especially the execute bit) —
// needed on Linux, skipped on macOS.
//
// On btrfs/XFS, reflink (FICLONE ioctl) clones data extents
// only — the destination gets umask-based permissions, losing
// execute bits. std::fs::copy's fallback preserves permissions
// via fchmod, creating an asymmetry in reflink_or_copy.
//
// On macOS/APFS, clonefile() already preserves the source's
// mode bits, so this chmod is redundant — skip it to save a
// syscall per file.
//
// Refs: ioctl_ficlonerange(2), LWN Articles/331808
#[cfg(unix)]
#[cfg(all(unix, not(target_os = "macos")))]
{
fs::set_permissions(dest, src_meta.permissions())
.context("setting destination file permissions")?;
Expand Down
Loading