@@ -27,7 +27,9 @@ use uucore::mode::get_umask;
27
27
use uucore:: perms:: { Verbosity , VerbosityLevel , wrap_chown} ;
28
28
use uucore:: process:: { getegid, geteuid} ;
29
29
#[ cfg( feature ="selinux" ) ]
30
- use uucore:: selinux:: { contexts_differ, set_selinux_security_context} ;
30
+ use uucore:: selinux:: {
31
+ contexts_differ, set_selinux_context_for_created_directories, set_selinux_security_context,
32
+ } ;
31
33
use uucore:: { format_usage, show, show_error, show_if_err} ;
32
34
33
35
#[ cfg( unix) ]
@@ -57,6 +59,7 @@ pub struct Behavior {
57
59
no_target_dir : bool ,
58
60
preserve_context : bool ,
59
61
context : Option < String > ,
62
+ default_context : bool ,
60
63
}
61
64
62
65
#[ derive( Error , Debug ) ]
@@ -157,6 +160,7 @@ static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory";
157
160
static OPT_VERBOSE : & str ="verbose" ;
158
161
static OPT_PRESERVE_CONTEXT : & str ="preserve-context" ;
159
162
static OPT_CONTEXT : & str ="context" ;
163
+ static OPT_DEFAULT_CONTEXT : & str ="default-context" ;
160
164
161
165
static ARG_FILES : & str ="files" ;
162
166
@@ -290,8 +294,13 @@ pub fn uu_app() -> Command {
290
294
. action ( ArgAction :: SetTrue ) ,
291
295
)
292
296
. arg (
293
- Arg :: new ( OPT_CONTEXT )
297
+ Arg :: new ( OPT_DEFAULT_CONTEXT )
294
298
. short ( 'Z' )
299
+ . help ( get_message ( "install-help-default-context" ) )
300
+ . action ( ArgAction :: SetTrue ) ,
301
+ )
302
+ . arg (
303
+ Arg :: new ( OPT_CONTEXT )
295
304
. long ( OPT_CONTEXT )
296
305
. help ( get_message ( "install-help-context" ) )
297
306
. value_name ( "CONTEXT" )
@@ -403,6 +412,7 @@ fn behavior(matches: &ArgMatches) -> UResult<Behavior> {
403
412
} ;
404
413
405
414
let context = matches. get_one :: < String > ( OPT_CONTEXT ) . cloned ( ) ;
415
+ let default_context = matches. get_flag ( OPT_DEFAULT_CONTEXT ) ;
406
416
407
417
Ok ( Behavior {
408
418
main_function,
@@ -425,6 +435,7 @@ fn behavior(matches: &ArgMatches) -> UResult<Behavior> {
425
435
no_target_dir,
426
436
preserve_context : matches. get_flag ( OPT_PRESERVE_CONTEXT ) ,
427
437
context,
438
+ default_context,
428
439
} )
429
440
}
430
441
@@ -463,6 +474,13 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
463
474
continue ;
464
475
}
465
476
477
+ // Set SELinux context for all created directories if needed
478
+ #[ cfg( feature ="selinux" ) ]
479
+ if b. context . is_some ( ) || b. default_context {
480
+ let context =get_context_for_selinux ( b) ;
481
+ set_selinux_context_for_created_directories ( path_to_create. as_path ( ) , context) ;
482
+ }
483
+
466
484
if b. verbose {
467
485
println ! (
468
486
"{}" ,
@@ -487,7 +505,10 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
487
505
488
506
// Set SELinux context for directory if needed
489
507
#[ cfg( feature ="selinux" ) ]
490
- show_if_err ! ( set_selinux_context( path, b) ) ;
508
+ if b. context . is_some ( ) || b. default_context {
509
+ let context =get_context_for_selinux ( b) ;
510
+ show_if_err ! ( set_selinux_security_context( path, context) ) ;
511
+ }
491
512
}
492
513
// If the exit code was set, or show! has been called at least once
493
514
// (which sets the exit code as well), function execution will end after
@@ -606,6 +627,13 @@ fn standard(mut paths: Vec<String>, b: &Behavior) -> UResult<()> {
606
627
if let Err ( e) = fs:: create_dir_all ( to_create) {
607
628
return Err ( InstallError :: CreateDirFailed ( to_create. to_path_buf ( ) , e) . into ( ) ) ;
608
629
}
630
+
631
+ // Set SELinux context for all created directories if needed
632
+ #[ cfg( feature ="selinux" ) ]
633
+ if b. context . is_some ( ) || b. default_context {
634
+ let context =get_context_for_selinux ( b) ;
635
+ set_selinux_context_for_created_directories ( to_create, context) ;
636
+ }
609
637
}
610
638
}
611
639
if b. target_dir . is_some ( ) {
@@ -975,8 +1003,10 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
975
1003
if b. preserve_context {
976
1004
uucore:: selinux:: preserve_security_context ( from, to)
977
1005
. map_err ( |e|InstallError :: SelinuxContextFailed ( e. to_string ( ) ) ) ?;
978
- } else if b. context . is_some ( ) {
979
- set_selinux_context ( to, b) ?;
1006
+ } else if b. context . is_some ( ) || b. default_context {
1007
+ let context =get_context_for_selinux ( b) ;
1008
+ set_selinux_security_context ( to, context)
1009
+ . map_err ( |e|InstallError :: SelinuxContextFailed ( e. to_string ( ) ) ) ?;
980
1010
}
981
1011
982
1012
if b. verbose {
@@ -1005,6 +1035,15 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
1005
1035
Ok ( ( ) )
1006
1036
}
1007
1037
1038
+ #[ cfg( feature ="selinux" ) ]
1039
+ fn get_context_for_selinux ( b : & Behavior ) ->Option < & String > {
1040
+ if b. default_context {
1041
+ None
1042
+ } else {
1043
+ b. context . as_ref ( )
1044
+ }
1045
+ }
1046
+
1008
1047
/// Check if a file needs to be copied due to ownership differences when no explicit group is specified.
1009
1048
/// Returns true if the destination file's ownership would differ from what it should be after installation.
1010
1049
fn needs_copy_for_ownership ( to : & Path , to_meta : & fs:: Metadata ) ->bool {