mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
test_ls: add/adjust tests for SELinux context
This commit is contained in:
parent
fe3645d4d5
commit
e018a45b54
2 changed files with 94 additions and 45 deletions
|
@ -639,10 +639,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
.map(|v| v.map(Path::new).collect())
|
.map(|v| v.map(Path::new).collect())
|
||||||
.unwrap_or_else(|| vec![Path::new(".")]);
|
.unwrap_or_else(|| vec![Path::new(".")]);
|
||||||
|
|
||||||
if config.context && !config.selinux_supported {
|
|
||||||
show_warning!("--context (-Z) works only on an SELinux-enabled kernel",);
|
|
||||||
}
|
|
||||||
|
|
||||||
list(locs, config)
|
list(locs, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,7 +1256,7 @@ impl PathData {
|
||||||
None => OnceCell::new(),
|
None => OnceCell::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let security_context: String = if config.context {
|
let security_context = if config.context {
|
||||||
if config.selinux_supported {
|
if config.selinux_supported {
|
||||||
#[cfg(feature = "selinux")]
|
#[cfg(feature = "selinux")]
|
||||||
{
|
{
|
||||||
|
@ -1692,9 +1688,9 @@ fn display_item_long(
|
||||||
out,
|
out,
|
||||||
"{}{} {}",
|
"{}{} {}",
|
||||||
display_permissions(md, true),
|
display_permissions(md, true),
|
||||||
if item.security_context != "?" {
|
if item.security_context.len() > 1 {
|
||||||
// GNU `ls` uses a "." character to indicate a file with a security context, but not
|
// GNU `ls` uses a "." character to indicate a file with a security context,
|
||||||
// other alternate access method.
|
// but not other alternate access method.
|
||||||
"."
|
"."
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
|
|
@ -347,6 +347,7 @@ fn test_ls_long_format() {
|
||||||
// A line of the output should be:
|
// A line of the output should be:
|
||||||
// One of the characters -bcCdDlMnpPsStTx?
|
// One of the characters -bcCdDlMnpPsStTx?
|
||||||
// rwx, with - for missing permissions, thrice.
|
// rwx, with - for missing permissions, thrice.
|
||||||
|
// Zero or one "." for indicating a file with security context
|
||||||
// A number, preceded by column whitespace, and followed by a single space.
|
// A number, preceded by column whitespace, and followed by a single space.
|
||||||
// A username, currently [^ ], followed by column whitespace, twice (or thrice for Hurd).
|
// A username, currently [^ ], followed by column whitespace, twice (or thrice for Hurd).
|
||||||
// A number, followed by a single space.
|
// A number, followed by a single space.
|
||||||
|
@ -356,13 +357,13 @@ fn test_ls_long_format() {
|
||||||
// and followed by a single space.
|
// and followed by a single space.
|
||||||
// Whatever comes after is irrelevant to this specific test.
|
// Whatever comes after is irrelevant to this specific test.
|
||||||
scene.ucmd().arg(arg).arg("test-long-dir").succeeds().stdout_matches(&Regex::new(
|
scene.ucmd().arg(arg).arg("test-long-dir").succeeds().stdout_matches(&Regex::new(
|
||||||
r"\n[-bcCdDlMnpPsStTx?]([r-][w-][xt-]){3} +\d+ [^ ]+ +[^ ]+( +[^ ]+)? +\d+ [A-Z][a-z]{2} {0,2}\d{0,2} {0,2}[0-9:]+ "
|
r"\n[-bcCdDlMnpPsStTx?]([r-][w-][xt-]){3}\.? +\d+ [^ ]+ +[^ ]+( +[^ ]+)? +\d+ [A-Z][a-z]{2} {0,2}\d{0,2} {0,2}[0-9:]+ "
|
||||||
).unwrap());
|
).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This checks for the line with the .. entry. The uname and group should be digits.
|
// This checks for the line with the .. entry. The uname and group should be digits.
|
||||||
scene.ucmd().arg("-lan").arg("test-long-dir").succeeds().stdout_matches(&Regex::new(
|
scene.ucmd().arg("-lan").arg("test-long-dir").succeeds().stdout_matches(&Regex::new(
|
||||||
r"\nd([r-][w-][xt-]){3} +\d+ \d+ +\d+( +\d+)? +\d+ [A-Z][a-z]{2} {0,2}\d{0,2} {0,2}[0-9:]+ \.\."
|
r"\nd([r-][w-][xt-]){3}\.? +\d+ \d+ +\d+( +\d+)? +\d+ [A-Z][a-z]{2} {0,2}\d{0,2} {0,2}[0-9:]+ \.\."
|
||||||
).unwrap());
|
).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,6 +371,7 @@ fn test_ls_long_format() {
|
||||||
/// This test is mainly about coloring, but, the recursion, symlink `->` processing,
|
/// This test is mainly about coloring, but, the recursion, symlink `->` processing,
|
||||||
/// and `.` and `..` being present in `-a` all need to work for the test to pass.
|
/// and `.` and `..` being present in `-a` all need to work for the test to pass.
|
||||||
/// This test does not really test anything provided by `-l` but the file names and symlinks.
|
/// This test does not really test anything provided by `-l` but the file names and symlinks.
|
||||||
|
#[cfg(all(feature = "ln", feature = "mkdir", feature = "touch"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ls_long_symlink_color() {
|
fn test_ls_long_symlink_color() {
|
||||||
// If you break this test after breaking mkdir, touch, or ln, do not be alarmed!
|
// If you break this test after breaking mkdir, touch, or ln, do not be alarmed!
|
||||||
|
@ -639,55 +641,57 @@ fn test_ls_long_formats() {
|
||||||
let at = &scene.fixtures;
|
let at = &scene.fixtures;
|
||||||
at.touch(&at.plus_as_string("test-long-formats"));
|
at.touch(&at.plus_as_string("test-long-formats"));
|
||||||
|
|
||||||
|
// Zero or one "." for indicating a file with security context
|
||||||
|
|
||||||
// Regex for three names, so all of author, group and owner
|
// Regex for three names, so all of author, group and owner
|
||||||
let re_three = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){3}0").unwrap();
|
let re_three = Regex::new(r"[xrw-]{9}\.? \d ([-0-9_a-z]+ ){3}0").unwrap();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let re_three_num = Regex::new(r"[xrw-]{9} \d (\d+ ){3}0").unwrap();
|
let re_three_num = Regex::new(r"[xrw-]{9}\.? \d (\d+ ){3}0").unwrap();
|
||||||
|
|
||||||
// Regex for two names, either:
|
// Regex for two names, either:
|
||||||
// - group and owner
|
// - group and owner
|
||||||
// - author and owner
|
// - author and owner
|
||||||
// - author and group
|
// - author and group
|
||||||
let re_two = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){2}0").unwrap();
|
let re_two = Regex::new(r"[xrw-]{9}\.? \d ([-0-9_a-z]+ ){2}0").unwrap();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let re_two_num = Regex::new(r"[xrw-]{9} \d (\d+ ){2}0").unwrap();
|
let re_two_num = Regex::new(r"[xrw-]{9}\.? \d (\d+ ){2}0").unwrap();
|
||||||
|
|
||||||
// Regex for one name: author, group or owner
|
// Regex for one name: author, group or owner
|
||||||
let re_one = Regex::new(r"[xrw-]{9} \d [-0-9_a-z]+ 0").unwrap();
|
let re_one = Regex::new(r"[xrw-]{9}\.? \d [-0-9_a-z]+ 0").unwrap();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let re_one_num = Regex::new(r"[xrw-]{9} \d \d+ 0").unwrap();
|
let re_one_num = Regex::new(r"[xrw-]{9}\.? \d \d+ 0").unwrap();
|
||||||
|
|
||||||
// Regex for no names
|
// Regex for no names
|
||||||
let re_zero = Regex::new(r"[xrw-]{9} \d 0").unwrap();
|
let re_zero = Regex::new(r"[xrw-]{9}\.? \d 0").unwrap();
|
||||||
|
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-l")
|
.arg("-l")
|
||||||
.arg("--author")
|
.arg("--author")
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_three.is_match(result.stdout_str()));
|
.stdout_matches(&re_three);
|
||||||
|
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-l1")
|
.arg("-l1")
|
||||||
.arg("--author")
|
.arg("--author")
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_three.is_match(result.stdout_str()));
|
.stdout_matches(&re_three);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.arg("--author")
|
.arg("--author")
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_three_num.is_match(result.stdout_str()));
|
.stdout_matches(&re_three_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg in &[
|
for arg in &[
|
||||||
|
@ -697,22 +701,22 @@ fn test_ls_long_formats() {
|
||||||
"-lG --author", // only author and owner
|
"-lG --author", // only author and owner
|
||||||
"-l --no-group --author", // only author and owner
|
"-l --no-group --author", // only author and owner
|
||||||
] {
|
] {
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_two.is_match(result.stdout_str()));
|
.stdout_matches(&re_two);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_two_num.is_match(result.stdout_str()));
|
.stdout_matches(&re_two_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,22 +730,22 @@ fn test_ls_long_formats() {
|
||||||
"-l --no-group", // only owner
|
"-l --no-group", // only owner
|
||||||
"-gG --author", // only author
|
"-gG --author", // only author
|
||||||
] {
|
] {
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_one.is_match(result.stdout_str()));
|
.stdout_matches(&re_one);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_one_num.is_match(result.stdout_str()));
|
.stdout_matches(&re_one_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,22 +762,22 @@ fn test_ls_long_formats() {
|
||||||
"-og1",
|
"-og1",
|
||||||
"-og1l",
|
"-og1l",
|
||||||
] {
|
] {
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_zero.is_match(result.stdout_str()));
|
.stdout_matches(&re_zero);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
let result = scene
|
scene
|
||||||
.ucmd()
|
.ucmd()
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.args(&arg.split(' ').collect::<Vec<_>>())
|
.args(&arg.split(' ').collect::<Vec<_>>())
|
||||||
.arg("test-long-formats")
|
.arg("test-long-formats")
|
||||||
.succeeds();
|
.succeeds()
|
||||||
assert!(re_zero.is_match(result.stdout_str()));
|
.stdout_matches(&re_zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1251,7 +1255,7 @@ fn test_ls_inode() {
|
||||||
at.touch(file);
|
at.touch(file);
|
||||||
|
|
||||||
let re_short = Regex::new(r" *(\d+) test_inode").unwrap();
|
let re_short = Regex::new(r" *(\d+) test_inode").unwrap();
|
||||||
let re_long = Regex::new(r" *(\d+) [xrw-]{10} \d .+ test_inode").unwrap();
|
let re_long = Regex::new(r" *(\d+) [xrw-]{10}\.? \d .+ test_inode").unwrap();
|
||||||
|
|
||||||
let result = scene.ucmd().arg("test_inode").arg("-i").succeeds();
|
let result = scene.ucmd().arg("test_inode").arg("-i").succeeds();
|
||||||
assert!(re_short.is_match(result.stdout_str()));
|
assert!(re_short.is_match(result.stdout_str()));
|
||||||
|
@ -2275,3 +2279,52 @@ fn test_ls_dangling_symlinks() {
|
||||||
.succeeds() // this should fail, though at the moment, ls lacks a way to propagate errors encountered during display
|
.succeeds() // this should fail, though at the moment, ls lacks a way to propagate errors encountered during display
|
||||||
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
|
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "feat_selinux")]
|
||||||
|
fn test_ls_context() {
|
||||||
|
use selinux::{self, KernelSupport};
|
||||||
|
if selinux::kernel_support() == KernelSupport::Unsupported {
|
||||||
|
println!("test skipped: Kernel has no support for SElinux context",);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
for c_flag in &["-Z", "--context"] {
|
||||||
|
ts.ucmd()
|
||||||
|
.args(&[c_flag, &"/"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only(unwrap_or_return!(expected_result(&ts, &[c_flag, &"/"])).stdout_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "feat_selinux")]
|
||||||
|
fn test_ls_context_format() {
|
||||||
|
use selinux::{self, KernelSupport};
|
||||||
|
if selinux::kernel_support() == KernelSupport::Unsupported {
|
||||||
|
println!("test skipped: Kernel has no support for SElinux context",);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ts = TestScenario::new(util_name!());
|
||||||
|
// NOTE:
|
||||||
|
// --format=long/verbose matches the output of GNU's ls for --context
|
||||||
|
// except for the size count which may differ to the size count reported by GNU's ls.
|
||||||
|
for word in &[
|
||||||
|
"across",
|
||||||
|
"commas",
|
||||||
|
"horizontal",
|
||||||
|
// "long",
|
||||||
|
"single-column",
|
||||||
|
// "verbose",
|
||||||
|
"vertical",
|
||||||
|
] {
|
||||||
|
let format = format!("--format={}", word);
|
||||||
|
ts.ucmd()
|
||||||
|
.args(&[&"-Z", &format.as_str(), &"/"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only(
|
||||||
|
unwrap_or_return!(expected_result(&ts, &[&"-Z", &format.as_str(), &"/"]))
|
||||||
|
.stdout_str(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue