Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/CICD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,7 @@ jobs:
- run: rsync -v -a -e ssh . lima-default:~/work/
- name: Setup Rust and other build deps in VM
run: |
lima sudo dnf install gcc g++ git rustup libselinux-devel clang-devel -y
lima sudo dnf install gcc g++ git rustup libselinux-devel clang-devel attr -y
lima rustup-init -y --default-toolchain stable
- name: Verify SELinux Status
run: |
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ feat_selinux = [
"cp/selinux",
"id/selinux",
"ls/selinux",
"mkdir/selinux",
"selinux",
"feat_require_selinux",
]
Expand Down
2 changes: 2 additions & 0 deletions src/uu/mkdir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ path = "src/mkdir.rs"
clap = { workspace = true }
uucore = { workspace = true, features = ["fs", "mode", "fsxattr"] }

[features]
selinux = ["uucore/selinux"]

[[bin]]
name = "mkdir"
Expand Down
90 changes: 70 additions & 20 deletions src/uu/mkdir/src/mkdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ mod options {
pub const PARENTS: &str = "parents";
pub const VERBOSE: &str = "verbose";
pub const DIRS: &str = "dirs";
pub const SELINUX: &str = "z";
pub const CONTEXT: &str = "context";
}

/// Configuration for directory creation.
pub struct Config<'a> {
/// Create parent directories as needed.
pub recursive: bool,

/// File permissions (octal).
pub mode: u32,

/// Print message for each created directory.
pub verbose: bool,

/// Set SELinux security context.
pub set_selinux_context: bool,

/// Specific SELinux context.
pub context: Option<&'a String>,
}

#[cfg(windows)]
Expand Down Expand Up @@ -91,8 +111,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let verbose = matches.get_flag(options::VERBOSE);
let recursive = matches.get_flag(options::PARENTS);

// Extract the SELinux related flags and options
let set_selinux_context = matches.get_flag(options::SELINUX);
let context = matches.get_one::<String>(options::CONTEXT);

