@@ -27,7 +27,10 @@ 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_install,
32
+ set_selinux_default_context_for_install, set_selinux_security_context,
33
+ } ;
31
34
use uucore:: { format_usage, show, show_error, show_if_err} ;
32
35
33
36
#[ cfg( unix) ]
@@ -57,6 +60,7 @@ pub struct Behavior {
57
60
no_target_dir : bool ,
58
61
preserve_context : bool ,
59
62
context : Option < String > ,
63
+ default_context : bool ,
60
64
}
61
65
62
66
#[ derive( Error , Debug ) ]
@@ -157,6 +161,7 @@ static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory";
157
161
static OPT_VERBOSE : & str ="verbose" ;
158
162
static OPT_PRESERVE_CONTEXT : & str ="preserve-context" ;
159
163
static OPT_CONTEXT : & str ="context" ;
164
+ static OPT_DEFAULT_CONTEXT : & str ="default-context" ;
160
165
161
166
static ARG_FILES : & str ="files" ;
162
167
@@ -290,8 +295,13 @@ pub fn uu_app() -> Command {
290
295
. action ( ArgAction :: SetTrue ) ,
291
296
)
292
297
. arg (
293
- Arg :: new ( OPT_CONTEXT )
298
+ Arg :: new ( OPT_DEFAULT_CONTEXT )
294
299
. short ( 'Z' )
300
+ . help ( get_message ( "install-help-default-context" ) )
301
+ . action ( ArgAction :: SetTrue ) ,
302
+ )
303
+ . arg (
304
+ Arg :: new ( OPT_CONTEXT )
295
305
. long ( OPT_CONTEXT )
296
306
. help ( get_message ( "install-help-context" ) )
297
307
. value_name ( "CONTEXT" )
@@ -403,6 +413,7 @@ fn behavior(matches: &ArgMatches) -> UResult<Behavior> {
403
413
} ;
404
414
405
415
let context = matches. get_one :: < String > ( OPT_CONTEXT ) . cloned ( ) ;
416
+ let default_context = matches. get_flag ( OPT_DEFAULT_CONTEXT ) ;
406
417
407
418
Ok ( Behavior {
408
419
main_function,
@@ -425,6 +436,7 @@ fn behavior(matches: &ArgMatches) -> UResult<Behavior> {
425
436
no_target_dir,
426
437
preserve_context : matches. get_flag ( OPT_PRESERVE_CONTEXT ) ,
427
438
context,
439
+ default_context,
428
440
} )
429
441
}
430
442
@@ -463,6 +475,16 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
463
475
continue ;
464
476
}
465
477
478
+ // Set SELinux context for all created directories if needed
479
+ #[ cfg( feature ="selinux" ) ]
480
+ if b. context . is_some ( ) || b. default_context {
481
+ let context =get_context_for_selinux ( b) ;
482
+ set_selinux_context_for_created_directories_install (
483
+ path_to_create. as_path ( ) ,
484
+ context,
485
+ ) ;
486
+ }
487
+
466
488
if b. verbose {
467
489
println ! (
468
490
"{}" ,
@@ -487,7 +509,12 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
487
509
488
510
// Set SELinux context for directory if needed
489
511
#[ cfg( feature ="selinux" ) ]
490
- show_if_err ! ( set_selinux_context( path, b) ) ;
512
+ if b. default_context {
513
+ show_if_err ! ( set_selinux_default_context_for_install( path) ) ;
514
+ } else if b. context . is_some ( ) {
515
+ let context =get_context_for_selinux ( b) ;
516
+ show_if_err ! ( set_selinux_security_context( path, context) ) ;
517
+ }
491
518
}
492
519
// If the exit code was set, or show! has been called at least once
493
520
// (which sets the exit code as well), function execution will end after
@@ -606,6 +633,13 @@ fn standard(mut paths: Vec<String>, b: &Behavior) -> UResult<()> {
606
633
if let Err ( e) = fs:: create_dir_all ( to_create) {
607
634
return Err ( InstallError :: CreateDirFailed ( to_create. to_path_buf ( ) , e) . into ( ) ) ;
608
635
}
636
+
637
+ // Set SELinux context for all created directories if needed
638
+ #[ cfg( feature ="selinux" ) ]
639
+ if b. context . is_some ( ) || b. default_context {
640
+ let context =get_context_for_selinux ( b) ;
641
+ set_selinux_context_for_created_directories_install ( to_create, context) ;
642
+ }
609
643
}
610
644
}
611
645
if b. target_dir . is_some ( ) {
@@ -975,8 +1009,13 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
975
1009
if b. preserve_context {
976
1010
uucore:: selinux:: preserve_security_context ( from, to)
977
1011
. map_err ( |e|InstallError :: SelinuxContextFailed ( e. to_string ( ) ) ) ?;
1012
+ } else if b. default_context {
1013
+ set_selinux_default_context_for_install ( to)
1014
+ . map_err ( |e|InstallError :: SelinuxContextFailed ( e. to_string ( ) ) ) ?;
978
1015
} else if b. context . is_some ( ) {
979
- set_selinux_context ( to, b) ?;
1016
+ let context =get_context_for_selinux ( b) ;
1017
+ set_selinux_security_context ( to, context)
1018
+ . map_err ( |e|InstallError :: SelinuxContextFailed ( e. to_string ( ) ) ) ?;
980
1019
}
981
1020
982
1021
if b. verbose {
@@ -1005,6 +1044,15 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
1005
1044
Ok ( ( ) )
1006
1045
}
1007
1046
1047
+ #[ cfg( feature ="selinux" ) ]
1048
+ fn get_context_for_selinux ( b : & Behavior ) ->Option < & String > {
1049
+ if b. default_context {
1050
+ None
1051
+ } else {
1052
+ b. context . as_ref ( )
1053
+ }
1054
+ }
1055
+
1008
1056
/// Check if a file needs to be copied due to ownership differences when no explicit group is specified.
1009
1057
/// Returns true if the destination file's ownership would differ from what it should be after installation.
1010
1058
fn needs_copy_for_ownership ( to : & Path , to_meta : & fs:: Metadata ) ->bool {