Skip to content

Commit c9d1016

Browse files
committed
📝 Document cross-platform file flags behavior matching bsdtar
Document the intentional behavioral difference in set_flags() between Linux (merge) and BSD/macOS (overwrite), explaining this matches libarchive/bsdtar's own cross-platform inconsistency.
1 parent f9dff62 commit c9d1016

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

  • cli/src/utils/os/unix

cli/src/utils/os/unix/fs.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ pub(crate) fn get_flags(path: &Path) -> io::Result<Vec<String>> {
5757
Ok(flag_names)
5858
}
5959

60+
/// Sets file flags on macOS.
61+
///
62+
/// Note: This implementation overwrites all existing flags rather than merging them,
63+
/// which matches libarchive/bsdtar behavior. libarchive uses `chflags()` directly on
64+
/// BSD systems which replaces all flags, while on Linux it uses ioctl to read current
65+
/// flags first and merge them. This cross-platform inconsistency exists in bsdtar itself.
66+
/// See: https://github.com/libarchive/libarchive/blob/master/libarchive/archive_write_disk_posix.c
6067
#[cfg(target_os = "macos")]
6168
pub(crate) fn set_flags(path: &Path, flags: &[String]) -> io::Result<()> {
6269
use std::os::unix::ffi::OsStrExt;
@@ -152,6 +159,14 @@ pub(crate) fn get_flags(path: &Path) -> io::Result<Vec<String>> {
152159
Ok(flag_names)
153160
}
154161

162+
/// Sets file flags on Linux.
163+
///
164+
/// Note: This implementation reads current flags first and merges them with new flags,
165+
/// which matches libarchive/bsdtar behavior on Linux. libarchive uses ioctl to read
166+
/// current flags (`FS_IOC_GETFLAGS`) then computes `newflags = (oldflags & ~clear) | set`
167+
/// before writing. This differs from BSD systems where `chflags()` overwrites all flags.
168+
/// This cross-platform inconsistency exists in bsdtar itself.
169+
/// See: https://github.com/libarchive/libarchive/blob/master/libarchive/archive_write_disk_posix.c
155170
#[cfg(any(target_os = "linux", target_os = "android"))]
156171
pub(crate) fn set_flags(path: &Path, flags: &[String]) -> io::Result<()> {
157172
use linux_flags::*;
@@ -256,6 +271,13 @@ pub(crate) fn get_flags(path: &Path) -> io::Result<Vec<String>> {
256271
Ok(flag_names)
257272
}
258273

274+
/// Sets file flags on FreeBSD.
275+
///
276+
/// Note: This implementation overwrites all existing flags rather than merging them,
277+
/// which matches libarchive/bsdtar behavior. libarchive uses `chflags()` directly on
278+
/// BSD systems which replaces all flags, while on Linux it uses ioctl to read current
279+
/// flags first and merge them. This cross-platform inconsistency exists in bsdtar itself.
280+
/// See: https://github.com/libarchive/libarchive/blob/master/libarchive/archive_write_disk_posix.c
259281
#[cfg(target_os = "freebsd")]
260282
pub(crate) fn set_flags(path: &Path, flags: &[String]) -> io::Result<()> {
261283
use std::os::unix::ffi::OsStrExt;

0 commit comments

Comments
 (0)