@@ -643,7 +643,9 @@ fn test_install_copy_then_compare_file_with_extra_mode() {
643643 . arg ( "-m" )
644644 . arg ( "1644" )
645645 . succeeds ( )
646- . no_stderr ( ) ;
646+ . stderr_contains (
647+ "the --compare (-C) option is ignored when you specify a mode with non-permission bits" ,
648+ ) ;
647649
648650 file2_meta = at. metadata ( file2) ;
649651 let after_install_sticky = FileTime :: from_last_modification_time ( & file2_meta) ;
@@ -2222,20 +2224,37 @@ fn test_selinux() {
22222224
22232225 let args = [ "-Z" , "--context=unconfined_u:object_r:user_tmp_t:s0" ] ;
22242226 for arg in args {
2225- new_ucmd ! ( )
2227+ let result = new_ucmd ! ( )
22262228 . arg ( arg)
22272229 . arg ( "-v" )
22282230 . arg ( at. plus_as_string ( src) )
22292231 . arg ( at. plus_as_string ( dest) )
2230- . succeeds ( )
2231- . stdout_contains ( "orig' -> '" ) ;
2232+ . run ( ) ;
2233+
2234+ // Skip test if SELinux is not enabled
2235+ if result
2236+ . stderr_str ( )
2237+ . contains ( "SELinux is not enabled on this system" )
2238+ {
2239+ println ! ( "Skipping SELinux test: SELinux is not enabled" ) ;
2240+ at. remove ( & at. plus_as_string ( dest) ) ;
2241+ continue ;
2242+ }
2243+
2244+ result. success ( ) . stdout_contains ( "orig' -> '" ) ;
22322245
22332246 let getfattr_output = Command :: new ( "getfattr" )
22342247 . arg ( at. plus_as_string ( dest) )
22352248 . arg ( "-n" )
22362249 . arg ( "security.selinux" )
2237- . output ( )
2238- . expect ( "Failed to run `getfattr` on the destination file" ) ;
2250+ . output ( ) ;
2251+
2252+ // Skip test if getfattr is not available
2253+ let Ok ( getfattr_output) = getfattr_output else {
2254+ println ! ( "Skipping SELinux test: getfattr not available" ) ;
2255+ at. remove ( & at. plus_as_string ( dest) ) ;
2256+ continue ;
2257+ } ;
22392258 println ! ( "{:?}" , getfattr_output) ;
22402259 assert ! (
22412260 getfattr_output. status. success( ) ,
@@ -2267,14 +2286,69 @@ fn test_selinux_invalid_args() {
22672286 "--context=nconfined_u:object_r:user_tmp_t:s0" ,
22682287 ] ;
22692288 for arg in args {
2270- new_ucmd ! ( )
2289+ let result = new_ucmd ! ( )
22712290 . arg ( arg)
22722291 . arg ( "-v" )
22732292 . arg ( at. plus_as_string ( src) )
22742293 . arg ( at. plus_as_string ( dest) )
2275- . fails ( )
2276- . stderr_contains ( "failed to set default file creation" ) ;
2294+ . fails ( ) ;
2295+
2296+ let stderr = result. stderr_str ( ) ;
2297+ assert ! (
2298+ stderr. contains( "failed to set default file creation" )
2299+ || stderr. contains( "SELinux is not enabled on this system" ) ,
2300+ "Expected stderr to contain either 'failed to set default file creation' or 'SELinux is not enabled on this system', but got: '{}'" ,
2301+ stderr
2302+ ) ;
22772303
22782304 at. remove ( & at. plus_as_string ( dest) ) ;
22792305 }
22802306}
2307+
2308+ #[ test]
2309+ #[ cfg( not( any( target_os = "openbsd" , target_os = "freebsd" ) ) ) ]
2310+ fn test_install_compare_with_mode_bits ( ) {
2311+ let test_cases = [
2312+ ( "4755" , "setuid bit" , true ) ,
2313+ ( "2755" , "setgid bit" , true ) ,
2314+ ( "1755" , "sticky bit" , true ) ,
2315+ ( "7755" , "setuid + setgid + sticky bits" , true ) ,
2316+ ( "755" , "permission-only mode" , false ) ,
2317+ ] ;
2318+
2319+ for ( mode, description, should_warn) in test_cases {
2320+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
2321+ let at = & scene. fixtures ;
2322+ let source = format ! ( "source_file_{}" , mode) ;
2323+ let dest = format ! ( "dest_file_{}" , mode) ;
2324+
2325+ at. write ( & source, "test content" ) ;
2326+
2327+ let mode_arg = format ! ( "--mode={}" , mode) ;
2328+
2329+ if should_warn {
2330+ scene. ucmd ( ) . args ( & [ "-C" , & mode_arg, & source, & dest] )
2331+ . succeeds ( )
2332+ . stderr_contains ( "the --compare (-C) option is ignored when you specify a mode with non-permission bits" ) ;
2333+ } else {
2334+ scene
2335+ . ucmd ( )
2336+ . args ( & [ "-C" , & mode_arg, & source, & dest] )
2337+ . succeeds ( )
2338+ . no_stderr ( ) ;
2339+
2340+ // Test second install should be no-op due to -C
2341+ scene
2342+ . ucmd ( )
2343+ . args ( & [ "-C" , & mode_arg, & source, & dest] )
2344+ . succeeds ( )
2345+ . no_stderr ( ) ;
2346+ }
2347+
2348+ assert ! (
2349+ at. file_exists( & dest) ,
2350+ "Failed to create dest file for {}" ,
2351+ description
2352+ ) ;
2353+ }
2354+ }
0 commit comments