#[cfg(all(unix, not(target_os = "android")))]
pub fn adjust_nofile() {
use log::{debug, trace};
use std::{io::Error, mem};
unsafe {
let mut lim: libc::rlimit = mem::zeroed();
let ret = libc::getrlimit(libc::RLIMIT_NOFILE, &mut lim);
if ret < 0 {
debug!("getrlimit NOFILE failed, {}", Error::last_os_error());
return;
}
if lim.rlim_cur != lim.rlim_max {
trace!("rlimit NOFILE {:?} require adjustion", lim);
lim.rlim_cur = lim.rlim_max;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
{
use std::ptr;
unsafe extern "C" {
fn sysctlbyname(
name: *const libc::c_char,
oldp: *mut libc::c_void,
oldlenp: *mut libc::size_t,
newp: *mut libc::c_void,
newlen: libc::size_t,
) -> libc::c_int;
}
let name = b"kern.maxfilesperproc\0";
let mut nfile: i32 = 0;
let mut nfile_len: libc::size_t = mem::size_of_val(&nfile);
let ret = sysctlbyname(
name.as_ptr() as *const _,
&mut nfile as *mut _ as *mut _,
&mut nfile_len,
ptr::null_mut(),
0,
);
if ret < 0 {
debug!("sysctlbyname kern.maxfilesperproc failed, {}", Error::last_os_error());
} else {
lim.rlim_cur = nfile as libc::rlim_t;
}
}
let ret = libc::setrlimit(libc::RLIMIT_NOFILE, &lim);
if ret < 0 {
debug!("setrlimit NOFILE {:?} failed, {}", lim, Error::last_os_error());
} else {
debug!("rlimit NOFILE adjusted {:?}", lim);
}
}
}
}
#[cfg(unix)]
pub fn run_as_user(uname: &str) -> std::io::Result<()> {
use log::error;
use std::{
ffi::{CStr, CString},
io::{Error, ErrorKind},
};
unsafe {
let pwd = match uname.parse::<libc::uid_t>() {
Ok(uid) => {
let mut pwd = libc::getpwuid(uid);
if pwd.is_null() {
let uname = CString::new(uname).expect("username");
pwd = libc::getpwnam(uname.as_ptr())
}
pwd
}
Err(..) => {
let uname = CString::new(uname).expect("username");
libc::getpwnam(uname.as_ptr())
}
};
if pwd.is_null() {
return Err(Error::new(ErrorKind::InvalidInput, format!("user {} not found", uname)));
}
let pwd = &*pwd;
if libc::setgid(pwd.pw_gid as libc::gid_t) != 0 {
let err = Error::last_os_error();
error!(
"could not change group id to user {:?}'s gid: {}, uid: {}, error: {}",
CStr::from_ptr(pwd.pw_name),
pwd.pw_gid,
pwd.pw_uid,
err
);
return Err(err);
}
if libc::initgroups(pwd.pw_name, pwd.pw_gid as _) != 0 {
let err = Error::last_os_error();
error!(
"could not change supplementary groups to user {:?}'s gid: {}, uid: {}, error: {}",
CStr::from_ptr(pwd.pw_name),
pwd.pw_gid,
pwd.pw_uid,
err
);
return Err(err);
}
if libc::setuid(pwd.pw_uid) != 0 {
let err = Error::last_os_error();
error!(
"could not change user id to user {:?}'s gid: {}, uid: {}, error: {}",
CStr::from_ptr(pwd.pw_name),
pwd.pw_gid,
pwd.pw_uid,
err
);
return Err(err);
}
}
Ok(())
}