use std::io;
use std::os::unix;
use std::os::unix::io::AsRawFd;
use crate::{Int, SocklenT};
#[cfg(target_os = "linux")]
pub type Ucred = libc::ucred;
#[cfg(target_os = "openbsd")]
pub type Ucred = libc::sockpeercred;
#[cfg(target_os = "netbsd")]
pub type Ucred = crate::types::unpcbid;
#[cfg(target_os = "netbsd")]
const SO_PEERCRED: Int = crate::constants::LOCAL_PEEREID;
#[cfg(not(target_os = "netbsd"))]
const SO_PEERCRED: Int = libc::SO_PEERCRED;
pub fn get_ucred_raw(sockfd: Int) -> io::Result<Ucred> {
let mut ucred = Ucred {
pid: 0,
uid: 0,
gid: 0,
};
let len = unsafe {
super::getsockopt_raw(
sockfd,
libc::SOL_SOCKET,
SO_PEERCRED,
std::slice::from_mut(&mut ucred),
)
}?;
if len == std::mem::size_of::<Ucred>() as SocklenT {
Ok(ucred)
} else {
Err(io::Error::from_raw_os_error(libc::EINVAL))
}
}
pub fn get_ucred(sock: &unix::net::UnixStream) -> io::Result<Ucred> {
get_ucred_raw(sock.as_raw_fd())
}
#[cfg(test)]
mod tests {
use super::*;
use std::os::unix::net::UnixStream;
use crate::process;
#[test]
fn test_get_ucred() {
let (a, b) = UnixStream::pair().unwrap();
let acred = get_ucred(&a).unwrap();
assert_eq!(acred.uid, process::getuid());
assert_eq!(acred.gid, process::getgid());
assert_eq!(acred.pid, process::getpid());
let bcred = get_ucred(&b).unwrap();
assert_eq!(bcred.uid, process::getuid());
assert_eq!(bcred.gid, process::getgid());
assert_eq!(bcred.pid, process::getpid());
}
}