#![allow(unsafe_code)]
#[cfg(target_os = "linux")]
pub use lonca_client::sys::peer_cred;
pub use lonca_client::sys::{current_uid, peer_uid};
pub fn raise_open_files(wanted: u64) -> u64 {
let mut l = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
unsafe {
libc::getrlimit(libc::RLIMIT_NOFILE, &mut l);
l.rlim_cur = l.rlim_cur.max(wanted.min(l.rlim_max));
libc::setrlimit(libc::RLIMIT_NOFILE, &l);
libc::getrlimit(libc::RLIMIT_NOFILE, &mut l);
}
l.rlim_cur
}
pub fn kill_group(group: libc::pid_t, signal: libc::c_int) {
unsafe { libc::kill(-group, signal) };
}
pub fn group_named(name: &str) -> Option<u32> {
let c = std::ffi::CString::new(name).ok()?;
let mut size = 1024usize;
while size <= 1 << 20 {
let mut buf = vec![0 as libc::c_char; size];
let mut group: libc::group = unsafe { std::mem::zeroed() };
let mut found: *mut libc::group = std::ptr::null_mut();
let rc = unsafe {
libc::getgrnam_r(
c.as_ptr(),
&mut group,
buf.as_mut_ptr(),
buf.len(),
&mut found,
)
};
if rc == libc::ERANGE {
size *= 4;
continue;
}
return (rc == 0 && !found.is_null()).then_some(group.gr_gid);
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_peer_of_a_pair_is_this_process() {
let (a, _b) = std::os::unix::net::UnixStream::pair().unwrap();
assert_eq!(peer_uid(&a), Some(current_uid()));
}
#[test]
fn groups_resolve_by_name() {
assert!(group_named("wheel").is_some() || group_named("root").is_some());
assert_eq!(group_named("no-such-group-lonca"), None);
assert_eq!(group_named("bad\0name"), None);
}
#[test]
fn the_descriptor_limit_never_falls() {
let before = raise_open_files(0);
assert!(before > 0);
assert!(raise_open_files(before + 1) >= before);
}
}