Skip to content

Commit 8a7cbe4

Browse files
authored
Merge pull request #379 from marcus0x62/fix_chgrp_tests
More resilient secondary group selection for chgrp tests
2 parents 895c4fa + ce92fe2 commit 8a7cbe4

File tree

1 file changed

+61
-4
lines changed

1 file changed

+61
-4
lines changed

tree/tests/chgrp/mod.rs

+61-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ fn chgrp_test(args: &[&str], expected_output: &str, expected_error: &str, expect
3333
});
3434
}
3535

36+
static INIT_GROUPS: Once = Once::new();
3637
static mut PRIMARY_GROUP: String = String::new();
37-
static INIT_PRIMARY_GROUP: Once = Once::new();
38+
static mut SECONDARY_GROUP: String = String::new();
3839

3940
static mut GID1: u32 = 0;
4041
static mut GID2: u32 = 0;
@@ -53,11 +54,12 @@ fn get_group_id(name: &CStr) -> u32 {
5354

5455
// Return two groups that the current user belongs to.
5556
fn get_groups() -> ((String, u32), (String, u32)) {
56-
// Linux - (primary group of current user, "adm")
57+
// Linux - (primary group of current user, a group in the supplemental group list that
58+
// is not the primary group)
5759
// macOS - ("staff", "admin")
5860
let (g1, g2) = if cfg!(target_os = "linux") {
5961
unsafe {
60-
INIT_PRIMARY_GROUP.call_once(|| {
62+
INIT_GROUPS.call_once(|| {
6163
let uid = libc::getuid();
6264
let pw = libc::getpwuid(uid);
6365
if pw.is_null() {
@@ -72,8 +74,63 @@ fn get_groups() -> ((String, u32), (String, u32)) {
7274

7375
let gr_name = CStr::from_ptr((&*gr).gr_name).to_owned();
7476
PRIMARY_GROUP = gr_name.to_str().unwrap().to_owned();
77+
78+
let mut count = libc::getgroups(0, std::ptr::null_mut());
79+
if count < 0 {
80+
panic!(
81+
"unable to determine number of secondary groups {}",
82+
io::Error::last_os_error()
83+
);
84+
}
85+
86+
let mut groups_ptr: *mut libc::gid_t =
87+
libc::malloc(std::mem::size_of::<libc::gid_t>() * count as usize)
88+
as *mut libc::gid_t;
89+
90+
if groups_ptr.is_null() {
91+
panic!(
92+
"unable to allocate memory for groups list: {}",
93+
io::Error::last_os_error()
94+
);
95+
}
96+
97+
count = libc::getgroups(count, groups_ptr);
98+
match count {
99+
_ if count < 2 => panic!("user must be a member of at least two groups"),
100+
-1 => panic!(
101+
"unable to get secondary groups: {}",
102+
io::Error::last_os_error()
103+
),
104+
_ => {}
105+
}
106+
107+
for _ in 0..count {
108+
if groups_ptr.is_null() {
109+
panic!("unable to get second group: reached end of group list");
110+
}
111+
112+
// Skip over the primary_gid
113+
if *groups_ptr == primary_gid {
114+
groups_ptr = groups_ptr.offset(1);
115+
continue;
116+
} else {
117+
let second_gid = *groups_ptr;
118+
let sec_grent = libc::getgrgid(second_gid);
119+
if sec_grent.is_null() {
120+
panic!("Unable to get group entry for secondary group id {second_gid}");
121+
}
122+
123+
let sec_gr_name = CStr::from_ptr((&*sec_grent).gr_name).to_owned();
124+
SECONDARY_GROUP = sec_gr_name.to_str().unwrap().to_owned();
125+
break;
126+
}
127+
}
128+
if SECONDARY_GROUP == "" {
129+
panic!("unable to find suitable secondary group");
130+
}
75131
});
76-
(PRIMARY_GROUP.clone(), "adm".to_owned())
132+
133+
(PRIMARY_GROUP.clone(), SECONDARY_GROUP.clone())
77134
}
78135
} else if cfg!(target_os = "macos") {
79136
("staff".to_owned(), "admin".to_owned())

0 commit comments

Comments
 (0)