Skip to content

Commit d28c379

Browse files
committed
install: add test for install with invalid user or group
1 parent 2799daf commit d28c379

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

tests/by-util/test_install.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
use filetime::FileTime;
99
use std::fs;
1010
#[cfg(target_os = "linux")]
11+
use std::fs::File;
12+
#[cfg(target_os = "linux")]
13+
use std::io::{BufRead, BufReader};
14+
#[cfg(target_os = "linux")]
1115
use std::os::unix::ffi::OsStringExt;
1216
use std::os::unix::fs::{MetadataExt, PermissionsExt};
1317
#[cfg(not(windows))]
@@ -2545,3 +2549,86 @@ fn test_install_unprivileged_option_u_skips_chown() {
25452549
assert!(at.file_exists(dst_ok));
25462550
assert_eq!(at.metadata(dst_ok).uid(), geteuid());
25472551
}
2552+
2553+
#[test]
2554+
#[cfg(target_os = "linux")]
2555+
fn test_install_set_owner_nonexistent_uid_and_gid() {
2556+
let file = File::open("/etc/login.defs").unwrap();
2557+
let reader = BufReader::new(file);
2558+
let mut uid_min: u32 = 0;
2559+
let mut uid_max: u32 = 0;
2560+
let mut gid_min: u32 = 0;
2561+
let mut gid_max: u32 = 0;
2562+
for line in reader.lines() {
2563+
let line = line.unwrap();
2564+
if line.starts_with("UID_MIN") {
2565+
let tokens: Vec<&str> = line.split_whitespace().collect();
2566+
uid_min = tokens[1].parse().unwrap();
2567+
}
2568+
if line.starts_with("UID_MAX") {
2569+
let tokens: Vec<&str> = line.split_whitespace().collect();
2570+
uid_max = tokens[1].parse().unwrap();
2571+
}
2572+
if line.starts_with("GID_MIN") {
2573+
let tokens: Vec<&str> = line.split_whitespace().collect();
2574+
gid_min = tokens[1].parse().unwrap();
2575+
}
2576+
if line.starts_with("GID_MAX") {
2577+
let tokens: Vec<&str> = line.split_whitespace().collect();
2578+
gid_max = tokens[1].parse().unwrap();
2579+
}
2580+
}
2581+
let file = File::open("/etc/passwd").unwrap();
2582+
let reader = BufReader::new(file);
2583+
2584+
let mut uids: Vec<u32> = vec![];
2585+
let mut gids: Vec<u32> = vec![];
2586+
for line in reader.lines() {
2587+
let line = line.unwrap();
2588+
let tokens: Vec<&str> = line.split(':').collect();
2589+
let uid: u32 = tokens[2].parse().unwrap();
2590+
if (uid_min..=uid_max).contains(&uid) {
2591+
uids.push(uid);
2592+
}
2593+
let gid: u32 = tokens[3].parse().unwrap();
2594+
if (gid_min..=gid_max).contains(&gid) {
2595+
gids.push(gid);
2596+
}
2597+
}
2598+
uids.sort_unstable();
2599+
2600+
let next_uid = if let Some(uid) = uids.last() {
2601+
*uid + 1
2602+
} else {
2603+
uid_min
2604+
};
2605+
2606+
let next_gid = if let Some(gid) = gids.last() {
2607+
*gid + 1
2608+
} else {
2609+
gid_min
2610+
};
2611+
2612+
let ts = TestScenario::new(util_name!());
2613+
let at = &ts.fixtures;
2614+
at.touch("a");
2615+
2616+
if let Ok(result) = run_ucmd_as_root(
2617+
&ts,
2618+
&[
2619+
format!("-o{next_uid}").as_str(),
2620+
format!("-g{next_gid}").as_str(),
2621+
"a",
2622+
"b",
2623+
],
2624+
) {
2625+
result.success();
2626+
assert!(at.file_exists("b"));
2627+
2628+
let metadata = fs::metadata(at.plus("b")).unwrap();
2629+
assert_eq!(metadata.uid(), next_uid);
2630+
assert_eq!(metadata.gid(), next_gid);
2631+
} else {
2632+
println!("Test skipped; requires root user");
2633+
}
2634+
}

0 commit comments

Comments
 (0)