mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 11:07:44 +00:00
ls: fix the GNU test tests/ls/selinux.sh (#8281)
* ls: fix the GNU test tests/ls/selinux.sh * Remove old comment Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com> * simpli Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com> --------- Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
This commit is contained in:
parent
0923b92921
commit
d04d0cd987
3 changed files with 114 additions and 9 deletions
|
@ -52,4 +52,4 @@ name = "ls"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
feat_selinux = ["selinux"]
|
feat_selinux = ["selinux", "uucore/selinux"]
|
||||||
|
|
|
@ -1900,11 +1900,7 @@ impl PathData {
|
||||||
None => OnceCell::new(),
|
None => OnceCell::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let security_context = if config.context {
|
let security_context = get_security_context(config, &p_buf, must_dereference);
|
||||||
get_security_context(config, &p_buf, must_dereference)
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
md: OnceCell::new(),
|
md: OnceCell::new(),
|
||||||
|
@ -3339,7 +3335,10 @@ fn get_security_context(config: &Config, p_buf: &Path, must_dereference: bool) -
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// The Path couldn't be dereferenced, so return early and set exit code 1
|
// The Path couldn't be dereferenced, so return early and set exit code 1
|
||||||
// to indicate a minor error
|
// to indicate a minor error
|
||||||
|
// Only show error when context display is requested to avoid duplicate messages
|
||||||
|
if config.context {
|
||||||
show!(LsError::IOErrorContext(p_buf.to_path_buf(), err, false));
|
show!(LsError::IOErrorContext(p_buf.to_path_buf(), err, false));
|
||||||
|
}
|
||||||
return substitute_string;
|
return substitute_string;
|
||||||
}
|
}
|
||||||
Ok(_md) => (),
|
Ok(_md) => (),
|
||||||
|
|
|
@ -4263,8 +4263,7 @@ fn test_ls_context_long() {
|
||||||
let line: Vec<_> = result.stdout_str().split(' ').collect();
|
let line: Vec<_> = result.stdout_str().split(' ').collect();
|
||||||
assert!(line[0].ends_with('.'));
|
assert!(line[0].ends_with('.'));
|
||||||
assert!(line[4].starts_with("unconfined_u"));
|
assert!(line[4].starts_with("unconfined_u"));
|
||||||
let s: Vec<_> = line[4].split(':').collect();
|
validate_selinux_context(line[4]);
|
||||||
assert!(s.len() == 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4298,6 +4297,113 @@ fn test_ls_context_format() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to validate `SELinux` context format
|
||||||
|
#[cfg(feature = "feat_selinux")]
|
||||||
|
fn validate_selinux_context(context: &str) {
|
||||||
|
assert!(
|
||||||
|
context.contains(':'),
|
||||||
|
"Expected SELinux context format (user:role:type:level), got: {}",
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
context.split(':').count(),
|
||||||
|
4,
|
||||||
|
"SELinux context should have 4 components separated by colons, got: {}",
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "feat_selinux")]
|
||||||
|
fn test_ls_selinux_context_format() {
|
||||||
|
if !uucore::selinux::is_selinux_enabled() {
|
||||||
|
println!("test skipped: Kernel has no support for SElinux context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.touch("file");
|
||||||
|
at.symlink_file("file", "link");
|
||||||
|
|
||||||
|
// Test that ls -lnZ properly shows the context
|
||||||
|
for file in ["file", "link"] {
|
||||||
|
let result = scene.ucmd().args(&["-lnZ", file]).succeeds();
|
||||||
|
let output = result.stdout_str();
|
||||||
|
|
||||||
|
let lines: Vec<&str> = output.lines().collect();
|
||||||
|
assert!(!lines.is_empty(), "Output should contain at least one line");
|
||||||
|
|
||||||
|
let first_line = lines[0];
|
||||||
|
let parts: Vec<&str> = first_line.split_whitespace().collect();
|
||||||
|
assert!(parts.len() >= 6, "Line should have at least 6 fields");
|
||||||
|
|
||||||
|
// The 5th field (0-indexed position 4) should contain the SELinux context
|
||||||
|
// Format: permissions links owner group context size date time name
|
||||||
|
let context = parts[4];
|
||||||
|
validate_selinux_context(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "feat_selinux")]
|
||||||
|
fn test_ls_selinux_context_indicator() {
|
||||||
|
if !uucore::selinux::is_selinux_enabled() {
|
||||||
|
println!("test skipped: Kernel has no support for SElinux context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.touch("file");
|
||||||
|
at.symlink_file("file", "link");
|
||||||
|
|
||||||
|
// Test that ls -l shows "." indicator for files with SELinux contexts
|
||||||
|
for file in ["file", "link"] {
|
||||||
|
let result = scene.ucmd().args(&["-l", file]).succeeds();
|
||||||
|
let output = result.stdout_str();
|
||||||
|
|
||||||
|
// The 11th character should be "." indicating SELinux context
|
||||||
|
// -rw-rw-r--. (permissions + context indicator)
|
||||||
|
let lines: Vec<&str> = output.lines().collect();
|
||||||
|
assert!(!lines.is_empty(), "Output should contain at least one line");
|
||||||
|
|
||||||
|
let first_line = lines[0];
|
||||||
|
let chars: Vec<char> = first_line.chars().collect();
|
||||||
|
assert!(
|
||||||
|
chars.len() >= 11,
|
||||||
|
"Line should be at least 11 characters long"
|
||||||
|
);
|
||||||
|
|
||||||
|
// The 11th character (0-indexed position 10) should be "." for SELinux context
|
||||||
|
assert_eq!(
|
||||||
|
chars[10], '.',
|
||||||
|
"Expected '.' indicator for SELinux context in position 11, got '{}' in line: {}",
|
||||||
|
chars[10], first_line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that ls -lnZ properly shows the context
|
||||||
|
for file in ["file", "link"] {
|
||||||
|
let result = scene.ucmd().args(&["-lnZ", file]).succeeds();
|
||||||
|
let output = result.stdout_str();
|
||||||
|
|
||||||
|
let lines: Vec<&str> = output.lines().collect();
|
||||||
|
assert!(!lines.is_empty(), "Output should contain at least one line");
|
||||||
|
|
||||||
|
let first_line = lines[0];
|
||||||
|
let parts: Vec<&str> = first_line.split_whitespace().collect();
|
||||||
|
assert!(parts.len() >= 6, "Line should have at least 6 fields");
|
||||||
|
|
||||||
|
// The 5th field (0-indexed position 4) should contain the SELinux context
|
||||||
|
// Format: permissions links owner group context size date time name
|
||||||
|
validate_selinux_context(parts[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn test_ls_a_A() {
|
fn test_ls_a_A() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue