Skip to content

Commit 8c19054

Browse files
committed
install: add test for install with invalid user or group
1 parent af0e509 commit 8c19054

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

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))]
@@ -2660,3 +2664,86 @@ fn test_install_d_symlink_race_condition_concurrent() {
26602664
"Intermediate directory should be a real directory, not a symlink"
26612665
);
26622666
}
2667+
2668+
#[test]
2669+
#[cfg(target_os = "linux")]
2670+
fn test_install_set_owner_nonexistent_uid_and_gid() {
2671+
let file = File::open("/etc/login.defs").unwrap();
2672+
let reader = BufReader::new(file);
2673+
let mut uid_min: u32 = 0;
2674+
let mut uid_max: u32 = 0;
2675+
let mut gid_min: u32 = 0;
2676+
let mut gid_max: u32 = 0;
2677+
for line in reader.lines() {
2678+
let line = line.unwrap();
2679+
if line.starts_with("UID_MIN") {
2680+
let tokens: Vec<&str> = line.split_whitespace().collect();
2681+
uid_min = tokens[1].parse().unwrap();
2682+
}
2683+
if line.starts_with("UID_MAX") {
2684+
let tokens: Vec<&str> = line.split_whitespace().collect();
2685+
uid_max = tokens[1].parse().unwrap();
2686+
}
2687+
if line.starts_with("GID_MIN") {
2688+
let tokens: Vec<&str> = line.split_whitespace().collect();
2689+
gid_min = tokens[1].parse().unwrap();
2690+
}
2691+
if line.starts_with("GID_MAX") {
2692+
let tokens: Vec<&str> = line.split_whitespace().collect();
2693+
gid_max = tokens[1].parse().unwrap();
2694+
}
2695+
}
2696+
let file = File::open("/etc/passwd").unwrap();
2697+
let reader = BufReader::new(file);
2698+
2699+
let mut uids: Vec<u32> = vec![];
2700+
let mut gids: Vec<u32> = vec![];
2701+
for line in reader.lines() {
2702+
let line = line.unwrap();
2703+
let tokens: Vec<&str> = line.split(':').collect();
2704+
let uid: u32 = tokens[2].parse().unwrap();
2705+
if (uid_min..=uid_max).contains(&uid) {
2706+
uids.push(uid);
2707+
}
2708+
let gid: u32 = tokens[3].parse().unwrap();
2709+
if (gid_min..=gid_max).contains(&gid) {
2710+
gids.push(gid);
2711+
}
2712+
}
2713+
uids.sort_unstable();
2714+
2715+
let next_uid = if let Some(uid) = uids.last() {
2716+
*uid + 1
2717+
} else {
2718+
uid_min
2719+
};
2720+
2721+
let next_gid = if let Some(gid) = gids.last() {
2722+
*gid + 1
2723+
} else {
2724+
gid_min
2725+
};
2726+
2727+
let ts = TestScenario::new(util_name!());
2728+
let at = &ts.fixtures;
2729+
at.touch("a");
2730+
2731+
if let Ok(result) = run_ucmd_as_root(
2732+
&ts,
2733+
&[
2734+
format!("-o{next_uid}").as_str(),
2735+
format!("-g{next_gid}").as_str(),
2736+
"a",
2737+
"b",
2738+
],
2739+
) {
2740+
result.success();
2741+
assert!(at.file_exists("b"));
2742+
2743+
let metadata = fs::metadata(at.plus("b")).unwrap();
2744+
assert_eq!(metadata.uid(), next_uid);
2745+
assert_eq!(metadata.gid(), next_gid);
2746+
} else {
2747+
println!("Test skipped; requires root user");
2748+
}
2749+
}

0 commit comments

Comments
 (0)