From bc7ab270be94a036ffb807b045a65556561f6747 Mon Sep 17 00:00:00 2001 From: lunatic1hero Date: Thu, 29 Oct 2026 22:30:39 +0530 Subject: [PATCH 1/2] uucore/fsxattr: fix apply_xattrs_fd_ignore_unsupported to skip individual unsupported attributes --- src/uucore/src/lib/features/fsxattr.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uucore/src/lib/features/fsxattr.rs b/src/uucore/src/lib/features/fsxattr.rs index a962718f4e8..8245ce938a0 100644 --- a/src/uucore/src/lib/features/fsxattr.rs +++ b/src/uucore/src/lib/features/fsxattr.rs @@ -241,10 +241,14 @@ pub fn apply_xattrs_fd_ignore_unsupported( dest: &std::fs::File, xattrs: FxHashMap>, ) -> std::io::Result<()> { - match apply_xattrs_fd(dest, xattrs) { - Err(e) if is_xattr_unsupported(&e) => Ok(()), - res => res, + use xattr::FileExt; + for (attr, value) in xattrs { + match dest.set_xattr(&attr, &value) { + Err(e) if is_xattr_unsupported(&e) => {} + res => res?, + } } + Ok(()) } /// Checks if a file has an Access Control List (ACL). From db02a3387301cb8f97d45d6775ea7b161fe1a615 Mon Sep 17 00:00:00 2001 From: lunatic1hero Date: Tue, 3 Nov 2026 11:11:53 +0530 Subject: [PATCH 2/2] uucore/fsxattr: add test, update doc comment, suggested code change --- src/uucore/src/lib/features/fsxattr.rs | 51 +++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/uucore/src/lib/features/fsxattr.rs b/src/uucore/src/lib/features/fsxattr.rs index 8245ce938a0..0dc6fece1fc 100644 --- a/src/uucore/src/lib/features/fsxattr.rs +++ b/src/uucore/src/lib/features/fsxattr.rs @@ -235,7 +235,7 @@ pub fn apply_xattrs_fd( Ok(()) } -/// Like [`apply_xattrs_fd`], but maps `ENOTSUP` / `EOPNOTSUPP` to `Ok(())`. +/// Like [`apply_xattrs_fd`], but skips unsupported attributes. #[cfg(unix)] pub fn apply_xattrs_fd_ignore_unsupported( dest: &std::fs::File, @@ -245,7 +245,8 @@ pub fn apply_xattrs_fd_ignore_unsupported( for (attr, value) in xattrs { match dest.set_xattr(&attr, &value) { Err(e) if is_xattr_unsupported(&e) => {} - res => res?, + Err(e) => return Err(e), + Ok(()) => {} } } Ok(()) @@ -614,4 +615,50 @@ mod tests { test_value ); } + + #[test] + #[cfg(target_os = "linux")] + fn test_apply_xattrs_fd_ignore_unsupported() { + let temp_dir = tempdir().unwrap(); + let file_path = temp_dir.path().join("test_file.txt"); + + File::create(&file_path).unwrap(); + + // Skip silently if the test fs doesn't support user xattrs. + if xattr::set(&file_path, "user.probe", b"probe").is_err() { + return; + } + xattr::remove(&file_path, "user.probe").unwrap(); + + // Names in an unknown namespace get EOPNOTSUPP from the kernel. + let unsupported = ["foo.x", "bar.x", "baz.x"]; + for name in unsupported { + let err = xattr::set(&file_path, name, b"unsupported").unwrap_err(); + assert!(is_xattr_unsupported(&err)); + } + + let supported = ["user.a", "user.b", "user.c", "user.d", "user.e"]; + + let mut test_xattrs = FxHashMap::default(); + for name in unsupported { + test_xattrs.insert(OsString::from(name), b"unsupported".to_vec()); + } + for name in supported { + test_xattrs.insert(OsString::from(name), name.as_bytes().to_vec()); + } + + let dest = std::fs::OpenOptions::new() + .write(true) + .open(&file_path) + .unwrap(); + + apply_xattrs_fd_ignore_unsupported(&dest, test_xattrs).unwrap(); + + for name in supported { + assert_eq!( + xattr::get(&file_path, name).unwrap().unwrap(), + name.as_bytes() + ); + } + } }