match get_mode(&matches, mode_had_minus_prefix) {
Ok(mode) => exec(dirs, recursive, mode, verbose),
Ok(mode) => {
let config = Config {
recursive,
mode,
verbose,
set_selinux_context: set_selinux_context || context.is_some(),
context,
};
exec(dirs, &config)
}
Err(f) => Err(USimpleError::new(1, f)),
}
}
Expand Down Expand Up @@ -124,6 +157,15 @@ pub fn uu_app() -> Command {
.help("print a message for each printed directory")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::SELINUX)
.short('Z')
.help("set SELinux security context of each created directory to the default type")
.action(ArgAction::SetTrue),
)
.arg(Arg::new(options::CONTEXT).long(options::CONTEXT).value_name("CTX").help(
"like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX",
))
.arg(
Arg::new(options::DIRS)
.action(ArgAction::Append)
Expand All @@ -137,12 +179,12 @@ pub fn uu_app() -> Command {
/**
* Create the list of new directories
*/
fn exec(dirs: ValuesRef<OsString>, recursive: bool, mode: u32, verbose: bool) -> UResult<()> {
fn exec(dirs: ValuesRef<OsString>, config: &Config) -> UResult<()> {
for dir in dirs {
let path_buf = PathBuf::from(dir);
let path = path_buf.as_path();

show_if_err!(mkdir(path, recursive, mode, verbose));
show_if_err!(mkdir(path, config));
}
Ok(())
}
Expand All @@ -160,7 +202,7 @@ fn exec(dirs: ValuesRef<OsString>, recursive: bool, mode: u32, verbose: bool) ->
///
/// To match the GNU behavior, a path with the last directory being a single dot
/// (like `some/path/to/.`) is created (with the dot stripped).
pub fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<()> {
pub fn mkdir(path: &Path, config: &Config) -> UResult<()> {
if path.as_os_str().is_empty() {
return Err(USimpleError::new(
1,
Expand All @@ -173,7 +215,7 @@ pub fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<
// std::fs::create_dir("foo/."); fails in pure Rust
let path_buf = dir_strip_dot_for_creation(path);
let path = path_buf.as_path();
create_dir(path, recursive, verbose, false, mode)
create_dir(path, false, config)
}

#[cfg(any(unix, target_os = "redox"))]
Expand All @@ -194,15 +236,9 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
// Return true if the directory at `path` has been created by this call.
// `is_parent` argument is not used on windows
#[allow(unused_variables)]
fn create_dir(
path: &Path,
recursive: bool,
verbose: bool,
is_parent: bool,
mode: u32,
) -> UResult<()> {
fn create_dir(path: &Path, is_parent: bool, config: &Config) -> UResult<()> {
let path_exists = path.exists();
if path_exists && !recursive {
if path_exists && !config.recursive {
return Err(USimpleError::new(
1,
format!("{}: File exists", path.display()),
Expand All @@ -212,9 +248,9 @@ fn create_dir(
return Ok(());
}

if recursive {
if config.recursive {
match path.parent() {
Some(p) => create_dir(p, recursive, verbose, true, mode)?,
Some(p) => create_dir(p, true, config)?,
None => {
USimpleError::new(1, "failed to create whole tree");
}
Expand All @@ -223,7 +259,7 @@ fn create_dir(

match std::fs::create_dir(path) {
Ok(()) => {
if verbose {
if config.verbose {
println!(
"{}: created directory {}",
uucore::util_name(),
Expand All @@ -233,7 +269,7 @@ fn create_dir(

#[cfg(all(unix, target_os = "linux"))]
let new_mode = if path_exists {
mode
config.mode
} else {
// TODO: Make this macos and freebsd compatible by creating a function to get permission bits from
// acl in extended attributes
Expand All @@ -242,19 +278,33 @@ fn create_dir(
if is_parent {
(!mode::get_umask() & 0o777) | 0o300 | acl_perm_bits
} else {
mode | acl_perm_bits
config.mode | acl_perm_bits
}
};
#[cfg(all(unix, not(target_os = "linux")))]
let new_mode = if is_parent {
(!mode::get_umask() & 0o777) | 0o300
} else {
mode
config.mode
};
#[cfg(windows)]
let new_mode = mode;
let new_mode = config.mode;

chmod(path, new_mode)?;

// Apply SELinux context if requested
#[cfg(feature = "selinux")]
if config.set_selinux_context && uucore::selinux::check_selinux_enabled().is_ok() {
if let Err(e) = uucore::selinux::set_selinux_security_context(path, config.context)
{
let _ = std::fs::remove_dir(path);
return Err(USimpleError::new(
1,
format!("failed to set SELinux security context: {}", e),
));
}
}

Ok(())
}

Expand Down
4 changes: 3 additions & 1 deletion src/uucore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ crc32fast = { workspace = true, optional = true }
regex = { workspace = true, optional = true }
bigdecimal = { workspace = true, optional = true }
num-traits = { workspace = true, optional = true }
selinux = { workspace = true, optional = true }

[target.'cfg(unix)'.dependencies]
walkdir = { workspace = true, optional = true }
Expand Down Expand Up @@ -105,13 +106,14 @@ format = [
mode = ["libc"]
perms = ["entries", "libc", "walkdir"]
buf-copy = []
parser = ["extendedbigdecimal", "glob", "num-traits"]
pipes = []
process = ["libc"]
proc-info = ["tty", "walkdir"]
quoting-style = []
ranges = []
ringbuffer = []
parser = ["extendedbigdecimal", "glob", "num-traits"]
selinux = ["dep:selinux"]
signals = []
sum = [
"digest",
Expand Down
2 changes: 2 additions & 0 deletions src/uucore/src/lib/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub mod tty;

#[cfg(all(unix, feature = "fsxattr"))]
pub mod fsxattr;
#[cfg(all(target_os = "linux", feature = "selinux"))]
pub mod selinux;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub mod signals;
#[cfg(all(
Expand Down
Loading
Loading