1#[cfg(all(unix, not(target_os = "android")))]
12pub fn adjust_nofile() {
13 use log::{debug, trace};
14 use std::{io::Error, mem};
15
16 unsafe {
17 let mut lim: libc::rlimit = mem::zeroed();
18 let ret = libc::getrlimit(libc::RLIMIT_NOFILE, &mut lim);
19 if ret < 0 {
20 debug!("getrlimit NOFILE failed, {}", Error::last_os_error());
21 return;
22 }
23
24 if lim.rlim_cur != lim.rlim_max {
25 trace!("rlimit NOFILE {:?} require adjustion", lim);
26 lim.rlim_cur = lim.rlim_max;
27
28 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
30 {
31 use std::ptr;
32
33 unsafe extern "C" {
34 fn sysctlbyname(
35 name: *const libc::c_char,
36 oldp: *mut libc::c_void,
37 oldlenp: *mut libc::size_t,
38 newp: *mut libc::c_void,
39 newlen: libc::size_t,
40 ) -> libc::c_int;
41 }
42
43 let name = b"kern.maxfilesperproc\0";
50 let mut nfile: i32 = 0;
51 let mut nfile_len: libc::size_t = mem::size_of_val(&nfile);
52
53 let ret = sysctlbyname(
54 name.as_ptr() as *const _,
55 &mut nfile as *mut _ as *mut _,
56 &mut nfile_len,
57 ptr::null_mut(),
58 0,
59 );
60
61 if ret < 0 {
62 debug!("sysctlbyname kern.maxfilesperproc failed, {}", Error::last_os_error());
63 } else {
64 lim.rlim_cur = nfile as libc::rlim_t;
65 }
66 }
67
68 let ret = libc::setrlimit(libc::RLIMIT_NOFILE, &lim);
69 if ret < 0 {
70 debug!("setrlimit NOFILE {:?} failed, {}", lim, Error::last_os_error());
71 } else {
72 debug!("rlimit NOFILE adjusted {:?}", lim);
73 }
74 }
75 }
76}
77
78#[cfg(unix)]
80pub fn run_as_user(uname: &str) -> std::io::Result<()> {
81 use log::error;
82 use std::{
83 ffi::{CStr, CString},
84 io::{Error, ErrorKind},
85 };
86
87 unsafe {
88 let pwd = match uname.parse::<libc::uid_t>() {
89 Ok(uid) => {
90 let mut pwd = libc::getpwuid(uid);
91 if pwd.is_null() {
92 let uname = CString::new(uname).expect("username");
93 pwd = libc::getpwnam(uname.as_ptr())
94 }
95 pwd
96 }
97 Err(..) => {
98 let uname = CString::new(uname).expect("username");
99 libc::getpwnam(uname.as_ptr())
100 }
101 };
102
103 if pwd.is_null() {
104 return Err(Error::new(ErrorKind::InvalidInput, format!("user {} not found", uname)));
105 }
106
107 let pwd = &*pwd;
108
109 if libc::setgid(pwd.pw_gid as libc::gid_t) != 0 {
111 let err = Error::last_os_error();
112
113 error!(
114 "could not change group id to user {:?}'s gid: {}, uid: {}, error: {}",
115 CStr::from_ptr(pwd.pw_name),
116 pwd.pw_gid,
117 pwd.pw_uid,
118 err
119 );
120 return Err(err);
121 }
122
123 if libc::initgroups(pwd.pw_name, pwd.pw_gid as _) != 0 {
124 let err = Error::last_os_error();
125 error!(
126 "could not change supplementary groups to user {:?}'s gid: {}, uid: {}, error: {}",
127 CStr::from_ptr(pwd.pw_name),
128 pwd.pw_gid,
129 pwd.pw_uid,
130 err
131 );
132 return Err(err);
133 }
134
135 if libc::setuid(pwd.pw_uid) != 0 {
136 let err = Error::last_os_error();
137 error!(
138 "could not change user id to user {:?}'s gid: {}, uid: {}, error: {}",
139 CStr::from_ptr(pwd.pw_name),
140 pwd.pw_gid,
141 pwd.pw_uid,
142 err
143 );
144 return Err(err);
145 }
146 }
147
148 Ok(())
149}