use crate::{FromInner, IntoInner};
use std::ffi::CStr;
use uv::{
uv_available_parallelism, uv_group_t, uv_os_free_group, uv_os_free_passwd, uv_os_get_group,
uv_os_get_passwd, uv_os_get_passwd2, uv_os_gethostname, uv_os_getpid, uv_os_getppid,
uv_os_getpriority, uv_os_setpriority, uv_os_uname, uv_passwd_t, uv_utsname_t,
UV_MAXHOSTNAMESIZE,
};
pub type Pid = i32;
pub struct User {
pub username: String,
pub uid: Option<crate::Uid>,
pub gid: Option<crate::Gid>,
pub shell: Option<String>,
pub homedir: String,
}
impl FromInner<uv_passwd_t> for User {
fn from_inner(passwd: uv_passwd_t) -> User {
let username = unsafe { CStr::from_ptr(passwd.username) }
.to_string_lossy()
.into_owned();
let homedir = unsafe { CStr::from_ptr(passwd.homedir) }
.to_string_lossy()
.into_owned();
let shell = if passwd.shell.is_null() {
None
} else {
Some(
unsafe { CStr::from_ptr(passwd.shell) }
.to_string_lossy()
.into_owned(),
)
};
let uid = if passwd.uid >= 0 {
Some(passwd.uid as _)
} else {
None
};
let gid = if passwd.gid >= 0 {
Some(passwd.gid as _)
} else {
None
};
User {
username,
uid,
gid,
shell,
homedir,
}
}
}
pub struct Group {
pub groupname: String,
pub gid: Option<crate::Gid>,
pub members: Vec<String>,
}
impl FromInner<uv_group_t> for Group {
fn from_inner(group: uv_group_t) -> Group {
let groupname = unsafe { CStr::from_ptr(group.groupname) }
.to_string_lossy()
.into_owned();
let gid = if group.gid >= 0 {
Some(group.gid as _)
} else {
None
};
let mut members = Vec::new();
let mut members_ptr = group.members;
unsafe {
while let Some(member_ptr) = members_ptr.as_ref() {
let member = CStr::from_ptr(*member_ptr).to_string_lossy().into_owned();
members.push(member);
members_ptr = members_ptr.offset(1);
}
}
Group {
groupname,
gid,
members,
}
}
}
pub struct SystemInfo {
pub sysname: String,
pub release: String,
pub version: String,
pub machine: String,
}
impl FromInner<uv_utsname_t> for SystemInfo {
fn from_inner(uname: uv_utsname_t) -> SystemInfo {
let sysname = unsafe { CStr::from_ptr(&uname.sysname as _) }
.to_string_lossy()
.into_owned();
let release = unsafe { CStr::from_ptr(&uname.release as _) }
.to_string_lossy()
.into_owned();
let version = unsafe { CStr::from_ptr(&uname.version as _) }
.to_string_lossy()
.into_owned();
let machine = unsafe { CStr::from_ptr(&uname.machine as _) }
.to_string_lossy()
.into_owned();
SystemInfo {
sysname,
release,
version,
machine,
}
}
}
pub fn get_passwd() -> crate::Result<User> {
let mut passwd: uv_passwd_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_os_get_passwd(&mut passwd as _) })?;
let result = passwd.into_inner();
unsafe { uv_os_free_passwd(&mut passwd as _) };
Ok(result)
}
pub fn get_passwd2(uid: crate::Uid) -> crate::Result<User> {
let mut passwd: uv_passwd_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_os_get_passwd2(&mut passwd as _, uid) })?;
let result = passwd.into_inner();
unsafe { uv_os_free_passwd(&mut passwd as _) };
Ok(result)
}
pub fn get_group(gid: crate::Gid) -> crate::Result<Group> {
let mut group: uv_group_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_os_get_group(&mut group as _, gid) })?;
let result = group.into_inner();
unsafe { uv_os_free_group(&mut group as _) };
Ok(result)
}
pub fn gethostname() -> crate::Result<String> {
let mut size = UV_MAXHOSTNAMESIZE as usize;
let mut buf: Vec<std::os::raw::c_uchar> = Vec::with_capacity(size as _);
crate::uvret(unsafe { uv_os_gethostname(buf.as_mut_ptr() as _, &mut size as _) }).map(|_| {
unsafe { buf.set_len((size as usize) + 1) };
unsafe { CStr::from_bytes_with_nul_unchecked(&buf) }
.to_string_lossy()
.into_owned()
})
}
pub fn getpid() -> Pid {
unsafe { uv_os_getpid() as _ }
}
pub fn getppid() -> Pid {
unsafe { uv_os_getppid() as _ }
}
pub fn available_parallelism() -> u32 {
unsafe { uv_available_parallelism() as _ }
}
pub fn getpriority(pid: Pid) -> crate::Result<i32> {
let mut priority = 0i32;
crate::uvret(unsafe { uv_os_getpriority(pid as _, &mut priority as _) }).map(|_| priority)
}
pub fn setpriority(pid: Pid, priority: i32) -> crate::Result<()> {
crate::uvret(unsafe { uv_os_setpriority(pid as _, priority as _) })
}
pub fn uname() -> crate::Result<SystemInfo> {
let mut buf: uv_utsname_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_os_uname(&mut buf as _) })?;
Ok(buf.into_inner())
}