@@ -2615,7 +2615,7 @@ fn test_cp_reflink_insufficient_permission() {
26152615 . arg ( "unreadable" )
26162616 . arg ( TEST_EXISTING_FILE )
26172617 . fails ( )
2618- . stderr_only ( "cp: 'unreadable' -> 'existing_file.txt': Permission denied (os error 13) \n " ) ;
2618+ . stderr_only ( "cp: 'unreadable' -> 'existing_file.txt': Permission denied\n " ) ;
26192619}
26202620
26212621#[ cfg( target_os = "linux" ) ]
@@ -3131,9 +3131,8 @@ fn test_cp_archive_on_nonexistent_file() {
31313131 . arg ( TEST_NONEXISTENT_FILE )
31323132 . arg ( TEST_EXISTING_FILE )
31333133 . fails ( )
3134- . stderr_only (
3135- "cp: cannot stat 'nonexistent_file.txt': No such file or directory (os error 2)\n " ,
3136- ) ;
3134+ . stderr_contains ( "cannot stat 'nonexistent_file.txt'" )
3135+ . stderr_contains ( "No such file or directory" ) ;
31373136}
31383137
31393138#[ test]
@@ -7512,3 +7511,63 @@ fn test_cp_to_existing_file_permissions() {
75127511 let new_dst_mode = std:: fs:: metadata ( & dst_path) . unwrap ( ) . permissions ( ) . mode ( ) ;
75137512 assert_eq ! ( dst_mode, new_dst_mode) ;
75147513}
7514+
7515+ /// Test xattr ENOTSUP handling: -a/--preserve=all silent, --preserve=xattr errors
7516+ #[ test]
7517+ #[ cfg( target_os = "linux" ) ]
7518+ fn test_cp_xattr_enotsup_handling ( ) {
7519+ use std:: process:: Command ;
7520+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
7521+ let at = & scene. fixtures ;
7522+ at. write ( "src" , "x" ) ;
7523+
7524+ // Check if setfattr is available and source fs supports xattrs
7525+ if !Command :: new ( "setfattr" )
7526+ . args ( [ "-n" , "user.t" , "-v" , "v" , & at. plus_as_string ( "src" ) ] )
7527+ . status ( )
7528+ . is_ok_and ( |s| s. success ( ) )
7529+ {
7530+ return ; // Skip: setfattr not available or source doesn't support xattrs
7531+ }
7532+
7533+ // Check if /dev/shm exists
7534+ if !std:: path:: Path :: new ( "/dev/shm" ) . exists ( ) {
7535+ return ; // Skip: /dev/shm not available
7536+ }
7537+
7538+ // Check if /dev/shm actually doesn't support xattrs by trying to set one
7539+ let shm_test_file = "/dev/shm/xattr_test_probe" ;
7540+ std:: fs:: write ( shm_test_file, "test" ) . ok ( ) ;
7541+ let shm_supports_xattr = Command :: new ( "setfattr" )
7542+ . args ( [ "-n" , "user.t" , "-v" , "v" , shm_test_file] )
7543+ . status ( )
7544+ . is_ok_and ( |s| s. success ( ) ) ;
7545+ std:: fs:: remove_file ( shm_test_file) . ok ( ) ;
7546+
7547+ if shm_supports_xattr {
7548+ return ; // Skip: /dev/shm supports xattrs on this system
7549+ }
7550+
7551+ // -a: silent success
7552+ scene
7553+ . ucmd ( )
7554+ . args ( & [ "-a" , & at. plus_as_string ( "src" ) , "/dev/shm/t1" ] )
7555+ . succeeds ( )
7556+ . no_stderr ( ) ;
7557+ // --preserve=all: silent success
7558+ scene
7559+ . ucmd ( )
7560+ . args ( & [ "--preserve=all" , & at. plus_as_string ( "src" ) , "/dev/shm/t2" ] )
7561+ . succeeds ( )
7562+ . no_stderr ( ) ;
7563+ // --preserve=xattr: must fail with proper message
7564+ scene
7565+ . ucmd ( )
7566+ . args ( & [ "--preserve=xattr" , & at. plus_as_string ( "src" ) , "/dev/shm/t3" ] )
7567+ . fails ( )
7568+ . stderr_contains ( "setting attributes" )
7569+ . stderr_contains ( "Operation not supported" ) ;
7570+ for f in [ "/dev/shm/t1" , "/dev/shm/t2" , "/dev/shm/t3" ] {
7571+ std:: fs:: remove_file ( f) . ok ( ) ;
7572+ }
7573+ }
0 commit comments