13da5c369Sopenharmony_ci//! Safe wrappers around functions found in libc "unistd.h" header 23da5c369Sopenharmony_ci 33da5c369Sopenharmony_ciuse crate::errno::{self, Errno}; 43da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 53da5c369Sopenharmony_ci#[cfg(feature = "fs")] 63da5c369Sopenharmony_ciuse crate::fcntl::{at_rawfd, AtFlags}; 73da5c369Sopenharmony_ci#[cfg(feature = "fs")] 83da5c369Sopenharmony_ciuse crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag}; 93da5c369Sopenharmony_ci#[cfg(all( 103da5c369Sopenharmony_ci feature = "fs", 113da5c369Sopenharmony_ci any( 123da5c369Sopenharmony_ci target_os = "openbsd", 133da5c369Sopenharmony_ci target_os = "netbsd", 143da5c369Sopenharmony_ci target_os = "freebsd", 153da5c369Sopenharmony_ci target_os = "dragonfly", 163da5c369Sopenharmony_ci target_os = "macos", 173da5c369Sopenharmony_ci target_os = "ios" 183da5c369Sopenharmony_ci ) 193da5c369Sopenharmony_ci))] 203da5c369Sopenharmony_ciuse crate::sys::stat::FileFlag; 213da5c369Sopenharmony_ci#[cfg(feature = "fs")] 223da5c369Sopenharmony_ciuse crate::sys::stat::Mode; 233da5c369Sopenharmony_ciuse crate::{Error, NixPath, Result}; 243da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 253da5c369Sopenharmony_ciuse cfg_if::cfg_if; 263da5c369Sopenharmony_ciuse libc::{ 273da5c369Sopenharmony_ci self, c_char, c_int, c_long, c_uint, c_void, gid_t, mode_t, off_t, pid_t, 283da5c369Sopenharmony_ci size_t, uid_t, PATH_MAX, 293da5c369Sopenharmony_ci}; 303da5c369Sopenharmony_ciuse std::convert::Infallible; 313da5c369Sopenharmony_ciuse std::ffi::{CStr, OsString}; 323da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 333da5c369Sopenharmony_ciuse std::ffi::{CString, OsStr}; 343da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 353da5c369Sopenharmony_ciuse std::os::unix::ffi::OsStrExt; 363da5c369Sopenharmony_ciuse std::os::unix::ffi::OsStringExt; 373da5c369Sopenharmony_ciuse std::os::unix::io::RawFd; 383da5c369Sopenharmony_ciuse std::path::PathBuf; 393da5c369Sopenharmony_ciuse std::{fmt, mem, ptr}; 403da5c369Sopenharmony_ci 413da5c369Sopenharmony_cifeature! { 423da5c369Sopenharmony_ci #![feature = "fs"] 433da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 443da5c369Sopenharmony_ci pub use self::pivot_root::*; 453da5c369Sopenharmony_ci} 463da5c369Sopenharmony_ci 473da5c369Sopenharmony_ci#[cfg(any( 483da5c369Sopenharmony_ci target_os = "android", 493da5c369Sopenharmony_ci target_os = "dragonfly", 503da5c369Sopenharmony_ci target_os = "freebsd", 513da5c369Sopenharmony_ci target_os = "linux", 523da5c369Sopenharmony_ci target_os = "openbsd" 533da5c369Sopenharmony_ci))] 543da5c369Sopenharmony_cipub use self::setres::*; 553da5c369Sopenharmony_ci 563da5c369Sopenharmony_ci#[cfg(any( 573da5c369Sopenharmony_ci target_os = "android", 583da5c369Sopenharmony_ci target_os = "dragonfly", 593da5c369Sopenharmony_ci target_os = "freebsd", 603da5c369Sopenharmony_ci target_os = "linux", 613da5c369Sopenharmony_ci target_os = "openbsd" 623da5c369Sopenharmony_ci))] 633da5c369Sopenharmony_cipub use self::getres::*; 643da5c369Sopenharmony_ci 653da5c369Sopenharmony_cifeature! { 663da5c369Sopenharmony_ci#![feature = "user"] 673da5c369Sopenharmony_ci 683da5c369Sopenharmony_ci/// User identifier 693da5c369Sopenharmony_ci/// 703da5c369Sopenharmony_ci/// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally 713da5c369Sopenharmony_ci/// passing wrong value. 723da5c369Sopenharmony_ci#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 733da5c369Sopenharmony_cipub struct Uid(uid_t); 743da5c369Sopenharmony_ci 753da5c369Sopenharmony_ciimpl Uid { 763da5c369Sopenharmony_ci /// Creates `Uid` from raw `uid_t`. 773da5c369Sopenharmony_ci pub const fn from_raw(uid: uid_t) -> Self { 783da5c369Sopenharmony_ci Uid(uid) 793da5c369Sopenharmony_ci } 803da5c369Sopenharmony_ci 813da5c369Sopenharmony_ci /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`. 823da5c369Sopenharmony_ci #[doc(alias("getuid"))] 833da5c369Sopenharmony_ci pub fn current() -> Self { 843da5c369Sopenharmony_ci getuid() 853da5c369Sopenharmony_ci } 863da5c369Sopenharmony_ci 873da5c369Sopenharmony_ci /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`. 883da5c369Sopenharmony_ci #[doc(alias("geteuid"))] 893da5c369Sopenharmony_ci pub fn effective() -> Self { 903da5c369Sopenharmony_ci geteuid() 913da5c369Sopenharmony_ci } 923da5c369Sopenharmony_ci 933da5c369Sopenharmony_ci /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.) 943da5c369Sopenharmony_ci pub const fn is_root(self) -> bool { 953da5c369Sopenharmony_ci self.0 == ROOT.0 963da5c369Sopenharmony_ci } 973da5c369Sopenharmony_ci 983da5c369Sopenharmony_ci /// Get the raw `uid_t` wrapped by `self`. 993da5c369Sopenharmony_ci pub const fn as_raw(self) -> uid_t { 1003da5c369Sopenharmony_ci self.0 1013da5c369Sopenharmony_ci } 1023da5c369Sopenharmony_ci} 1033da5c369Sopenharmony_ci 1043da5c369Sopenharmony_ciimpl From<Uid> for uid_t { 1053da5c369Sopenharmony_ci fn from(uid: Uid) -> Self { 1063da5c369Sopenharmony_ci uid.0 1073da5c369Sopenharmony_ci } 1083da5c369Sopenharmony_ci} 1093da5c369Sopenharmony_ci 1103da5c369Sopenharmony_ciimpl From<uid_t> for Uid { 1113da5c369Sopenharmony_ci fn from(uid: uid_t) -> Self { 1123da5c369Sopenharmony_ci Uid(uid) 1133da5c369Sopenharmony_ci } 1143da5c369Sopenharmony_ci} 1153da5c369Sopenharmony_ci 1163da5c369Sopenharmony_ciimpl fmt::Display for Uid { 1173da5c369Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1183da5c369Sopenharmony_ci fmt::Display::fmt(&self.0, f) 1193da5c369Sopenharmony_ci } 1203da5c369Sopenharmony_ci} 1213da5c369Sopenharmony_ci 1223da5c369Sopenharmony_ci/// Constant for UID = 0 1233da5c369Sopenharmony_cipub const ROOT: Uid = Uid(0); 1243da5c369Sopenharmony_ci 1253da5c369Sopenharmony_ci/// Group identifier 1263da5c369Sopenharmony_ci/// 1273da5c369Sopenharmony_ci/// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally 1283da5c369Sopenharmony_ci/// passing wrong value. 1293da5c369Sopenharmony_ci#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 1303da5c369Sopenharmony_cipub struct Gid(gid_t); 1313da5c369Sopenharmony_ci 1323da5c369Sopenharmony_ciimpl Gid { 1333da5c369Sopenharmony_ci /// Creates `Gid` from raw `gid_t`. 1343da5c369Sopenharmony_ci pub const fn from_raw(gid: gid_t) -> Self { 1353da5c369Sopenharmony_ci Gid(gid) 1363da5c369Sopenharmony_ci } 1373da5c369Sopenharmony_ci 1383da5c369Sopenharmony_ci /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`. 1393da5c369Sopenharmony_ci #[doc(alias("getgid"))] 1403da5c369Sopenharmony_ci pub fn current() -> Self { 1413da5c369Sopenharmony_ci getgid() 1423da5c369Sopenharmony_ci } 1433da5c369Sopenharmony_ci 1443da5c369Sopenharmony_ci /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`. 1453da5c369Sopenharmony_ci #[doc(alias("getegid"))] 1463da5c369Sopenharmony_ci pub fn effective() -> Self { 1473da5c369Sopenharmony_ci getegid() 1483da5c369Sopenharmony_ci } 1493da5c369Sopenharmony_ci 1503da5c369Sopenharmony_ci /// Get the raw `gid_t` wrapped by `self`. 1513da5c369Sopenharmony_ci pub const fn as_raw(self) -> gid_t { 1523da5c369Sopenharmony_ci self.0 1533da5c369Sopenharmony_ci } 1543da5c369Sopenharmony_ci} 1553da5c369Sopenharmony_ci 1563da5c369Sopenharmony_ciimpl From<Gid> for gid_t { 1573da5c369Sopenharmony_ci fn from(gid: Gid) -> Self { 1583da5c369Sopenharmony_ci gid.0 1593da5c369Sopenharmony_ci } 1603da5c369Sopenharmony_ci} 1613da5c369Sopenharmony_ci 1623da5c369Sopenharmony_ciimpl From<gid_t> for Gid { 1633da5c369Sopenharmony_ci fn from(gid: gid_t) -> Self { 1643da5c369Sopenharmony_ci Gid(gid) 1653da5c369Sopenharmony_ci } 1663da5c369Sopenharmony_ci} 1673da5c369Sopenharmony_ci 1683da5c369Sopenharmony_ciimpl fmt::Display for Gid { 1693da5c369Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1703da5c369Sopenharmony_ci fmt::Display::fmt(&self.0, f) 1713da5c369Sopenharmony_ci } 1723da5c369Sopenharmony_ci} 1733da5c369Sopenharmony_ci} 1743da5c369Sopenharmony_ci 1753da5c369Sopenharmony_cifeature! { 1763da5c369Sopenharmony_ci#![feature = "process"] 1773da5c369Sopenharmony_ci/// Process identifier 1783da5c369Sopenharmony_ci/// 1793da5c369Sopenharmony_ci/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally 1803da5c369Sopenharmony_ci/// passing wrong value. 1813da5c369Sopenharmony_ci#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 1823da5c369Sopenharmony_cipub struct Pid(pid_t); 1833da5c369Sopenharmony_ci 1843da5c369Sopenharmony_ciimpl Pid { 1853da5c369Sopenharmony_ci /// Creates `Pid` from raw `pid_t`. 1863da5c369Sopenharmony_ci pub const fn from_raw(pid: pid_t) -> Self { 1873da5c369Sopenharmony_ci Pid(pid) 1883da5c369Sopenharmony_ci } 1893da5c369Sopenharmony_ci 1903da5c369Sopenharmony_ci /// Returns PID of calling process 1913da5c369Sopenharmony_ci #[doc(alias("getpid"))] 1923da5c369Sopenharmony_ci pub fn this() -> Self { 1933da5c369Sopenharmony_ci getpid() 1943da5c369Sopenharmony_ci } 1953da5c369Sopenharmony_ci 1963da5c369Sopenharmony_ci /// Returns PID of parent of calling process 1973da5c369Sopenharmony_ci #[doc(alias("getppid"))] 1983da5c369Sopenharmony_ci pub fn parent() -> Self { 1993da5c369Sopenharmony_ci getppid() 2003da5c369Sopenharmony_ci } 2013da5c369Sopenharmony_ci 2023da5c369Sopenharmony_ci /// Get the raw `pid_t` wrapped by `self`. 2033da5c369Sopenharmony_ci pub const fn as_raw(self) -> pid_t { 2043da5c369Sopenharmony_ci self.0 2053da5c369Sopenharmony_ci } 2063da5c369Sopenharmony_ci} 2073da5c369Sopenharmony_ci 2083da5c369Sopenharmony_ciimpl From<Pid> for pid_t { 2093da5c369Sopenharmony_ci fn from(pid: Pid) -> Self { 2103da5c369Sopenharmony_ci pid.0 2113da5c369Sopenharmony_ci } 2123da5c369Sopenharmony_ci} 2133da5c369Sopenharmony_ci 2143da5c369Sopenharmony_ciimpl fmt::Display for Pid { 2153da5c369Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2163da5c369Sopenharmony_ci fmt::Display::fmt(&self.0, f) 2173da5c369Sopenharmony_ci } 2183da5c369Sopenharmony_ci} 2193da5c369Sopenharmony_ci 2203da5c369Sopenharmony_ci 2213da5c369Sopenharmony_ci/// Represents the successful result of calling `fork` 2223da5c369Sopenharmony_ci/// 2233da5c369Sopenharmony_ci/// When `fork` is called, the process continues execution in the parent process 2243da5c369Sopenharmony_ci/// and in the new child. This return type can be examined to determine whether 2253da5c369Sopenharmony_ci/// you are now executing in the parent process or in the child. 2263da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)] 2273da5c369Sopenharmony_cipub enum ForkResult { 2283da5c369Sopenharmony_ci Parent { child: Pid }, 2293da5c369Sopenharmony_ci Child, 2303da5c369Sopenharmony_ci} 2313da5c369Sopenharmony_ci 2323da5c369Sopenharmony_ciimpl ForkResult { 2333da5c369Sopenharmony_ci 2343da5c369Sopenharmony_ci /// Return `true` if this is the child process of the `fork()` 2353da5c369Sopenharmony_ci #[inline] 2363da5c369Sopenharmony_ci pub fn is_child(self) -> bool { 2373da5c369Sopenharmony_ci matches!(self, ForkResult::Child) 2383da5c369Sopenharmony_ci } 2393da5c369Sopenharmony_ci 2403da5c369Sopenharmony_ci /// Returns `true` if this is the parent process of the `fork()` 2413da5c369Sopenharmony_ci #[inline] 2423da5c369Sopenharmony_ci pub fn is_parent(self) -> bool { 2433da5c369Sopenharmony_ci !self.is_child() 2443da5c369Sopenharmony_ci } 2453da5c369Sopenharmony_ci} 2463da5c369Sopenharmony_ci 2473da5c369Sopenharmony_ci/// Create a new child process duplicating the parent process ([see 2483da5c369Sopenharmony_ci/// fork(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)). 2493da5c369Sopenharmony_ci/// 2503da5c369Sopenharmony_ci/// After successfully calling the fork system call, a second process will 2513da5c369Sopenharmony_ci/// be created which is identical to the original except for the pid and the 2523da5c369Sopenharmony_ci/// return value of this function. As an example: 2533da5c369Sopenharmony_ci/// 2543da5c369Sopenharmony_ci/// ``` 2553da5c369Sopenharmony_ci/// use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}}; 2563da5c369Sopenharmony_ci/// 2573da5c369Sopenharmony_ci/// match unsafe{fork()} { 2583da5c369Sopenharmony_ci/// Ok(ForkResult::Parent { child, .. }) => { 2593da5c369Sopenharmony_ci/// println!("Continuing execution in parent process, new child has pid: {}", child); 2603da5c369Sopenharmony_ci/// waitpid(child, None).unwrap(); 2613da5c369Sopenharmony_ci/// } 2623da5c369Sopenharmony_ci/// Ok(ForkResult::Child) => { 2633da5c369Sopenharmony_ci/// // Unsafe to use `println!` (or `unwrap`) here. See Safety. 2643da5c369Sopenharmony_ci/// write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok(); 2653da5c369Sopenharmony_ci/// unsafe { libc::_exit(0) }; 2663da5c369Sopenharmony_ci/// } 2673da5c369Sopenharmony_ci/// Err(_) => println!("Fork failed"), 2683da5c369Sopenharmony_ci/// } 2693da5c369Sopenharmony_ci/// ``` 2703da5c369Sopenharmony_ci/// 2713da5c369Sopenharmony_ci/// This will print something like the following (order nondeterministic). The 2723da5c369Sopenharmony_ci/// thing to note is that you end up with two processes continuing execution 2733da5c369Sopenharmony_ci/// immediately after the fork call but with different match arms. 2743da5c369Sopenharmony_ci/// 2753da5c369Sopenharmony_ci/// ```text 2763da5c369Sopenharmony_ci/// Continuing execution in parent process, new child has pid: 1234 2773da5c369Sopenharmony_ci/// I'm a new child process 2783da5c369Sopenharmony_ci/// ``` 2793da5c369Sopenharmony_ci/// 2803da5c369Sopenharmony_ci/// # Safety 2813da5c369Sopenharmony_ci/// 2823da5c369Sopenharmony_ci/// In a multithreaded program, only [async-signal-safe] functions like `pause` 2833da5c369Sopenharmony_ci/// and `_exit` may be called by the child (the parent isn't restricted). Note 2843da5c369Sopenharmony_ci/// that memory allocation may **not** be async-signal-safe and thus must be 2853da5c369Sopenharmony_ci/// prevented. 2863da5c369Sopenharmony_ci/// 2873da5c369Sopenharmony_ci/// Those functions are only a small subset of your operating system's API, so 2883da5c369Sopenharmony_ci/// special care must be taken to only invoke code you can control and audit. 2893da5c369Sopenharmony_ci/// 2903da5c369Sopenharmony_ci/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html 2913da5c369Sopenharmony_ci#[inline] 2923da5c369Sopenharmony_cipub unsafe fn fork() -> Result<ForkResult> { 2933da5c369Sopenharmony_ci use self::ForkResult::*; 2943da5c369Sopenharmony_ci let res = libc::fork(); 2953da5c369Sopenharmony_ci 2963da5c369Sopenharmony_ci Errno::result(res).map(|res| match res { 2973da5c369Sopenharmony_ci 0 => Child, 2983da5c369Sopenharmony_ci res => Parent { child: Pid(res) }, 2993da5c369Sopenharmony_ci }) 3003da5c369Sopenharmony_ci} 3013da5c369Sopenharmony_ci 3023da5c369Sopenharmony_ci/// Get the pid of this process (see 3033da5c369Sopenharmony_ci/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)). 3043da5c369Sopenharmony_ci/// 3053da5c369Sopenharmony_ci/// Since you are running code, there is always a pid to return, so there 3063da5c369Sopenharmony_ci/// is no error case that needs to be handled. 3073da5c369Sopenharmony_ci#[inline] 3083da5c369Sopenharmony_cipub fn getpid() -> Pid { 3093da5c369Sopenharmony_ci Pid(unsafe { libc::getpid() }) 3103da5c369Sopenharmony_ci} 3113da5c369Sopenharmony_ci 3123da5c369Sopenharmony_ci/// Get the pid of this processes' parent (see 3133da5c369Sopenharmony_ci/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)). 3143da5c369Sopenharmony_ci/// 3153da5c369Sopenharmony_ci/// There is always a parent pid to return, so there is no error case that needs 3163da5c369Sopenharmony_ci/// to be handled. 3173da5c369Sopenharmony_ci#[inline] 3183da5c369Sopenharmony_cipub fn getppid() -> Pid { 3193da5c369Sopenharmony_ci Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful." 3203da5c369Sopenharmony_ci} 3213da5c369Sopenharmony_ci 3223da5c369Sopenharmony_ci/// Set a process group ID (see 3233da5c369Sopenharmony_ci/// [setpgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)). 3243da5c369Sopenharmony_ci/// 3253da5c369Sopenharmony_ci/// Set the process group id (PGID) of a particular process. If a pid of zero 3263da5c369Sopenharmony_ci/// is specified, then the pid of the calling process is used. Process groups 3273da5c369Sopenharmony_ci/// may be used to group together a set of processes in order for the OS to 3283da5c369Sopenharmony_ci/// apply some operations across the group. 3293da5c369Sopenharmony_ci/// 3303da5c369Sopenharmony_ci/// `setsid()` may be used to create a new process group. 3313da5c369Sopenharmony_ci#[inline] 3323da5c369Sopenharmony_cipub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> { 3333da5c369Sopenharmony_ci let res = unsafe { libc::setpgid(pid.into(), pgid.into()) }; 3343da5c369Sopenharmony_ci Errno::result(res).map(drop) 3353da5c369Sopenharmony_ci} 3363da5c369Sopenharmony_ci#[inline] 3373da5c369Sopenharmony_cipub fn getpgid(pid: Option<Pid>) -> Result<Pid> { 3383da5c369Sopenharmony_ci let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) }; 3393da5c369Sopenharmony_ci Errno::result(res).map(Pid) 3403da5c369Sopenharmony_ci} 3413da5c369Sopenharmony_ci 3423da5c369Sopenharmony_ci/// Create new session and set process group id (see 3433da5c369Sopenharmony_ci/// [setsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)). 3443da5c369Sopenharmony_ci#[inline] 3453da5c369Sopenharmony_cipub fn setsid() -> Result<Pid> { 3463da5c369Sopenharmony_ci Errno::result(unsafe { libc::setsid() }).map(Pid) 3473da5c369Sopenharmony_ci} 3483da5c369Sopenharmony_ci 3493da5c369Sopenharmony_ci/// Get the process group ID of a session leader 3503da5c369Sopenharmony_ci/// [getsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html). 3513da5c369Sopenharmony_ci/// 3523da5c369Sopenharmony_ci/// Obtain the process group ID of the process that is the session leader of the process specified 3533da5c369Sopenharmony_ci/// by pid. If pid is zero, it specifies the calling process. 3543da5c369Sopenharmony_ci#[inline] 3553da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 3563da5c369Sopenharmony_cipub fn getsid(pid: Option<Pid>) -> Result<Pid> { 3573da5c369Sopenharmony_ci let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) }; 3583da5c369Sopenharmony_ci Errno::result(res).map(Pid) 3593da5c369Sopenharmony_ci} 3603da5c369Sopenharmony_ci} 3613da5c369Sopenharmony_ci 3623da5c369Sopenharmony_cifeature! { 3633da5c369Sopenharmony_ci#![all(feature = "process", feature = "term")] 3643da5c369Sopenharmony_ci/// Get the terminal foreground process group (see 3653da5c369Sopenharmony_ci/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)). 3663da5c369Sopenharmony_ci/// 3673da5c369Sopenharmony_ci/// Get the group process id (GPID) of the foreground process group on the 3683da5c369Sopenharmony_ci/// terminal associated to file descriptor (FD). 3693da5c369Sopenharmony_ci#[inline] 3703da5c369Sopenharmony_cipub fn tcgetpgrp(fd: c_int) -> Result<Pid> { 3713da5c369Sopenharmony_ci let res = unsafe { libc::tcgetpgrp(fd) }; 3723da5c369Sopenharmony_ci Errno::result(res).map(Pid) 3733da5c369Sopenharmony_ci} 3743da5c369Sopenharmony_ci/// Set the terminal foreground process group (see 3753da5c369Sopenharmony_ci/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)). 3763da5c369Sopenharmony_ci/// 3773da5c369Sopenharmony_ci/// Get the group process id (PGID) to the foreground process group on the 3783da5c369Sopenharmony_ci/// terminal associated to file descriptor (FD). 3793da5c369Sopenharmony_ci#[inline] 3803da5c369Sopenharmony_cipub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> { 3813da5c369Sopenharmony_ci let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) }; 3823da5c369Sopenharmony_ci Errno::result(res).map(drop) 3833da5c369Sopenharmony_ci} 3843da5c369Sopenharmony_ci} 3853da5c369Sopenharmony_ci 3863da5c369Sopenharmony_cifeature! { 3873da5c369Sopenharmony_ci#![feature = "process"] 3883da5c369Sopenharmony_ci/// Get the group id of the calling process (see 3893da5c369Sopenharmony_ci///[getpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)). 3903da5c369Sopenharmony_ci/// 3913da5c369Sopenharmony_ci/// Get the process group id (PGID) of the calling process. 3923da5c369Sopenharmony_ci/// According to the man page it is always successful. 3933da5c369Sopenharmony_ci#[inline] 3943da5c369Sopenharmony_cipub fn getpgrp() -> Pid { 3953da5c369Sopenharmony_ci Pid(unsafe { libc::getpgrp() }) 3963da5c369Sopenharmony_ci} 3973da5c369Sopenharmony_ci 3983da5c369Sopenharmony_ci/// Get the caller's thread ID (see 3993da5c369Sopenharmony_ci/// [gettid(2)](https://man7.org/linux/man-pages/man2/gettid.2.html). 4003da5c369Sopenharmony_ci/// 4013da5c369Sopenharmony_ci/// This function is only available on Linux based systems. In a single 4023da5c369Sopenharmony_ci/// threaded process, the main thread will have the same ID as the process. In 4033da5c369Sopenharmony_ci/// a multithreaded process, each thread will have a unique thread id but the 4043da5c369Sopenharmony_ci/// same process ID. 4053da5c369Sopenharmony_ci/// 4063da5c369Sopenharmony_ci/// No error handling is required as a thread id should always exist for any 4073da5c369Sopenharmony_ci/// process, even if threads are not being used. 4083da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))] 4093da5c369Sopenharmony_ci#[inline] 4103da5c369Sopenharmony_cipub fn gettid() -> Pid { 4113da5c369Sopenharmony_ci Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t }) 4123da5c369Sopenharmony_ci} 4133da5c369Sopenharmony_ci} 4143da5c369Sopenharmony_ci 4153da5c369Sopenharmony_cifeature! { 4163da5c369Sopenharmony_ci#![feature = "fs"] 4173da5c369Sopenharmony_ci/// Create a copy of the specified file descriptor (see 4183da5c369Sopenharmony_ci/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)). 4193da5c369Sopenharmony_ci/// 4203da5c369Sopenharmony_ci/// The new file descriptor will have a new index but refer to the same 4213da5c369Sopenharmony_ci/// resource as the old file descriptor and the old and new file descriptors may 4223da5c369Sopenharmony_ci/// be used interchangeably. The new and old file descriptor share the same 4233da5c369Sopenharmony_ci/// underlying resource, offset, and file status flags. The actual index used 4243da5c369Sopenharmony_ci/// for the file descriptor will be the lowest fd index that is available. 4253da5c369Sopenharmony_ci/// 4263da5c369Sopenharmony_ci/// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`). 4273da5c369Sopenharmony_ci#[inline] 4283da5c369Sopenharmony_cipub fn dup(oldfd: RawFd) -> Result<RawFd> { 4293da5c369Sopenharmony_ci let res = unsafe { libc::dup(oldfd) }; 4303da5c369Sopenharmony_ci 4313da5c369Sopenharmony_ci Errno::result(res) 4323da5c369Sopenharmony_ci} 4333da5c369Sopenharmony_ci 4343da5c369Sopenharmony_ci/// Create a copy of the specified file descriptor using the specified fd (see 4353da5c369Sopenharmony_ci/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)). 4363da5c369Sopenharmony_ci/// 4373da5c369Sopenharmony_ci/// This function behaves similar to `dup()` except that it will try to use the 4383da5c369Sopenharmony_ci/// specified fd instead of allocating a new one. See the man pages for more 4393da5c369Sopenharmony_ci/// detail on the exact behavior of this function. 4403da5c369Sopenharmony_ci#[inline] 4413da5c369Sopenharmony_cipub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> { 4423da5c369Sopenharmony_ci let res = unsafe { libc::dup2(oldfd, newfd) }; 4433da5c369Sopenharmony_ci 4443da5c369Sopenharmony_ci Errno::result(res) 4453da5c369Sopenharmony_ci} 4463da5c369Sopenharmony_ci 4473da5c369Sopenharmony_ci/// Create a new copy of the specified file descriptor using the specified fd 4483da5c369Sopenharmony_ci/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)). 4493da5c369Sopenharmony_ci/// 4503da5c369Sopenharmony_ci/// This function behaves similar to `dup2()` but allows for flags to be 4513da5c369Sopenharmony_ci/// specified. 4523da5c369Sopenharmony_cipub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> { 4533da5c369Sopenharmony_ci dup3_polyfill(oldfd, newfd, flags) 4543da5c369Sopenharmony_ci} 4553da5c369Sopenharmony_ci 4563da5c369Sopenharmony_ci#[inline] 4573da5c369Sopenharmony_cifn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> { 4583da5c369Sopenharmony_ci if oldfd == newfd { 4593da5c369Sopenharmony_ci return Err(Errno::EINVAL); 4603da5c369Sopenharmony_ci } 4613da5c369Sopenharmony_ci 4623da5c369Sopenharmony_ci let fd = dup2(oldfd, newfd)?; 4633da5c369Sopenharmony_ci 4643da5c369Sopenharmony_ci if flags.contains(OFlag::O_CLOEXEC) { 4653da5c369Sopenharmony_ci if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) { 4663da5c369Sopenharmony_ci let _ = close(fd); 4673da5c369Sopenharmony_ci return Err(e); 4683da5c369Sopenharmony_ci } 4693da5c369Sopenharmony_ci } 4703da5c369Sopenharmony_ci 4713da5c369Sopenharmony_ci Ok(fd) 4723da5c369Sopenharmony_ci} 4733da5c369Sopenharmony_ci 4743da5c369Sopenharmony_ci/// Change the current working directory of the calling process (see 4753da5c369Sopenharmony_ci/// [chdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)). 4763da5c369Sopenharmony_ci/// 4773da5c369Sopenharmony_ci/// This function may fail in a number of different scenarios. See the man 4783da5c369Sopenharmony_ci/// pages for additional details on possible failure cases. 4793da5c369Sopenharmony_ci#[inline] 4803da5c369Sopenharmony_cipub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> { 4813da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 4823da5c369Sopenharmony_ci unsafe { libc::chdir(cstr.as_ptr()) } 4833da5c369Sopenharmony_ci })?; 4843da5c369Sopenharmony_ci 4853da5c369Sopenharmony_ci Errno::result(res).map(drop) 4863da5c369Sopenharmony_ci} 4873da5c369Sopenharmony_ci 4883da5c369Sopenharmony_ci/// Change the current working directory of the process to the one 4893da5c369Sopenharmony_ci/// given as an open file descriptor (see 4903da5c369Sopenharmony_ci/// [fchdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)). 4913da5c369Sopenharmony_ci/// 4923da5c369Sopenharmony_ci/// This function may fail in a number of different scenarios. See the man 4933da5c369Sopenharmony_ci/// pages for additional details on possible failure cases. 4943da5c369Sopenharmony_ci#[inline] 4953da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))] 4963da5c369Sopenharmony_cipub fn fchdir(dirfd: RawFd) -> Result<()> { 4973da5c369Sopenharmony_ci let res = unsafe { libc::fchdir(dirfd) }; 4983da5c369Sopenharmony_ci 4993da5c369Sopenharmony_ci Errno::result(res).map(drop) 5003da5c369Sopenharmony_ci} 5013da5c369Sopenharmony_ci 5023da5c369Sopenharmony_ci/// Creates new directory `path` with access rights `mode`. (see [mkdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html)) 5033da5c369Sopenharmony_ci/// 5043da5c369Sopenharmony_ci/// # Errors 5053da5c369Sopenharmony_ci/// 5063da5c369Sopenharmony_ci/// There are several situations where mkdir might fail: 5073da5c369Sopenharmony_ci/// 5083da5c369Sopenharmony_ci/// - current user has insufficient rights in the parent directory 5093da5c369Sopenharmony_ci/// - the path already exists 5103da5c369Sopenharmony_ci/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X) 5113da5c369Sopenharmony_ci/// 5123da5c369Sopenharmony_ci/// # Example 5133da5c369Sopenharmony_ci/// 5143da5c369Sopenharmony_ci/// ```rust 5153da5c369Sopenharmony_ci/// use nix::unistd; 5163da5c369Sopenharmony_ci/// use nix::sys::stat; 5173da5c369Sopenharmony_ci/// use tempfile::tempdir; 5183da5c369Sopenharmony_ci/// 5193da5c369Sopenharmony_ci/// let tmp_dir1 = tempdir().unwrap(); 5203da5c369Sopenharmony_ci/// let tmp_dir2 = tmp_dir1.path().join("new_dir"); 5213da5c369Sopenharmony_ci/// 5223da5c369Sopenharmony_ci/// // create new directory and give read, write and execute rights to the owner 5233da5c369Sopenharmony_ci/// match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) { 5243da5c369Sopenharmony_ci/// Ok(_) => println!("created {:?}", tmp_dir2), 5253da5c369Sopenharmony_ci/// Err(err) => println!("Error creating directory: {}", err), 5263da5c369Sopenharmony_ci/// } 5273da5c369Sopenharmony_ci/// ``` 5283da5c369Sopenharmony_ci#[inline] 5293da5c369Sopenharmony_cipub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> { 5303da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 5313da5c369Sopenharmony_ci unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) } 5323da5c369Sopenharmony_ci })?; 5333da5c369Sopenharmony_ci 5343da5c369Sopenharmony_ci Errno::result(res).map(drop) 5353da5c369Sopenharmony_ci} 5363da5c369Sopenharmony_ci 5373da5c369Sopenharmony_ci/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`. 5383da5c369Sopenharmony_ci/// 5393da5c369Sopenharmony_ci/// # Errors 5403da5c369Sopenharmony_ci/// 5413da5c369Sopenharmony_ci/// There are several situations where mkfifo might fail: 5423da5c369Sopenharmony_ci/// 5433da5c369Sopenharmony_ci/// - current user has insufficient rights in the parent directory 5443da5c369Sopenharmony_ci/// - the path already exists 5453da5c369Sopenharmony_ci/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X) 5463da5c369Sopenharmony_ci/// 5473da5c369Sopenharmony_ci/// For a full list consult 5483da5c369Sopenharmony_ci/// [posix specification](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html) 5493da5c369Sopenharmony_ci/// 5503da5c369Sopenharmony_ci/// # Example 5513da5c369Sopenharmony_ci/// 5523da5c369Sopenharmony_ci/// ```rust 5533da5c369Sopenharmony_ci/// use nix::unistd; 5543da5c369Sopenharmony_ci/// use nix::sys::stat; 5553da5c369Sopenharmony_ci/// use tempfile::tempdir; 5563da5c369Sopenharmony_ci/// 5573da5c369Sopenharmony_ci/// let tmp_dir = tempdir().unwrap(); 5583da5c369Sopenharmony_ci/// let fifo_path = tmp_dir.path().join("foo.pipe"); 5593da5c369Sopenharmony_ci/// 5603da5c369Sopenharmony_ci/// // create new fifo and give read, write and execute rights to the owner 5613da5c369Sopenharmony_ci/// match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) { 5623da5c369Sopenharmony_ci/// Ok(_) => println!("created {:?}", fifo_path), 5633da5c369Sopenharmony_ci/// Err(err) => println!("Error creating fifo: {}", err), 5643da5c369Sopenharmony_ci/// } 5653da5c369Sopenharmony_ci/// ``` 5663da5c369Sopenharmony_ci#[inline] 5673da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet 5683da5c369Sopenharmony_cipub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> { 5693da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 5703da5c369Sopenharmony_ci unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) } 5713da5c369Sopenharmony_ci })?; 5723da5c369Sopenharmony_ci 5733da5c369Sopenharmony_ci Errno::result(res).map(drop) 5743da5c369Sopenharmony_ci} 5753da5c369Sopenharmony_ci 5763da5c369Sopenharmony_ci/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`. 5773da5c369Sopenharmony_ci/// 5783da5c369Sopenharmony_ci/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor. 5793da5c369Sopenharmony_ci/// 5803da5c369Sopenharmony_ci/// If `dirfd` is `None`, then `path` is relative to the current working directory. 5813da5c369Sopenharmony_ci/// 5823da5c369Sopenharmony_ci/// # References 5833da5c369Sopenharmony_ci/// 5843da5c369Sopenharmony_ci/// [mkfifoat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html). 5853da5c369Sopenharmony_ci// mkfifoat is not implemented in OSX or android 5863da5c369Sopenharmony_ci#[inline] 5873da5c369Sopenharmony_ci#[cfg(not(any( 5883da5c369Sopenharmony_ci target_os = "macos", target_os = "ios", target_os = "haiku", 5893da5c369Sopenharmony_ci target_os = "android", target_os = "redox")))] 5903da5c369Sopenharmony_cipub fn mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()> { 5913da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| unsafe { 5923da5c369Sopenharmony_ci libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t) 5933da5c369Sopenharmony_ci })?; 5943da5c369Sopenharmony_ci 5953da5c369Sopenharmony_ci Errno::result(res).map(drop) 5963da5c369Sopenharmony_ci} 5973da5c369Sopenharmony_ci 5983da5c369Sopenharmony_ci/// Creates a symbolic link at `path2` which points to `path1`. 5993da5c369Sopenharmony_ci/// 6003da5c369Sopenharmony_ci/// If `dirfd` has a value, then `path2` is relative to directory associated 6013da5c369Sopenharmony_ci/// with the file descriptor. 6023da5c369Sopenharmony_ci/// 6033da5c369Sopenharmony_ci/// If `dirfd` is `None`, then `path2` is relative to the current working 6043da5c369Sopenharmony_ci/// directory. This is identical to `libc::symlink(path1, path2)`. 6053da5c369Sopenharmony_ci/// 6063da5c369Sopenharmony_ci/// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html). 6073da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 6083da5c369Sopenharmony_cipub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>( 6093da5c369Sopenharmony_ci path1: &P1, 6103da5c369Sopenharmony_ci dirfd: Option<RawFd>, 6113da5c369Sopenharmony_ci path2: &P2) -> Result<()> { 6123da5c369Sopenharmony_ci let res = 6133da5c369Sopenharmony_ci path1.with_nix_path(|path1| { 6143da5c369Sopenharmony_ci path2.with_nix_path(|path2| { 6153da5c369Sopenharmony_ci unsafe { 6163da5c369Sopenharmony_ci libc::symlinkat( 6173da5c369Sopenharmony_ci path1.as_ptr(), 6183da5c369Sopenharmony_ci dirfd.unwrap_or(libc::AT_FDCWD), 6193da5c369Sopenharmony_ci path2.as_ptr() 6203da5c369Sopenharmony_ci ) 6213da5c369Sopenharmony_ci } 6223da5c369Sopenharmony_ci }) 6233da5c369Sopenharmony_ci })??; 6243da5c369Sopenharmony_ci Errno::result(res).map(drop) 6253da5c369Sopenharmony_ci} 6263da5c369Sopenharmony_ci} 6273da5c369Sopenharmony_ci 6283da5c369Sopenharmony_ci// Double the buffer capacity up to limit. In case it already has 6293da5c369Sopenharmony_ci// reached the limit, return Errno::ERANGE. 6303da5c369Sopenharmony_ci#[cfg(any(feature = "fs", feature = "user"))] 6313da5c369Sopenharmony_cifn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> { 6323da5c369Sopenharmony_ci use std::cmp::min; 6333da5c369Sopenharmony_ci 6343da5c369Sopenharmony_ci if buf.capacity() >= limit { 6353da5c369Sopenharmony_ci return Err(Errno::ERANGE); 6363da5c369Sopenharmony_ci } 6373da5c369Sopenharmony_ci 6383da5c369Sopenharmony_ci let capacity = min(buf.capacity() * 2, limit); 6393da5c369Sopenharmony_ci buf.reserve(capacity); 6403da5c369Sopenharmony_ci 6413da5c369Sopenharmony_ci Ok(()) 6423da5c369Sopenharmony_ci} 6433da5c369Sopenharmony_ci 6443da5c369Sopenharmony_cifeature! { 6453da5c369Sopenharmony_ci#![feature = "fs"] 6463da5c369Sopenharmony_ci 6473da5c369Sopenharmony_ci/// Returns the current directory as a `PathBuf` 6483da5c369Sopenharmony_ci/// 6493da5c369Sopenharmony_ci/// Err is returned if the current user doesn't have the permission to read or search a component 6503da5c369Sopenharmony_ci/// of the current path. 6513da5c369Sopenharmony_ci/// 6523da5c369Sopenharmony_ci/// # Example 6533da5c369Sopenharmony_ci/// 6543da5c369Sopenharmony_ci/// ```rust 6553da5c369Sopenharmony_ci/// use nix::unistd; 6563da5c369Sopenharmony_ci/// 6573da5c369Sopenharmony_ci/// // assume that we are allowed to get current directory 6583da5c369Sopenharmony_ci/// let dir = unistd::getcwd().unwrap(); 6593da5c369Sopenharmony_ci/// println!("The current directory is {:?}", dir); 6603da5c369Sopenharmony_ci/// ``` 6613da5c369Sopenharmony_ci#[inline] 6623da5c369Sopenharmony_cipub fn getcwd() -> Result<PathBuf> { 6633da5c369Sopenharmony_ci let mut buf = Vec::with_capacity(512); 6643da5c369Sopenharmony_ci loop { 6653da5c369Sopenharmony_ci unsafe { 6663da5c369Sopenharmony_ci let ptr = buf.as_mut_ptr() as *mut c_char; 6673da5c369Sopenharmony_ci 6683da5c369Sopenharmony_ci // The buffer must be large enough to store the absolute pathname plus 6693da5c369Sopenharmony_ci // a terminating null byte, or else null is returned. 6703da5c369Sopenharmony_ci // To safely handle this we start with a reasonable size (512 bytes) 6713da5c369Sopenharmony_ci // and double the buffer size upon every error 6723da5c369Sopenharmony_ci if !libc::getcwd(ptr, buf.capacity()).is_null() { 6733da5c369Sopenharmony_ci let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len(); 6743da5c369Sopenharmony_ci buf.set_len(len); 6753da5c369Sopenharmony_ci buf.shrink_to_fit(); 6763da5c369Sopenharmony_ci return Ok(PathBuf::from(OsString::from_vec(buf))); 6773da5c369Sopenharmony_ci } else { 6783da5c369Sopenharmony_ci let error = Errno::last(); 6793da5c369Sopenharmony_ci // ERANGE means buffer was too small to store directory name 6803da5c369Sopenharmony_ci if error != Errno::ERANGE { 6813da5c369Sopenharmony_ci return Err(error); 6823da5c369Sopenharmony_ci } 6833da5c369Sopenharmony_ci } 6843da5c369Sopenharmony_ci 6853da5c369Sopenharmony_ci // Trigger the internal buffer resizing logic. 6863da5c369Sopenharmony_ci reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?; 6873da5c369Sopenharmony_ci } 6883da5c369Sopenharmony_ci } 6893da5c369Sopenharmony_ci} 6903da5c369Sopenharmony_ci} 6913da5c369Sopenharmony_ci 6923da5c369Sopenharmony_cifeature! { 6933da5c369Sopenharmony_ci#![all(feature = "user", feature = "fs")] 6943da5c369Sopenharmony_ci 6953da5c369Sopenharmony_ci/// Computes the raw UID and GID values to pass to a `*chown` call. 6963da5c369Sopenharmony_ci// The cast is not unnecessary on all platforms. 6973da5c369Sopenharmony_ci#[allow(clippy::unnecessary_cast)] 6983da5c369Sopenharmony_cifn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::gid_t) { 6993da5c369Sopenharmony_ci // According to the POSIX specification, -1 is used to indicate that owner and group 7003da5c369Sopenharmony_ci // are not to be changed. Since uid_t and gid_t are unsigned types, we have to wrap 7013da5c369Sopenharmony_ci // around to get -1. 7023da5c369Sopenharmony_ci let uid = owner.map(Into::into) 7033da5c369Sopenharmony_ci .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1)); 7043da5c369Sopenharmony_ci let gid = group.map(Into::into) 7053da5c369Sopenharmony_ci .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1)); 7063da5c369Sopenharmony_ci (uid, gid) 7073da5c369Sopenharmony_ci} 7083da5c369Sopenharmony_ci 7093da5c369Sopenharmony_ci/// Change the ownership of the file at `path` to be owned by the specified 7103da5c369Sopenharmony_ci/// `owner` (user) and `group` (see 7113da5c369Sopenharmony_ci/// [chown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)). 7123da5c369Sopenharmony_ci/// 7133da5c369Sopenharmony_ci/// The owner/group for the provided path name will not be modified if `None` is 7143da5c369Sopenharmony_ci/// provided for that argument. Ownership change will be attempted for the path 7153da5c369Sopenharmony_ci/// only if `Some` owner/group is provided. 7163da5c369Sopenharmony_ci#[inline] 7173da5c369Sopenharmony_cipub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()> { 7183da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 7193da5c369Sopenharmony_ci let (uid, gid) = chown_raw_ids(owner, group); 7203da5c369Sopenharmony_ci unsafe { libc::chown(cstr.as_ptr(), uid, gid) } 7213da5c369Sopenharmony_ci })?; 7223da5c369Sopenharmony_ci 7233da5c369Sopenharmony_ci Errno::result(res).map(drop) 7243da5c369Sopenharmony_ci} 7253da5c369Sopenharmony_ci 7263da5c369Sopenharmony_ci/// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by 7273da5c369Sopenharmony_ci/// the specified `owner` (user) and `group` (see 7283da5c369Sopenharmony_ci/// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)). 7293da5c369Sopenharmony_ci/// 7303da5c369Sopenharmony_ci/// The owner/group for the provided file will not be modified if `None` is 7313da5c369Sopenharmony_ci/// provided for that argument. Ownership change will be attempted for the path 7323da5c369Sopenharmony_ci/// only if `Some` owner/group is provided. 7333da5c369Sopenharmony_ci#[inline] 7343da5c369Sopenharmony_cipub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> { 7353da5c369Sopenharmony_ci let (uid, gid) = chown_raw_ids(owner, group); 7363da5c369Sopenharmony_ci let res = unsafe { libc::fchown(fd, uid, gid) }; 7373da5c369Sopenharmony_ci Errno::result(res).map(drop) 7383da5c369Sopenharmony_ci} 7393da5c369Sopenharmony_ci 7403da5c369Sopenharmony_ci/// Flags for `fchownat` function. 7413da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)] 7423da5c369Sopenharmony_cipub enum FchownatFlags { 7433da5c369Sopenharmony_ci FollowSymlink, 7443da5c369Sopenharmony_ci NoFollowSymlink, 7453da5c369Sopenharmony_ci} 7463da5c369Sopenharmony_ci 7473da5c369Sopenharmony_ci/// Change the ownership of the file at `path` to be owned by the specified 7483da5c369Sopenharmony_ci/// `owner` (user) and `group`. 7493da5c369Sopenharmony_ci/// 7503da5c369Sopenharmony_ci/// The owner/group for the provided path name will not be modified if `None` is 7513da5c369Sopenharmony_ci/// provided for that argument. Ownership change will be attempted for the path 7523da5c369Sopenharmony_ci/// only if `Some` owner/group is provided. 7533da5c369Sopenharmony_ci/// 7543da5c369Sopenharmony_ci/// The file to be changed is determined relative to the directory associated 7553da5c369Sopenharmony_ci/// with the file descriptor `dirfd` or the current working directory 7563da5c369Sopenharmony_ci/// if `dirfd` is `None`. 7573da5c369Sopenharmony_ci/// 7583da5c369Sopenharmony_ci/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link, 7593da5c369Sopenharmony_ci/// then the mode of the symbolic link is changed. 7603da5c369Sopenharmony_ci/// 7613da5c369Sopenharmony_ci/// `fchownat(None, path, owner, group, FchownatFlags::NoFollowSymlink)` is identical to 7623da5c369Sopenharmony_ci/// a call `libc::lchown(path, owner, group)`. That's why `lchown` is unimplemented in 7633da5c369Sopenharmony_ci/// the `nix` crate. 7643da5c369Sopenharmony_ci/// 7653da5c369Sopenharmony_ci/// # References 7663da5c369Sopenharmony_ci/// 7673da5c369Sopenharmony_ci/// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html). 7683da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 7693da5c369Sopenharmony_cipub fn fchownat<P: ?Sized + NixPath>( 7703da5c369Sopenharmony_ci dirfd: Option<RawFd>, 7713da5c369Sopenharmony_ci path: &P, 7723da5c369Sopenharmony_ci owner: Option<Uid>, 7733da5c369Sopenharmony_ci group: Option<Gid>, 7743da5c369Sopenharmony_ci flag: FchownatFlags, 7753da5c369Sopenharmony_ci) -> Result<()> { 7763da5c369Sopenharmony_ci let atflag = 7773da5c369Sopenharmony_ci match flag { 7783da5c369Sopenharmony_ci FchownatFlags::FollowSymlink => AtFlags::empty(), 7793da5c369Sopenharmony_ci FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW, 7803da5c369Sopenharmony_ci }; 7813da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| unsafe { 7823da5c369Sopenharmony_ci let (uid, gid) = chown_raw_ids(owner, group); 7833da5c369Sopenharmony_ci libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid, 7843da5c369Sopenharmony_ci atflag.bits() as libc::c_int) 7853da5c369Sopenharmony_ci })?; 7863da5c369Sopenharmony_ci 7873da5c369Sopenharmony_ci Errno::result(res).map(drop) 7883da5c369Sopenharmony_ci} 7893da5c369Sopenharmony_ci} 7903da5c369Sopenharmony_ci 7913da5c369Sopenharmony_cifeature! { 7923da5c369Sopenharmony_ci#![feature = "process"] 7933da5c369Sopenharmony_cifn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> { 7943da5c369Sopenharmony_ci use std::iter::once; 7953da5c369Sopenharmony_ci args.iter() 7963da5c369Sopenharmony_ci .map(|s| s.as_ref().as_ptr()) 7973da5c369Sopenharmony_ci .chain(once(ptr::null())) 7983da5c369Sopenharmony_ci .collect() 7993da5c369Sopenharmony_ci} 8003da5c369Sopenharmony_ci 8013da5c369Sopenharmony_ci/// Replace the current process image with a new one (see 8023da5c369Sopenharmony_ci/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). 8033da5c369Sopenharmony_ci/// 8043da5c369Sopenharmony_ci/// See the `::nix::unistd::execve` system call for additional details. `execv` 8053da5c369Sopenharmony_ci/// performs the same action but does not allow for customization of the 8063da5c369Sopenharmony_ci/// environment for the new process. 8073da5c369Sopenharmony_ci#[inline] 8083da5c369Sopenharmony_cipub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> { 8093da5c369Sopenharmony_ci let args_p = to_exec_array(argv); 8103da5c369Sopenharmony_ci 8113da5c369Sopenharmony_ci unsafe { 8123da5c369Sopenharmony_ci libc::execv(path.as_ptr(), args_p.as_ptr()) 8133da5c369Sopenharmony_ci }; 8143da5c369Sopenharmony_ci 8153da5c369Sopenharmony_ci Err(Errno::last()) 8163da5c369Sopenharmony_ci} 8173da5c369Sopenharmony_ci 8183da5c369Sopenharmony_ci 8193da5c369Sopenharmony_ci/// Replace the current process image with a new one (see 8203da5c369Sopenharmony_ci/// [execve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). 8213da5c369Sopenharmony_ci/// 8223da5c369Sopenharmony_ci/// The execve system call allows for another process to be "called" which will 8233da5c369Sopenharmony_ci/// replace the current process image. That is, this process becomes the new 8243da5c369Sopenharmony_ci/// command that is run. On success, this function will not return. Instead, 8253da5c369Sopenharmony_ci/// the new program will run until it exits. 8263da5c369Sopenharmony_ci/// 8273da5c369Sopenharmony_ci/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice 8283da5c369Sopenharmony_ci/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element 8293da5c369Sopenharmony_ci/// in the `args` list is an argument to the new process. Each element in the 8303da5c369Sopenharmony_ci/// `env` list should be a string in the form "key=value". 8313da5c369Sopenharmony_ci#[inline] 8323da5c369Sopenharmony_cipub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> { 8333da5c369Sopenharmony_ci let args_p = to_exec_array(args); 8343da5c369Sopenharmony_ci let env_p = to_exec_array(env); 8353da5c369Sopenharmony_ci 8363da5c369Sopenharmony_ci unsafe { 8373da5c369Sopenharmony_ci libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) 8383da5c369Sopenharmony_ci }; 8393da5c369Sopenharmony_ci 8403da5c369Sopenharmony_ci Err(Errno::last()) 8413da5c369Sopenharmony_ci} 8423da5c369Sopenharmony_ci 8433da5c369Sopenharmony_ci/// Replace the current process image with a new one and replicate shell `PATH` 8443da5c369Sopenharmony_ci/// searching behavior (see 8453da5c369Sopenharmony_ci/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). 8463da5c369Sopenharmony_ci/// 8473da5c369Sopenharmony_ci/// See `::nix::unistd::execve` for additional details. `execvp` behaves the 8483da5c369Sopenharmony_ci/// same as execv except that it will examine the `PATH` environment variables 8493da5c369Sopenharmony_ci/// for file names not specified with a leading slash. For example, `execv` 8503da5c369Sopenharmony_ci/// would not work if "bash" was specified for the path argument, but `execvp` 8513da5c369Sopenharmony_ci/// would assuming that a bash executable was on the system `PATH`. 8523da5c369Sopenharmony_ci#[inline] 8533da5c369Sopenharmony_cipub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> { 8543da5c369Sopenharmony_ci let args_p = to_exec_array(args); 8553da5c369Sopenharmony_ci 8563da5c369Sopenharmony_ci unsafe { 8573da5c369Sopenharmony_ci libc::execvp(filename.as_ptr(), args_p.as_ptr()) 8583da5c369Sopenharmony_ci }; 8593da5c369Sopenharmony_ci 8603da5c369Sopenharmony_ci Err(Errno::last()) 8613da5c369Sopenharmony_ci} 8623da5c369Sopenharmony_ci 8633da5c369Sopenharmony_ci/// Replace the current process image with a new one and replicate shell `PATH` 8643da5c369Sopenharmony_ci/// searching behavior (see 8653da5c369Sopenharmony_ci/// [`execvpe(3)`](https://man7.org/linux/man-pages/man3/exec.3.html)). 8663da5c369Sopenharmony_ci/// 8673da5c369Sopenharmony_ci/// This functions like a combination of `execvp(2)` and `execve(2)` to pass an 8683da5c369Sopenharmony_ci/// environment and have a search path. See these two for additional 8693da5c369Sopenharmony_ci/// information. 8703da5c369Sopenharmony_ci#[cfg(any(target_os = "haiku", 8713da5c369Sopenharmony_ci target_os = "linux", 8723da5c369Sopenharmony_ci target_os = "openbsd"))] 8733da5c369Sopenharmony_cipub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> { 8743da5c369Sopenharmony_ci let args_p = to_exec_array(args); 8753da5c369Sopenharmony_ci let env_p = to_exec_array(env); 8763da5c369Sopenharmony_ci 8773da5c369Sopenharmony_ci unsafe { 8783da5c369Sopenharmony_ci libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) 8793da5c369Sopenharmony_ci }; 8803da5c369Sopenharmony_ci 8813da5c369Sopenharmony_ci Err(Errno::last()) 8823da5c369Sopenharmony_ci} 8833da5c369Sopenharmony_ci 8843da5c369Sopenharmony_ci/// Replace the current process image with a new one (see 8853da5c369Sopenharmony_ci/// [fexecve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)). 8863da5c369Sopenharmony_ci/// 8873da5c369Sopenharmony_ci/// The `fexecve` function allows for another process to be "called" which will 8883da5c369Sopenharmony_ci/// replace the current process image. That is, this process becomes the new 8893da5c369Sopenharmony_ci/// command that is run. On success, this function will not return. Instead, 8903da5c369Sopenharmony_ci/// the new program will run until it exits. 8913da5c369Sopenharmony_ci/// 8923da5c369Sopenharmony_ci/// This function is similar to `execve`, except that the program to be executed 8933da5c369Sopenharmony_ci/// is referenced as a file descriptor instead of a path. 8943da5c369Sopenharmony_ci#[cfg(any(target_os = "android", 8953da5c369Sopenharmony_ci target_os = "linux", 8963da5c369Sopenharmony_ci target_os = "dragonfly", 8973da5c369Sopenharmony_ci target_os = "freebsd"))] 8983da5c369Sopenharmony_ci#[inline] 8993da5c369Sopenharmony_cipub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> { 9003da5c369Sopenharmony_ci let args_p = to_exec_array(args); 9013da5c369Sopenharmony_ci let env_p = to_exec_array(env); 9023da5c369Sopenharmony_ci 9033da5c369Sopenharmony_ci unsafe { 9043da5c369Sopenharmony_ci libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr()) 9053da5c369Sopenharmony_ci }; 9063da5c369Sopenharmony_ci 9073da5c369Sopenharmony_ci Err(Errno::last()) 9083da5c369Sopenharmony_ci} 9093da5c369Sopenharmony_ci 9103da5c369Sopenharmony_ci/// Execute program relative to a directory file descriptor (see 9113da5c369Sopenharmony_ci/// [execveat(2)](https://man7.org/linux/man-pages/man2/execveat.2.html)). 9123da5c369Sopenharmony_ci/// 9133da5c369Sopenharmony_ci/// The `execveat` function allows for another process to be "called" which will 9143da5c369Sopenharmony_ci/// replace the current process image. That is, this process becomes the new 9153da5c369Sopenharmony_ci/// command that is run. On success, this function will not return. Instead, 9163da5c369Sopenharmony_ci/// the new program will run until it exits. 9173da5c369Sopenharmony_ci/// 9183da5c369Sopenharmony_ci/// This function is similar to `execve`, except that the program to be executed 9193da5c369Sopenharmony_ci/// is referenced as a file descriptor to the base directory plus a path. 9203da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))] 9213da5c369Sopenharmony_ci#[inline] 9223da5c369Sopenharmony_cipub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA], 9233da5c369Sopenharmony_ci env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> { 9243da5c369Sopenharmony_ci let args_p = to_exec_array(args); 9253da5c369Sopenharmony_ci let env_p = to_exec_array(env); 9263da5c369Sopenharmony_ci 9273da5c369Sopenharmony_ci unsafe { 9283da5c369Sopenharmony_ci libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(), 9293da5c369Sopenharmony_ci args_p.as_ptr(), env_p.as_ptr(), flags); 9303da5c369Sopenharmony_ci }; 9313da5c369Sopenharmony_ci 9323da5c369Sopenharmony_ci Err(Errno::last()) 9333da5c369Sopenharmony_ci} 9343da5c369Sopenharmony_ci 9353da5c369Sopenharmony_ci/// Daemonize this process by detaching from the controlling terminal (see 9363da5c369Sopenharmony_ci/// [daemon(3)](https://man7.org/linux/man-pages/man3/daemon.3.html)). 9373da5c369Sopenharmony_ci/// 9383da5c369Sopenharmony_ci/// When a process is launched it is typically associated with a parent and it, 9393da5c369Sopenharmony_ci/// in turn, by its controlling terminal/process. In order for a process to run 9403da5c369Sopenharmony_ci/// in the "background" it must daemonize itself by detaching itself. Under 9413da5c369Sopenharmony_ci/// posix, this is done by doing the following: 9423da5c369Sopenharmony_ci/// 9433da5c369Sopenharmony_ci/// 1. Parent process (this one) forks 9443da5c369Sopenharmony_ci/// 2. Parent process exits 9453da5c369Sopenharmony_ci/// 3. Child process continues to run. 9463da5c369Sopenharmony_ci/// 9473da5c369Sopenharmony_ci/// `nochdir`: 9483da5c369Sopenharmony_ci/// 9493da5c369Sopenharmony_ci/// * `nochdir = true`: The current working directory after daemonizing will 9503da5c369Sopenharmony_ci/// be the current working directory. 9513da5c369Sopenharmony_ci/// * `nochdir = false`: The current working directory after daemonizing will 9523da5c369Sopenharmony_ci/// be the root direcory, `/`. 9533da5c369Sopenharmony_ci/// 9543da5c369Sopenharmony_ci/// `noclose`: 9553da5c369Sopenharmony_ci/// 9563da5c369Sopenharmony_ci/// * `noclose = true`: The process' current stdin, stdout, and stderr file 9573da5c369Sopenharmony_ci/// descriptors will remain identical after daemonizing. 9583da5c369Sopenharmony_ci/// * `noclose = false`: The process' stdin, stdout, and stderr will point to 9593da5c369Sopenharmony_ci/// `/dev/null` after daemonizing. 9603da5c369Sopenharmony_ci#[cfg(any(target_os = "android", 9613da5c369Sopenharmony_ci target_os = "dragonfly", 9623da5c369Sopenharmony_ci target_os = "freebsd", 9633da5c369Sopenharmony_ci target_os = "illumos", 9643da5c369Sopenharmony_ci target_os = "linux", 9653da5c369Sopenharmony_ci target_os = "netbsd", 9663da5c369Sopenharmony_ci target_os = "openbsd", 9673da5c369Sopenharmony_ci target_os = "solaris"))] 9683da5c369Sopenharmony_cipub fn daemon(nochdir: bool, noclose: bool) -> Result<()> { 9693da5c369Sopenharmony_ci let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) }; 9703da5c369Sopenharmony_ci Errno::result(res).map(drop) 9713da5c369Sopenharmony_ci} 9723da5c369Sopenharmony_ci} 9733da5c369Sopenharmony_ci 9743da5c369Sopenharmony_cifeature! { 9753da5c369Sopenharmony_ci#![feature = "hostname"] 9763da5c369Sopenharmony_ci 9773da5c369Sopenharmony_ci/// Set the system host name (see 9783da5c369Sopenharmony_ci/// [sethostname(2)](https://man7.org/linux/man-pages/man2/gethostname.2.html)). 9793da5c369Sopenharmony_ci/// 9803da5c369Sopenharmony_ci/// Given a name, attempt to update the system host name to the given string. 9813da5c369Sopenharmony_ci/// On some systems, the host name is limited to as few as 64 bytes. An error 9823da5c369Sopenharmony_ci/// will be returned if the name is not valid or the current process does not 9833da5c369Sopenharmony_ci/// have permissions to update the host name. 9843da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 9853da5c369Sopenharmony_cipub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> { 9863da5c369Sopenharmony_ci // Handle some differences in type of the len arg across platforms. 9873da5c369Sopenharmony_ci cfg_if! { 9883da5c369Sopenharmony_ci if #[cfg(any(target_os = "dragonfly", 9893da5c369Sopenharmony_ci target_os = "freebsd", 9903da5c369Sopenharmony_ci target_os = "illumos", 9913da5c369Sopenharmony_ci target_os = "ios", 9923da5c369Sopenharmony_ci target_os = "macos", 9933da5c369Sopenharmony_ci target_os = "solaris", ))] { 9943da5c369Sopenharmony_ci type sethostname_len_t = c_int; 9953da5c369Sopenharmony_ci } else { 9963da5c369Sopenharmony_ci type sethostname_len_t = size_t; 9973da5c369Sopenharmony_ci } 9983da5c369Sopenharmony_ci } 9993da5c369Sopenharmony_ci let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char; 10003da5c369Sopenharmony_ci let len = name.as_ref().len() as sethostname_len_t; 10013da5c369Sopenharmony_ci 10023da5c369Sopenharmony_ci let res = unsafe { libc::sethostname(ptr, len) }; 10033da5c369Sopenharmony_ci Errno::result(res).map(drop) 10043da5c369Sopenharmony_ci} 10053da5c369Sopenharmony_ci 10063da5c369Sopenharmony_ci/// Get the host name and store it in an internally allocated buffer, returning an 10073da5c369Sopenharmony_ci/// `OsString` on success (see 10083da5c369Sopenharmony_ci/// [gethostname(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)). 10093da5c369Sopenharmony_ci/// 10103da5c369Sopenharmony_ci/// This function call attempts to get the host name for the running system and 10113da5c369Sopenharmony_ci/// store it in an internal buffer, returning it as an `OsString` if successful. 10123da5c369Sopenharmony_ci/// 10133da5c369Sopenharmony_ci/// ```no_run 10143da5c369Sopenharmony_ci/// use nix::unistd; 10153da5c369Sopenharmony_ci/// 10163da5c369Sopenharmony_ci/// let hostname = unistd::gethostname().expect("Failed getting hostname"); 10173da5c369Sopenharmony_ci/// let hostname = hostname.into_string().expect("Hostname wasn't valid UTF-8"); 10183da5c369Sopenharmony_ci/// println!("Hostname: {}", hostname); 10193da5c369Sopenharmony_ci/// ``` 10203da5c369Sopenharmony_cipub fn gethostname() -> Result<OsString> { 10213da5c369Sopenharmony_ci // The capacity is the max length of a hostname plus the NUL terminator. 10223da5c369Sopenharmony_ci let mut buffer: Vec<u8> = Vec::with_capacity(256); 10233da5c369Sopenharmony_ci let ptr = buffer.as_mut_ptr() as *mut c_char; 10243da5c369Sopenharmony_ci let len = buffer.capacity() as size_t; 10253da5c369Sopenharmony_ci 10263da5c369Sopenharmony_ci let res = unsafe { libc::gethostname(ptr, len) }; 10273da5c369Sopenharmony_ci Errno::result(res).map(|_| { 10283da5c369Sopenharmony_ci unsafe { 10293da5c369Sopenharmony_ci buffer.as_mut_ptr().wrapping_add(len - 1).write(0); // ensure always null-terminated 10303da5c369Sopenharmony_ci let len = CStr::from_ptr(buffer.as_ptr() as *const c_char).len(); 10313da5c369Sopenharmony_ci buffer.set_len(len); 10323da5c369Sopenharmony_ci } 10333da5c369Sopenharmony_ci OsString::from_vec(buffer) 10343da5c369Sopenharmony_ci }) 10353da5c369Sopenharmony_ci} 10363da5c369Sopenharmony_ci} 10373da5c369Sopenharmony_ci 10383da5c369Sopenharmony_ci/// Close a raw file descriptor 10393da5c369Sopenharmony_ci/// 10403da5c369Sopenharmony_ci/// Be aware that many Rust types implicitly close-on-drop, including 10413da5c369Sopenharmony_ci/// `std::fs::File`. Explicitly closing them with this method too can result in 10423da5c369Sopenharmony_ci/// a double-close condition, which can cause confusing `EBADF` errors in 10433da5c369Sopenharmony_ci/// seemingly unrelated code. Caveat programmer. See also 10443da5c369Sopenharmony_ci/// [close(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html). 10453da5c369Sopenharmony_ci/// 10463da5c369Sopenharmony_ci/// # Examples 10473da5c369Sopenharmony_ci/// 10483da5c369Sopenharmony_ci/// ```no_run 10493da5c369Sopenharmony_ci/// use std::os::unix::io::AsRawFd; 10503da5c369Sopenharmony_ci/// use nix::unistd::close; 10513da5c369Sopenharmony_ci/// 10523da5c369Sopenharmony_ci/// let f = tempfile::tempfile().unwrap(); 10533da5c369Sopenharmony_ci/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop! 10543da5c369Sopenharmony_ci/// ``` 10553da5c369Sopenharmony_ci/// 10563da5c369Sopenharmony_ci/// ```rust 10573da5c369Sopenharmony_ci/// use std::os::unix::io::IntoRawFd; 10583da5c369Sopenharmony_ci/// use nix::unistd::close; 10593da5c369Sopenharmony_ci/// 10603da5c369Sopenharmony_ci/// let f = tempfile::tempfile().unwrap(); 10613da5c369Sopenharmony_ci/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f 10623da5c369Sopenharmony_ci/// ``` 10633da5c369Sopenharmony_cipub fn close(fd: RawFd) -> Result<()> { 10643da5c369Sopenharmony_ci let res = unsafe { libc::close(fd) }; 10653da5c369Sopenharmony_ci Errno::result(res).map(drop) 10663da5c369Sopenharmony_ci} 10673da5c369Sopenharmony_ci 10683da5c369Sopenharmony_ci/// Read from a raw file descriptor. 10693da5c369Sopenharmony_ci/// 10703da5c369Sopenharmony_ci/// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html) 10713da5c369Sopenharmony_cipub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> { 10723da5c369Sopenharmony_ci let res = unsafe { 10733da5c369Sopenharmony_ci libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) 10743da5c369Sopenharmony_ci }; 10753da5c369Sopenharmony_ci 10763da5c369Sopenharmony_ci Errno::result(res).map(|r| r as usize) 10773da5c369Sopenharmony_ci} 10783da5c369Sopenharmony_ci 10793da5c369Sopenharmony_ci/// Write to a raw file descriptor. 10803da5c369Sopenharmony_ci/// 10813da5c369Sopenharmony_ci/// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) 10823da5c369Sopenharmony_cipub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> { 10833da5c369Sopenharmony_ci let res = unsafe { 10843da5c369Sopenharmony_ci libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) 10853da5c369Sopenharmony_ci }; 10863da5c369Sopenharmony_ci 10873da5c369Sopenharmony_ci Errno::result(res).map(|r| r as usize) 10883da5c369Sopenharmony_ci} 10893da5c369Sopenharmony_ci 10903da5c369Sopenharmony_cifeature! { 10913da5c369Sopenharmony_ci#![feature = "fs"] 10923da5c369Sopenharmony_ci 10933da5c369Sopenharmony_ci/// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to. 10943da5c369Sopenharmony_ci/// 10953da5c369Sopenharmony_ci/// [`lseek`]: ./fn.lseek.html 10963da5c369Sopenharmony_ci/// [`lseek64`]: ./fn.lseek64.html 10973da5c369Sopenharmony_ci#[repr(i32)] 10983da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)] 10993da5c369Sopenharmony_cipub enum Whence { 11003da5c369Sopenharmony_ci /// Specify an offset relative to the start of the file. 11013da5c369Sopenharmony_ci SeekSet = libc::SEEK_SET, 11023da5c369Sopenharmony_ci /// Specify an offset relative to the current file location. 11033da5c369Sopenharmony_ci SeekCur = libc::SEEK_CUR, 11043da5c369Sopenharmony_ci /// Specify an offset relative to the end of the file. 11053da5c369Sopenharmony_ci SeekEnd = libc::SEEK_END, 11063da5c369Sopenharmony_ci /// Specify an offset relative to the next location in the file greater than or 11073da5c369Sopenharmony_ci /// equal to offset that contains some data. If offset points to 11083da5c369Sopenharmony_ci /// some data, then the file offset is set to offset. 11093da5c369Sopenharmony_ci #[cfg(any(target_os = "dragonfly", 11103da5c369Sopenharmony_ci target_os = "freebsd", 11113da5c369Sopenharmony_ci target_os = "illumos", 11123da5c369Sopenharmony_ci target_os = "linux", 11133da5c369Sopenharmony_ci target_os = "solaris"))] 11143da5c369Sopenharmony_ci SeekData = libc::SEEK_DATA, 11153da5c369Sopenharmony_ci /// Specify an offset relative to the next hole in the file greater than 11163da5c369Sopenharmony_ci /// or equal to offset. If offset points into the middle of a hole, then 11173da5c369Sopenharmony_ci /// the file offset should be set to offset. If there is no hole past offset, 11183da5c369Sopenharmony_ci /// then the file offset should be adjusted to the end of the file (i.e., there 11193da5c369Sopenharmony_ci /// is an implicit hole at the end of any file). 11203da5c369Sopenharmony_ci #[cfg(any(target_os = "dragonfly", 11213da5c369Sopenharmony_ci target_os = "freebsd", 11223da5c369Sopenharmony_ci target_os = "illumos", 11233da5c369Sopenharmony_ci target_os = "linux", 11243da5c369Sopenharmony_ci target_os = "solaris"))] 11253da5c369Sopenharmony_ci SeekHole = libc::SEEK_HOLE 11263da5c369Sopenharmony_ci} 11273da5c369Sopenharmony_ci 11283da5c369Sopenharmony_ci/// Move the read/write file offset. 11293da5c369Sopenharmony_ci/// 11303da5c369Sopenharmony_ci/// See also [lseek(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html) 11313da5c369Sopenharmony_cipub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> { 11323da5c369Sopenharmony_ci let res = unsafe { libc::lseek(fd, offset, whence as i32) }; 11333da5c369Sopenharmony_ci 11343da5c369Sopenharmony_ci Errno::result(res).map(|r| r as off_t) 11353da5c369Sopenharmony_ci} 11363da5c369Sopenharmony_ci 11373da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))] 11383da5c369Sopenharmony_cipub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t> { 11393da5c369Sopenharmony_ci let res = unsafe { libc::lseek64(fd, offset, whence as i32) }; 11403da5c369Sopenharmony_ci 11413da5c369Sopenharmony_ci Errno::result(res).map(|r| r as libc::off64_t) 11423da5c369Sopenharmony_ci} 11433da5c369Sopenharmony_ci} 11443da5c369Sopenharmony_ci 11453da5c369Sopenharmony_ci/// Create an interprocess channel. 11463da5c369Sopenharmony_ci/// 11473da5c369Sopenharmony_ci/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html) 11483da5c369Sopenharmony_cipub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> { 11493da5c369Sopenharmony_ci let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); 11503da5c369Sopenharmony_ci 11513da5c369Sopenharmony_ci let res = unsafe { libc::pipe(fds.as_mut_ptr() as *mut c_int) }; 11523da5c369Sopenharmony_ci 11533da5c369Sopenharmony_ci Error::result(res)?; 11543da5c369Sopenharmony_ci 11553da5c369Sopenharmony_ci unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } 11563da5c369Sopenharmony_ci} 11573da5c369Sopenharmony_ci 11583da5c369Sopenharmony_cifeature! { 11593da5c369Sopenharmony_ci#![feature = "fs"] 11603da5c369Sopenharmony_ci/// Like `pipe`, but allows setting certain file descriptor flags. 11613da5c369Sopenharmony_ci/// 11623da5c369Sopenharmony_ci/// The following flags are supported, and will be set atomically as the pipe is 11633da5c369Sopenharmony_ci/// created: 11643da5c369Sopenharmony_ci/// 11653da5c369Sopenharmony_ci/// - `O_CLOEXEC`: Set the close-on-exec flag for the new file descriptors. 11663da5c369Sopenharmony_ci#[cfg_attr(target_os = "linux", doc = "- `O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode.")] 11673da5c369Sopenharmony_ci#[cfg_attr(target_os = "netbsd", doc = "- `O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`.")] 11683da5c369Sopenharmony_ci/// - `O_NONBLOCK`: Set the non-blocking flag for the ends of the pipe. 11693da5c369Sopenharmony_ci/// 11703da5c369Sopenharmony_ci/// See also [pipe(2)](https://man7.org/linux/man-pages/man2/pipe.2.html) 11713da5c369Sopenharmony_ci#[cfg(any(target_os = "android", 11723da5c369Sopenharmony_ci target_os = "dragonfly", 11733da5c369Sopenharmony_ci target_os = "emscripten", 11743da5c369Sopenharmony_ci target_os = "freebsd", 11753da5c369Sopenharmony_ci target_os = "illumos", 11763da5c369Sopenharmony_ci target_os = "linux", 11773da5c369Sopenharmony_ci target_os = "redox", 11783da5c369Sopenharmony_ci target_os = "netbsd", 11793da5c369Sopenharmony_ci target_os = "openbsd", 11803da5c369Sopenharmony_ci target_os = "solaris"))] 11813da5c369Sopenharmony_cipub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { 11823da5c369Sopenharmony_ci let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); 11833da5c369Sopenharmony_ci 11843da5c369Sopenharmony_ci let res = unsafe { 11853da5c369Sopenharmony_ci libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) 11863da5c369Sopenharmony_ci }; 11873da5c369Sopenharmony_ci 11883da5c369Sopenharmony_ci Errno::result(res)?; 11893da5c369Sopenharmony_ci 11903da5c369Sopenharmony_ci unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } 11913da5c369Sopenharmony_ci} 11923da5c369Sopenharmony_ci 11933da5c369Sopenharmony_ci/// Truncate a file to a specified length 11943da5c369Sopenharmony_ci/// 11953da5c369Sopenharmony_ci/// See also 11963da5c369Sopenharmony_ci/// [truncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html) 11973da5c369Sopenharmony_ci#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] 11983da5c369Sopenharmony_cipub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> { 11993da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 12003da5c369Sopenharmony_ci unsafe { 12013da5c369Sopenharmony_ci libc::truncate(cstr.as_ptr(), len) 12023da5c369Sopenharmony_ci } 12033da5c369Sopenharmony_ci })?; 12043da5c369Sopenharmony_ci 12053da5c369Sopenharmony_ci Errno::result(res).map(drop) 12063da5c369Sopenharmony_ci} 12073da5c369Sopenharmony_ci 12083da5c369Sopenharmony_ci/// Truncate a file to a specified length 12093da5c369Sopenharmony_ci/// 12103da5c369Sopenharmony_ci/// See also 12113da5c369Sopenharmony_ci/// [ftruncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html) 12123da5c369Sopenharmony_cipub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> { 12133da5c369Sopenharmony_ci Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop) 12143da5c369Sopenharmony_ci} 12153da5c369Sopenharmony_ci 12163da5c369Sopenharmony_cipub fn isatty(fd: RawFd) -> Result<bool> { 12173da5c369Sopenharmony_ci unsafe { 12183da5c369Sopenharmony_ci // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so 12193da5c369Sopenharmony_ci // we return `Ok(false)` 12203da5c369Sopenharmony_ci if libc::isatty(fd) == 1 { 12213da5c369Sopenharmony_ci Ok(true) 12223da5c369Sopenharmony_ci } else { 12233da5c369Sopenharmony_ci match Errno::last() { 12243da5c369Sopenharmony_ci Errno::ENOTTY => Ok(false), 12253da5c369Sopenharmony_ci err => Err(err), 12263da5c369Sopenharmony_ci } 12273da5c369Sopenharmony_ci } 12283da5c369Sopenharmony_ci } 12293da5c369Sopenharmony_ci} 12303da5c369Sopenharmony_ci 12313da5c369Sopenharmony_ci/// Flags for `linkat` function. 12323da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)] 12333da5c369Sopenharmony_cipub enum LinkatFlags { 12343da5c369Sopenharmony_ci SymlinkFollow, 12353da5c369Sopenharmony_ci NoSymlinkFollow, 12363da5c369Sopenharmony_ci} 12373da5c369Sopenharmony_ci 12383da5c369Sopenharmony_ci/// Link one file to another file 12393da5c369Sopenharmony_ci/// 12403da5c369Sopenharmony_ci/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the 12413da5c369Sopenharmony_ci/// case of a relative `oldpath`, the path is interpreted relative to the directory associated 12423da5c369Sopenharmony_ci/// with file descriptor `olddirfd` instead of the current working directory and similiarly for 12433da5c369Sopenharmony_ci/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and 12443da5c369Sopenharmony_ci/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. 12453da5c369Sopenharmony_ci/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath` 12463da5c369Sopenharmony_ci/// and/or `newpath` is then interpreted relative to the current working directory of the calling 12473da5c369Sopenharmony_ci/// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored. 12483da5c369Sopenharmony_ci/// 12493da5c369Sopenharmony_ci/// # References 12503da5c369Sopenharmony_ci/// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html) 12513da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet 12523da5c369Sopenharmony_cipub fn linkat<P: ?Sized + NixPath>( 12533da5c369Sopenharmony_ci olddirfd: Option<RawFd>, 12543da5c369Sopenharmony_ci oldpath: &P, 12553da5c369Sopenharmony_ci newdirfd: Option<RawFd>, 12563da5c369Sopenharmony_ci newpath: &P, 12573da5c369Sopenharmony_ci flag: LinkatFlags, 12583da5c369Sopenharmony_ci) -> Result<()> { 12593da5c369Sopenharmony_ci 12603da5c369Sopenharmony_ci let atflag = 12613da5c369Sopenharmony_ci match flag { 12623da5c369Sopenharmony_ci LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW, 12633da5c369Sopenharmony_ci LinkatFlags::NoSymlinkFollow => AtFlags::empty(), 12643da5c369Sopenharmony_ci }; 12653da5c369Sopenharmony_ci 12663da5c369Sopenharmony_ci let res = 12673da5c369Sopenharmony_ci oldpath.with_nix_path(|oldcstr| { 12683da5c369Sopenharmony_ci newpath.with_nix_path(|newcstr| { 12693da5c369Sopenharmony_ci unsafe { 12703da5c369Sopenharmony_ci libc::linkat( 12713da5c369Sopenharmony_ci at_rawfd(olddirfd), 12723da5c369Sopenharmony_ci oldcstr.as_ptr(), 12733da5c369Sopenharmony_ci at_rawfd(newdirfd), 12743da5c369Sopenharmony_ci newcstr.as_ptr(), 12753da5c369Sopenharmony_ci atflag.bits() as libc::c_int 12763da5c369Sopenharmony_ci ) 12773da5c369Sopenharmony_ci } 12783da5c369Sopenharmony_ci }) 12793da5c369Sopenharmony_ci })??; 12803da5c369Sopenharmony_ci Errno::result(res).map(drop) 12813da5c369Sopenharmony_ci} 12823da5c369Sopenharmony_ci 12833da5c369Sopenharmony_ci 12843da5c369Sopenharmony_ci/// Remove a directory entry 12853da5c369Sopenharmony_ci/// 12863da5c369Sopenharmony_ci/// See also [unlink(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html) 12873da5c369Sopenharmony_cipub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> { 12883da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 12893da5c369Sopenharmony_ci unsafe { 12903da5c369Sopenharmony_ci libc::unlink(cstr.as_ptr()) 12913da5c369Sopenharmony_ci } 12923da5c369Sopenharmony_ci })?; 12933da5c369Sopenharmony_ci Errno::result(res).map(drop) 12943da5c369Sopenharmony_ci} 12953da5c369Sopenharmony_ci 12963da5c369Sopenharmony_ci/// Flags for `unlinkat` function. 12973da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)] 12983da5c369Sopenharmony_cipub enum UnlinkatFlags { 12993da5c369Sopenharmony_ci RemoveDir, 13003da5c369Sopenharmony_ci NoRemoveDir, 13013da5c369Sopenharmony_ci} 13023da5c369Sopenharmony_ci 13033da5c369Sopenharmony_ci/// Remove a directory entry 13043da5c369Sopenharmony_ci/// 13053da5c369Sopenharmony_ci/// In the case of a relative path, the directory entry to be removed is determined relative to 13063da5c369Sopenharmony_ci/// the directory associated with the file descriptor `dirfd` or the current working directory 13073da5c369Sopenharmony_ci/// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is 13083da5c369Sopenharmony_ci/// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path` 13093da5c369Sopenharmony_ci/// is performed. 13103da5c369Sopenharmony_ci/// 13113da5c369Sopenharmony_ci/// # References 13123da5c369Sopenharmony_ci/// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html) 13133da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 13143da5c369Sopenharmony_cipub fn unlinkat<P: ?Sized + NixPath>( 13153da5c369Sopenharmony_ci dirfd: Option<RawFd>, 13163da5c369Sopenharmony_ci path: &P, 13173da5c369Sopenharmony_ci flag: UnlinkatFlags, 13183da5c369Sopenharmony_ci) -> Result<()> { 13193da5c369Sopenharmony_ci let atflag = 13203da5c369Sopenharmony_ci match flag { 13213da5c369Sopenharmony_ci UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR, 13223da5c369Sopenharmony_ci UnlinkatFlags::NoRemoveDir => AtFlags::empty(), 13233da5c369Sopenharmony_ci }; 13243da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 13253da5c369Sopenharmony_ci unsafe { 13263da5c369Sopenharmony_ci libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int) 13273da5c369Sopenharmony_ci } 13283da5c369Sopenharmony_ci })?; 13293da5c369Sopenharmony_ci Errno::result(res).map(drop) 13303da5c369Sopenharmony_ci} 13313da5c369Sopenharmony_ci 13323da5c369Sopenharmony_ci 13333da5c369Sopenharmony_ci#[inline] 13343da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))] 13353da5c369Sopenharmony_cipub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> { 13363da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 13373da5c369Sopenharmony_ci unsafe { libc::chroot(cstr.as_ptr()) } 13383da5c369Sopenharmony_ci })?; 13393da5c369Sopenharmony_ci 13403da5c369Sopenharmony_ci Errno::result(res).map(drop) 13413da5c369Sopenharmony_ci} 13423da5c369Sopenharmony_ci 13433da5c369Sopenharmony_ci/// Commit filesystem caches to disk 13443da5c369Sopenharmony_ci/// 13453da5c369Sopenharmony_ci/// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html) 13463da5c369Sopenharmony_ci#[cfg(any( 13473da5c369Sopenharmony_ci target_os = "dragonfly", 13483da5c369Sopenharmony_ci target_os = "freebsd", 13493da5c369Sopenharmony_ci target_os = "linux", 13503da5c369Sopenharmony_ci target_os = "netbsd", 13513da5c369Sopenharmony_ci target_os = "openbsd" 13523da5c369Sopenharmony_ci))] 13533da5c369Sopenharmony_cipub fn sync() { 13543da5c369Sopenharmony_ci unsafe { libc::sync() }; 13553da5c369Sopenharmony_ci} 13563da5c369Sopenharmony_ci 13573da5c369Sopenharmony_ci/// Commit filesystem caches containing file referred to by the open file 13583da5c369Sopenharmony_ci/// descriptor `fd` to disk 13593da5c369Sopenharmony_ci/// 13603da5c369Sopenharmony_ci/// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html) 13613da5c369Sopenharmony_ci#[cfg(target_os = "linux")] 13623da5c369Sopenharmony_cipub fn syncfs(fd: RawFd) -> Result<()> { 13633da5c369Sopenharmony_ci let res = unsafe { libc::syncfs(fd) }; 13643da5c369Sopenharmony_ci 13653da5c369Sopenharmony_ci Errno::result(res).map(drop) 13663da5c369Sopenharmony_ci} 13673da5c369Sopenharmony_ci 13683da5c369Sopenharmony_ci/// Synchronize changes to a file 13693da5c369Sopenharmony_ci/// 13703da5c369Sopenharmony_ci/// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html) 13713da5c369Sopenharmony_ci#[inline] 13723da5c369Sopenharmony_cipub fn fsync(fd: RawFd) -> Result<()> { 13733da5c369Sopenharmony_ci let res = unsafe { libc::fsync(fd) }; 13743da5c369Sopenharmony_ci 13753da5c369Sopenharmony_ci Errno::result(res).map(drop) 13763da5c369Sopenharmony_ci} 13773da5c369Sopenharmony_ci 13783da5c369Sopenharmony_ci/// Synchronize the data of a file 13793da5c369Sopenharmony_ci/// 13803da5c369Sopenharmony_ci/// See also 13813da5c369Sopenharmony_ci/// [fdatasync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html) 13823da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", 13833da5c369Sopenharmony_ci target_os = "android", 13843da5c369Sopenharmony_ci target_os = "emscripten", 13853da5c369Sopenharmony_ci target_os = "freebsd", 13863da5c369Sopenharmony_ci target_os = "fuchsia", 13873da5c369Sopenharmony_ci target_os = "netbsd", 13883da5c369Sopenharmony_ci target_os = "openbsd", 13893da5c369Sopenharmony_ci target_os = "illumos", 13903da5c369Sopenharmony_ci target_os = "solaris"))] 13913da5c369Sopenharmony_ci#[inline] 13923da5c369Sopenharmony_cipub fn fdatasync(fd: RawFd) -> Result<()> { 13933da5c369Sopenharmony_ci let res = unsafe { libc::fdatasync(fd) }; 13943da5c369Sopenharmony_ci 13953da5c369Sopenharmony_ci Errno::result(res).map(drop) 13963da5c369Sopenharmony_ci} 13973da5c369Sopenharmony_ci} 13983da5c369Sopenharmony_ci 13993da5c369Sopenharmony_cifeature! { 14003da5c369Sopenharmony_ci#![feature = "user"] 14013da5c369Sopenharmony_ci 14023da5c369Sopenharmony_ci/// Get a real user ID 14033da5c369Sopenharmony_ci/// 14043da5c369Sopenharmony_ci/// See also [getuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html) 14053da5c369Sopenharmony_ci// POSIX requires that getuid is always successful, so no need to check return 14063da5c369Sopenharmony_ci// value or errno. 14073da5c369Sopenharmony_ci#[inline] 14083da5c369Sopenharmony_cipub fn getuid() -> Uid { 14093da5c369Sopenharmony_ci Uid(unsafe { libc::getuid() }) 14103da5c369Sopenharmony_ci} 14113da5c369Sopenharmony_ci 14123da5c369Sopenharmony_ci/// Get the effective user ID 14133da5c369Sopenharmony_ci/// 14143da5c369Sopenharmony_ci/// See also [geteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html) 14153da5c369Sopenharmony_ci// POSIX requires that geteuid is always successful, so no need to check return 14163da5c369Sopenharmony_ci// value or errno. 14173da5c369Sopenharmony_ci#[inline] 14183da5c369Sopenharmony_cipub fn geteuid() -> Uid { 14193da5c369Sopenharmony_ci Uid(unsafe { libc::geteuid() }) 14203da5c369Sopenharmony_ci} 14213da5c369Sopenharmony_ci 14223da5c369Sopenharmony_ci/// Get the real group ID 14233da5c369Sopenharmony_ci/// 14243da5c369Sopenharmony_ci/// See also [getgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html) 14253da5c369Sopenharmony_ci// POSIX requires that getgid is always successful, so no need to check return 14263da5c369Sopenharmony_ci// value or errno. 14273da5c369Sopenharmony_ci#[inline] 14283da5c369Sopenharmony_cipub fn getgid() -> Gid { 14293da5c369Sopenharmony_ci Gid(unsafe { libc::getgid() }) 14303da5c369Sopenharmony_ci} 14313da5c369Sopenharmony_ci 14323da5c369Sopenharmony_ci/// Get the effective group ID 14333da5c369Sopenharmony_ci/// 14343da5c369Sopenharmony_ci/// See also [getegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html) 14353da5c369Sopenharmony_ci// POSIX requires that getegid is always successful, so no need to check return 14363da5c369Sopenharmony_ci// value or errno. 14373da5c369Sopenharmony_ci#[inline] 14383da5c369Sopenharmony_cipub fn getegid() -> Gid { 14393da5c369Sopenharmony_ci Gid(unsafe { libc::getegid() }) 14403da5c369Sopenharmony_ci} 14413da5c369Sopenharmony_ci 14423da5c369Sopenharmony_ci/// Set the effective user ID 14433da5c369Sopenharmony_ci/// 14443da5c369Sopenharmony_ci/// See also [seteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html) 14453da5c369Sopenharmony_ci#[inline] 14463da5c369Sopenharmony_cipub fn seteuid(euid: Uid) -> Result<()> { 14473da5c369Sopenharmony_ci let res = unsafe { libc::seteuid(euid.into()) }; 14483da5c369Sopenharmony_ci 14493da5c369Sopenharmony_ci Errno::result(res).map(drop) 14503da5c369Sopenharmony_ci} 14513da5c369Sopenharmony_ci 14523da5c369Sopenharmony_ci/// Set the effective group ID 14533da5c369Sopenharmony_ci/// 14543da5c369Sopenharmony_ci/// See also [setegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html) 14553da5c369Sopenharmony_ci#[inline] 14563da5c369Sopenharmony_cipub fn setegid(egid: Gid) -> Result<()> { 14573da5c369Sopenharmony_ci let res = unsafe { libc::setegid(egid.into()) }; 14583da5c369Sopenharmony_ci 14593da5c369Sopenharmony_ci Errno::result(res).map(drop) 14603da5c369Sopenharmony_ci} 14613da5c369Sopenharmony_ci 14623da5c369Sopenharmony_ci/// Set the user ID 14633da5c369Sopenharmony_ci/// 14643da5c369Sopenharmony_ci/// See also [setuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html) 14653da5c369Sopenharmony_ci#[inline] 14663da5c369Sopenharmony_cipub fn setuid(uid: Uid) -> Result<()> { 14673da5c369Sopenharmony_ci let res = unsafe { libc::setuid(uid.into()) }; 14683da5c369Sopenharmony_ci 14693da5c369Sopenharmony_ci Errno::result(res).map(drop) 14703da5c369Sopenharmony_ci} 14713da5c369Sopenharmony_ci 14723da5c369Sopenharmony_ci/// Set the group ID 14733da5c369Sopenharmony_ci/// 14743da5c369Sopenharmony_ci/// See also [setgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html) 14753da5c369Sopenharmony_ci#[inline] 14763da5c369Sopenharmony_cipub fn setgid(gid: Gid) -> Result<()> { 14773da5c369Sopenharmony_ci let res = unsafe { libc::setgid(gid.into()) }; 14783da5c369Sopenharmony_ci 14793da5c369Sopenharmony_ci Errno::result(res).map(drop) 14803da5c369Sopenharmony_ci} 14813da5c369Sopenharmony_ci} 14823da5c369Sopenharmony_ci 14833da5c369Sopenharmony_cifeature! { 14843da5c369Sopenharmony_ci#![all(feature = "fs", feature = "user")] 14853da5c369Sopenharmony_ci/// Set the user identity used for filesystem checks per-thread. 14863da5c369Sopenharmony_ci/// On both success and failure, this call returns the previous filesystem user 14873da5c369Sopenharmony_ci/// ID of the caller. 14883da5c369Sopenharmony_ci/// 14893da5c369Sopenharmony_ci/// See also [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html) 14903da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))] 14913da5c369Sopenharmony_cipub fn setfsuid(uid: Uid) -> Uid { 14923da5c369Sopenharmony_ci let prev_fsuid = unsafe { libc::setfsuid(uid.into()) }; 14933da5c369Sopenharmony_ci Uid::from_raw(prev_fsuid as uid_t) 14943da5c369Sopenharmony_ci} 14953da5c369Sopenharmony_ci 14963da5c369Sopenharmony_ci/// Set the group identity used for filesystem checks per-thread. 14973da5c369Sopenharmony_ci/// On both success and failure, this call returns the previous filesystem group 14983da5c369Sopenharmony_ci/// ID of the caller. 14993da5c369Sopenharmony_ci/// 15003da5c369Sopenharmony_ci/// See also [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html) 15013da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))] 15023da5c369Sopenharmony_cipub fn setfsgid(gid: Gid) -> Gid { 15033da5c369Sopenharmony_ci let prev_fsgid = unsafe { libc::setfsgid(gid.into()) }; 15043da5c369Sopenharmony_ci Gid::from_raw(prev_fsgid as gid_t) 15053da5c369Sopenharmony_ci} 15063da5c369Sopenharmony_ci} 15073da5c369Sopenharmony_ci 15083da5c369Sopenharmony_cifeature! { 15093da5c369Sopenharmony_ci#![feature = "user"] 15103da5c369Sopenharmony_ci 15113da5c369Sopenharmony_ci/// Get the list of supplementary group IDs of the calling process. 15123da5c369Sopenharmony_ci/// 15133da5c369Sopenharmony_ci/// [Further reading](https://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html) 15143da5c369Sopenharmony_ci/// 15153da5c369Sopenharmony_ci/// **Note:** This function is not available for Apple platforms. On those 15163da5c369Sopenharmony_ci/// platforms, checking group membership should be achieved via communication 15173da5c369Sopenharmony_ci/// with the `opendirectoryd` service. 15183da5c369Sopenharmony_ci#[cfg(not(any(target_os = "ios", target_os = "macos")))] 15193da5c369Sopenharmony_cipub fn getgroups() -> Result<Vec<Gid>> { 15203da5c369Sopenharmony_ci // First get the maximum number of groups. The value returned 15213da5c369Sopenharmony_ci // shall always be greater than or equal to one and less than or 15223da5c369Sopenharmony_ci // equal to the value of {NGROUPS_MAX} + 1. 15233da5c369Sopenharmony_ci let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) { 15243da5c369Sopenharmony_ci Ok(Some(n)) => (n + 1) as usize, 15253da5c369Sopenharmony_ci Ok(None) | Err(_) => <usize>::max_value(), 15263da5c369Sopenharmony_ci }; 15273da5c369Sopenharmony_ci 15283da5c369Sopenharmony_ci // Next, get the number of groups so we can size our Vec 15293da5c369Sopenharmony_ci let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) }; 15303da5c369Sopenharmony_ci 15313da5c369Sopenharmony_ci // If there are no supplementary groups, return early. 15323da5c369Sopenharmony_ci // This prevents a potential buffer over-read if the number of groups 15333da5c369Sopenharmony_ci // increases from zero before the next call. It would return the total 15343da5c369Sopenharmony_ci // number of groups beyond the capacity of the buffer. 15353da5c369Sopenharmony_ci if ngroups == 0 { 15363da5c369Sopenharmony_ci return Ok(Vec::new()); 15373da5c369Sopenharmony_ci } 15383da5c369Sopenharmony_ci 15393da5c369Sopenharmony_ci // Now actually get the groups. We try multiple times in case the number of 15403da5c369Sopenharmony_ci // groups has changed since the first call to getgroups() and the buffer is 15413da5c369Sopenharmony_ci // now too small. 15423da5c369Sopenharmony_ci let mut groups = Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize); 15433da5c369Sopenharmony_ci loop { 15443da5c369Sopenharmony_ci // FIXME: On the platforms we currently support, the `Gid` struct has 15453da5c369Sopenharmony_ci // the same representation in memory as a bare `gid_t`. This is not 15463da5c369Sopenharmony_ci // necessarily the case on all Rust platforms, though. See RFC 1785. 15473da5c369Sopenharmony_ci let ngroups = unsafe { 15483da5c369Sopenharmony_ci libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t) 15493da5c369Sopenharmony_ci }; 15503da5c369Sopenharmony_ci 15513da5c369Sopenharmony_ci match Errno::result(ngroups) { 15523da5c369Sopenharmony_ci Ok(s) => { 15533da5c369Sopenharmony_ci unsafe { groups.set_len(s as usize) }; 15543da5c369Sopenharmony_ci return Ok(groups); 15553da5c369Sopenharmony_ci }, 15563da5c369Sopenharmony_ci Err(Errno::EINVAL) => { 15573da5c369Sopenharmony_ci // EINVAL indicates that the buffer size was too 15583da5c369Sopenharmony_ci // small, resize it up to ngroups_max as limit. 15593da5c369Sopenharmony_ci reserve_double_buffer_size(&mut groups, ngroups_max) 15603da5c369Sopenharmony_ci .or(Err(Errno::EINVAL))?; 15613da5c369Sopenharmony_ci }, 15623da5c369Sopenharmony_ci Err(e) => return Err(e) 15633da5c369Sopenharmony_ci } 15643da5c369Sopenharmony_ci } 15653da5c369Sopenharmony_ci} 15663da5c369Sopenharmony_ci 15673da5c369Sopenharmony_ci/// Set the list of supplementary group IDs for the calling process. 15683da5c369Sopenharmony_ci/// 15693da5c369Sopenharmony_ci/// [Further reading](https://man7.org/linux/man-pages/man2/getgroups.2.html) 15703da5c369Sopenharmony_ci/// 15713da5c369Sopenharmony_ci/// **Note:** This function is not available for Apple platforms. On those 15723da5c369Sopenharmony_ci/// platforms, group membership management should be achieved via communication 15733da5c369Sopenharmony_ci/// with the `opendirectoryd` service. 15743da5c369Sopenharmony_ci/// 15753da5c369Sopenharmony_ci/// # Examples 15763da5c369Sopenharmony_ci/// 15773da5c369Sopenharmony_ci/// `setgroups` can be used when dropping privileges from the root user to a 15783da5c369Sopenharmony_ci/// specific user and group. For example, given the user `www-data` with UID 15793da5c369Sopenharmony_ci/// `33` and the group `backup` with the GID `34`, one could switch the user as 15803da5c369Sopenharmony_ci/// follows: 15813da5c369Sopenharmony_ci/// 15823da5c369Sopenharmony_ci/// ```rust,no_run 15833da5c369Sopenharmony_ci/// # use std::error::Error; 15843da5c369Sopenharmony_ci/// # use nix::unistd::*; 15853da5c369Sopenharmony_ci/// # 15863da5c369Sopenharmony_ci/// # fn try_main() -> Result<(), Box<dyn Error>> { 15873da5c369Sopenharmony_ci/// let uid = Uid::from_raw(33); 15883da5c369Sopenharmony_ci/// let gid = Gid::from_raw(34); 15893da5c369Sopenharmony_ci/// setgroups(&[gid])?; 15903da5c369Sopenharmony_ci/// setgid(gid)?; 15913da5c369Sopenharmony_ci/// setuid(uid)?; 15923da5c369Sopenharmony_ci/// # 15933da5c369Sopenharmony_ci/// # Ok(()) 15943da5c369Sopenharmony_ci/// # } 15953da5c369Sopenharmony_ci/// # 15963da5c369Sopenharmony_ci/// # try_main().unwrap(); 15973da5c369Sopenharmony_ci/// ``` 15983da5c369Sopenharmony_ci#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "haiku")))] 15993da5c369Sopenharmony_cipub fn setgroups(groups: &[Gid]) -> Result<()> { 16003da5c369Sopenharmony_ci cfg_if! { 16013da5c369Sopenharmony_ci if #[cfg(any(target_os = "dragonfly", 16023da5c369Sopenharmony_ci target_os = "freebsd", 16033da5c369Sopenharmony_ci target_os = "illumos", 16043da5c369Sopenharmony_ci target_os = "ios", 16053da5c369Sopenharmony_ci target_os = "macos", 16063da5c369Sopenharmony_ci target_os = "netbsd", 16073da5c369Sopenharmony_ci target_os = "illumos", 16083da5c369Sopenharmony_ci target_os = "openbsd"))] { 16093da5c369Sopenharmony_ci type setgroups_ngroups_t = c_int; 16103da5c369Sopenharmony_ci } else { 16113da5c369Sopenharmony_ci type setgroups_ngroups_t = size_t; 16123da5c369Sopenharmony_ci } 16133da5c369Sopenharmony_ci } 16143da5c369Sopenharmony_ci // FIXME: On the platforms we currently support, the `Gid` struct has the 16153da5c369Sopenharmony_ci // same representation in memory as a bare `gid_t`. This is not necessarily 16163da5c369Sopenharmony_ci // the case on all Rust platforms, though. See RFC 1785. 16173da5c369Sopenharmony_ci let res = unsafe { 16183da5c369Sopenharmony_ci libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t) 16193da5c369Sopenharmony_ci }; 16203da5c369Sopenharmony_ci 16213da5c369Sopenharmony_ci Errno::result(res).map(drop) 16223da5c369Sopenharmony_ci} 16233da5c369Sopenharmony_ci 16243da5c369Sopenharmony_ci/// Calculate the supplementary group access list. 16253da5c369Sopenharmony_ci/// 16263da5c369Sopenharmony_ci/// Gets the group IDs of all groups that `user` is a member of. The additional 16273da5c369Sopenharmony_ci/// group `group` is also added to the list. 16283da5c369Sopenharmony_ci/// 16293da5c369Sopenharmony_ci/// [Further reading](https://man7.org/linux/man-pages/man3/getgrouplist.3.html) 16303da5c369Sopenharmony_ci/// 16313da5c369Sopenharmony_ci/// **Note:** This function is not available for Apple platforms. On those 16323da5c369Sopenharmony_ci/// platforms, checking group membership should be achieved via communication 16333da5c369Sopenharmony_ci/// with the `opendirectoryd` service. 16343da5c369Sopenharmony_ci/// 16353da5c369Sopenharmony_ci/// # Errors 16363da5c369Sopenharmony_ci/// 16373da5c369Sopenharmony_ci/// Although the `getgrouplist()` call does not return any specific 16383da5c369Sopenharmony_ci/// errors on any known platforms, this implementation will return a system 16393da5c369Sopenharmony_ci/// error of `EINVAL` if the number of groups to be fetched exceeds the 16403da5c369Sopenharmony_ci/// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()` 16413da5c369Sopenharmony_ci/// and `setgroups()`. Additionally, while some implementations will return a 16423da5c369Sopenharmony_ci/// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation 16433da5c369Sopenharmony_ci/// will only ever return the complete list or else an error. 16443da5c369Sopenharmony_ci#[cfg(not(any(target_os = "illumos", 16453da5c369Sopenharmony_ci target_os = "ios", 16463da5c369Sopenharmony_ci target_os = "macos", 16473da5c369Sopenharmony_ci target_os = "redox")))] 16483da5c369Sopenharmony_cipub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> { 16493da5c369Sopenharmony_ci let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) { 16503da5c369Sopenharmony_ci Ok(Some(n)) => n as c_int, 16513da5c369Sopenharmony_ci Ok(None) | Err(_) => <c_int>::max_value(), 16523da5c369Sopenharmony_ci }; 16533da5c369Sopenharmony_ci use std::cmp::min; 16543da5c369Sopenharmony_ci let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize); 16553da5c369Sopenharmony_ci cfg_if! { 16563da5c369Sopenharmony_ci if #[cfg(any(target_os = "ios", target_os = "macos"))] { 16573da5c369Sopenharmony_ci type getgrouplist_group_t = c_int; 16583da5c369Sopenharmony_ci } else { 16593da5c369Sopenharmony_ci type getgrouplist_group_t = gid_t; 16603da5c369Sopenharmony_ci } 16613da5c369Sopenharmony_ci } 16623da5c369Sopenharmony_ci let gid: gid_t = group.into(); 16633da5c369Sopenharmony_ci loop { 16643da5c369Sopenharmony_ci let mut ngroups = groups.capacity() as i32; 16653da5c369Sopenharmony_ci let ret = unsafe { 16663da5c369Sopenharmony_ci libc::getgrouplist(user.as_ptr(), 16673da5c369Sopenharmony_ci gid as getgrouplist_group_t, 16683da5c369Sopenharmony_ci groups.as_mut_ptr() as *mut getgrouplist_group_t, 16693da5c369Sopenharmony_ci &mut ngroups) 16703da5c369Sopenharmony_ci }; 16713da5c369Sopenharmony_ci 16723da5c369Sopenharmony_ci // BSD systems only return 0 or -1, Linux returns ngroups on success. 16733da5c369Sopenharmony_ci if ret >= 0 { 16743da5c369Sopenharmony_ci unsafe { groups.set_len(ngroups as usize) }; 16753da5c369Sopenharmony_ci return Ok(groups); 16763da5c369Sopenharmony_ci } else if ret == -1 { 16773da5c369Sopenharmony_ci // Returns -1 if ngroups is too small, but does not set errno. 16783da5c369Sopenharmony_ci // BSD systems will still fill the groups buffer with as many 16793da5c369Sopenharmony_ci // groups as possible, but Linux manpages do not mention this 16803da5c369Sopenharmony_ci // behavior. 16813da5c369Sopenharmony_ci reserve_double_buffer_size(&mut groups, ngroups_max as usize) 16823da5c369Sopenharmony_ci .map_err(|_| Errno::EINVAL)?; 16833da5c369Sopenharmony_ci } 16843da5c369Sopenharmony_ci } 16853da5c369Sopenharmony_ci} 16863da5c369Sopenharmony_ci 16873da5c369Sopenharmony_ci/// Initialize the supplementary group access list. 16883da5c369Sopenharmony_ci/// 16893da5c369Sopenharmony_ci/// Sets the supplementary group IDs for the calling process using all groups 16903da5c369Sopenharmony_ci/// that `user` is a member of. The additional group `group` is also added to 16913da5c369Sopenharmony_ci/// the list. 16923da5c369Sopenharmony_ci/// 16933da5c369Sopenharmony_ci/// [Further reading](https://man7.org/linux/man-pages/man3/initgroups.3.html) 16943da5c369Sopenharmony_ci/// 16953da5c369Sopenharmony_ci/// **Note:** This function is not available for Apple platforms. On those 16963da5c369Sopenharmony_ci/// platforms, group membership management should be achieved via communication 16973da5c369Sopenharmony_ci/// with the `opendirectoryd` service. 16983da5c369Sopenharmony_ci/// 16993da5c369Sopenharmony_ci/// # Examples 17003da5c369Sopenharmony_ci/// 17013da5c369Sopenharmony_ci/// `initgroups` can be used when dropping privileges from the root user to 17023da5c369Sopenharmony_ci/// another user. For example, given the user `www-data`, we could look up the 17033da5c369Sopenharmony_ci/// UID and GID for the user in the system's password database (usually found 17043da5c369Sopenharmony_ci/// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`, 17053da5c369Sopenharmony_ci/// respectively, one could switch the user as follows: 17063da5c369Sopenharmony_ci/// 17073da5c369Sopenharmony_ci/// ```rust,no_run 17083da5c369Sopenharmony_ci/// # use std::error::Error; 17093da5c369Sopenharmony_ci/// # use std::ffi::CString; 17103da5c369Sopenharmony_ci/// # use nix::unistd::*; 17113da5c369Sopenharmony_ci/// # 17123da5c369Sopenharmony_ci/// # fn try_main() -> Result<(), Box<dyn Error>> { 17133da5c369Sopenharmony_ci/// let user = CString::new("www-data").unwrap(); 17143da5c369Sopenharmony_ci/// let uid = Uid::from_raw(33); 17153da5c369Sopenharmony_ci/// let gid = Gid::from_raw(33); 17163da5c369Sopenharmony_ci/// initgroups(&user, gid)?; 17173da5c369Sopenharmony_ci/// setgid(gid)?; 17183da5c369Sopenharmony_ci/// setuid(uid)?; 17193da5c369Sopenharmony_ci/// # 17203da5c369Sopenharmony_ci/// # Ok(()) 17213da5c369Sopenharmony_ci/// # } 17223da5c369Sopenharmony_ci/// # 17233da5c369Sopenharmony_ci/// # try_main().unwrap(); 17243da5c369Sopenharmony_ci/// ``` 17253da5c369Sopenharmony_ci#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "haiku")))] 17263da5c369Sopenharmony_cipub fn initgroups(user: &CStr, group: Gid) -> Result<()> { 17273da5c369Sopenharmony_ci cfg_if! { 17283da5c369Sopenharmony_ci if #[cfg(any(target_os = "ios", target_os = "macos"))] { 17293da5c369Sopenharmony_ci type initgroups_group_t = c_int; 17303da5c369Sopenharmony_ci } else { 17313da5c369Sopenharmony_ci type initgroups_group_t = gid_t; 17323da5c369Sopenharmony_ci } 17333da5c369Sopenharmony_ci } 17343da5c369Sopenharmony_ci let gid: gid_t = group.into(); 17353da5c369Sopenharmony_ci let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) }; 17363da5c369Sopenharmony_ci 17373da5c369Sopenharmony_ci Errno::result(res).map(drop) 17383da5c369Sopenharmony_ci} 17393da5c369Sopenharmony_ci} 17403da5c369Sopenharmony_ci 17413da5c369Sopenharmony_cifeature! { 17423da5c369Sopenharmony_ci#![feature = "signal"] 17433da5c369Sopenharmony_ci 17443da5c369Sopenharmony_ci/// Suspend the thread until a signal is received. 17453da5c369Sopenharmony_ci/// 17463da5c369Sopenharmony_ci/// See also [pause(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html). 17473da5c369Sopenharmony_ci#[inline] 17483da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 17493da5c369Sopenharmony_cipub fn pause() { 17503da5c369Sopenharmony_ci unsafe { libc::pause() }; 17513da5c369Sopenharmony_ci} 17523da5c369Sopenharmony_ci 17533da5c369Sopenharmony_cipub mod alarm { 17543da5c369Sopenharmony_ci //! Alarm signal scheduling. 17553da5c369Sopenharmony_ci //! 17563da5c369Sopenharmony_ci //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has 17573da5c369Sopenharmony_ci //! elapsed, which has to be caught, because the default action for the 17583da5c369Sopenharmony_ci //! signal is to terminate the program. This signal also can't be ignored 17593da5c369Sopenharmony_ci //! because the system calls like `pause` will not be interrupted, see the 17603da5c369Sopenharmony_ci //! second example below. 17613da5c369Sopenharmony_ci //! 17623da5c369Sopenharmony_ci //! # Examples 17633da5c369Sopenharmony_ci //! 17643da5c369Sopenharmony_ci //! Canceling an alarm: 17653da5c369Sopenharmony_ci //! 17663da5c369Sopenharmony_ci //! ``` 17673da5c369Sopenharmony_ci //! use nix::unistd::alarm; 17683da5c369Sopenharmony_ci //! 17693da5c369Sopenharmony_ci //! // Set an alarm for 60 seconds from now. 17703da5c369Sopenharmony_ci //! alarm::set(60); 17713da5c369Sopenharmony_ci //! 17723da5c369Sopenharmony_ci //! // Cancel the above set alarm, which returns the number of seconds left 17733da5c369Sopenharmony_ci //! // of the previously set alarm. 17743da5c369Sopenharmony_ci //! assert_eq!(alarm::cancel(), Some(60)); 17753da5c369Sopenharmony_ci //! ``` 17763da5c369Sopenharmony_ci //! 17773da5c369Sopenharmony_ci //! Scheduling an alarm and waiting for the signal: 17783da5c369Sopenharmony_ci //! 17793da5c369Sopenharmony_ci#![cfg_attr(target_os = "redox", doc = " ```rust,ignore")] 17803da5c369Sopenharmony_ci#![cfg_attr(not(target_os = "redox"), doc = " ```rust")] 17813da5c369Sopenharmony_ci //! use std::time::{Duration, Instant}; 17823da5c369Sopenharmony_ci //! 17833da5c369Sopenharmony_ci //! use nix::unistd::{alarm, pause}; 17843da5c369Sopenharmony_ci //! use nix::sys::signal::*; 17853da5c369Sopenharmony_ci //! 17863da5c369Sopenharmony_ci //! // We need to setup an empty signal handler to catch the alarm signal, 17873da5c369Sopenharmony_ci //! // otherwise the program will be terminated once the signal is delivered. 17883da5c369Sopenharmony_ci //! extern fn signal_handler(_: nix::libc::c_int) { } 17893da5c369Sopenharmony_ci //! let sa = SigAction::new( 17903da5c369Sopenharmony_ci //! SigHandler::Handler(signal_handler), 17913da5c369Sopenharmony_ci //! SaFlags::SA_RESTART, 17923da5c369Sopenharmony_ci //! SigSet::empty() 17933da5c369Sopenharmony_ci //! ); 17943da5c369Sopenharmony_ci //! unsafe { 17953da5c369Sopenharmony_ci //! sigaction(Signal::SIGALRM, &sa); 17963da5c369Sopenharmony_ci //! } 17973da5c369Sopenharmony_ci //! 17983da5c369Sopenharmony_ci //! let start = Instant::now(); 17993da5c369Sopenharmony_ci //! 18003da5c369Sopenharmony_ci //! // Set an alarm for 1 second from now. 18013da5c369Sopenharmony_ci //! alarm::set(1); 18023da5c369Sopenharmony_ci //! 18033da5c369Sopenharmony_ci //! // Pause the process until the alarm signal is received. 18043da5c369Sopenharmony_ci //! let mut sigset = SigSet::empty(); 18053da5c369Sopenharmony_ci //! sigset.add(Signal::SIGALRM); 18063da5c369Sopenharmony_ci //! sigset.wait(); 18073da5c369Sopenharmony_ci //! 18083da5c369Sopenharmony_ci //! assert!(start.elapsed() >= Duration::from_secs(1)); 18093da5c369Sopenharmony_ci //! ``` 18103da5c369Sopenharmony_ci //! 18113da5c369Sopenharmony_ci //! # References 18123da5c369Sopenharmony_ci //! 18133da5c369Sopenharmony_ci //! See also [alarm(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html). 18143da5c369Sopenharmony_ci 18153da5c369Sopenharmony_ci /// Schedule an alarm signal. 18163da5c369Sopenharmony_ci /// 18173da5c369Sopenharmony_ci /// This will cause the system to generate a `SIGALRM` signal for the 18183da5c369Sopenharmony_ci /// process after the specified number of seconds have elapsed. 18193da5c369Sopenharmony_ci /// 18203da5c369Sopenharmony_ci /// Returns the leftover time of a previously set alarm if there was one. 18213da5c369Sopenharmony_ci pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> { 18223da5c369Sopenharmony_ci assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`"); 18233da5c369Sopenharmony_ci alarm(secs) 18243da5c369Sopenharmony_ci } 18253da5c369Sopenharmony_ci 18263da5c369Sopenharmony_ci /// Cancel an previously set alarm signal. 18273da5c369Sopenharmony_ci /// 18283da5c369Sopenharmony_ci /// Returns the leftover time of a previously set alarm if there was one. 18293da5c369Sopenharmony_ci pub fn cancel() -> Option<libc::c_uint> { 18303da5c369Sopenharmony_ci alarm(0) 18313da5c369Sopenharmony_ci } 18323da5c369Sopenharmony_ci 18333da5c369Sopenharmony_ci fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> { 18343da5c369Sopenharmony_ci match unsafe { libc::alarm(secs) } { 18353da5c369Sopenharmony_ci 0 => None, 18363da5c369Sopenharmony_ci secs => Some(secs), 18373da5c369Sopenharmony_ci } 18383da5c369Sopenharmony_ci } 18393da5c369Sopenharmony_ci} 18403da5c369Sopenharmony_ci} 18413da5c369Sopenharmony_ci 18423da5c369Sopenharmony_ci/// Suspend execution for an interval of time 18433da5c369Sopenharmony_ci/// 18443da5c369Sopenharmony_ci/// See also [sleep(2)](https://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05) 18453da5c369Sopenharmony_ci// Per POSIX, does not fail 18463da5c369Sopenharmony_ci#[inline] 18473da5c369Sopenharmony_cipub fn sleep(seconds: c_uint) -> c_uint { 18483da5c369Sopenharmony_ci unsafe { libc::sleep(seconds) } 18493da5c369Sopenharmony_ci} 18503da5c369Sopenharmony_ci 18513da5c369Sopenharmony_cifeature! { 18523da5c369Sopenharmony_ci#![feature = "acct"] 18533da5c369Sopenharmony_ci 18543da5c369Sopenharmony_ci#[cfg(not(any(target_os = "redox", target_os = "haiku")))] 18553da5c369Sopenharmony_cipub mod acct { 18563da5c369Sopenharmony_ci use crate::{Result, NixPath}; 18573da5c369Sopenharmony_ci use crate::errno::Errno; 18583da5c369Sopenharmony_ci use std::ptr; 18593da5c369Sopenharmony_ci 18603da5c369Sopenharmony_ci /// Enable process accounting 18613da5c369Sopenharmony_ci /// 18623da5c369Sopenharmony_ci /// See also [acct(2)](https://linux.die.net/man/2/acct) 18633da5c369Sopenharmony_ci pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> { 18643da5c369Sopenharmony_ci let res = filename.with_nix_path(|cstr| { 18653da5c369Sopenharmony_ci unsafe { libc::acct(cstr.as_ptr()) } 18663da5c369Sopenharmony_ci })?; 18673da5c369Sopenharmony_ci 18683da5c369Sopenharmony_ci Errno::result(res).map(drop) 18693da5c369Sopenharmony_ci } 18703da5c369Sopenharmony_ci 18713da5c369Sopenharmony_ci /// Disable process accounting 18723da5c369Sopenharmony_ci pub fn disable() -> Result<()> { 18733da5c369Sopenharmony_ci let res = unsafe { libc::acct(ptr::null()) }; 18743da5c369Sopenharmony_ci 18753da5c369Sopenharmony_ci Errno::result(res).map(drop) 18763da5c369Sopenharmony_ci } 18773da5c369Sopenharmony_ci} 18783da5c369Sopenharmony_ci} 18793da5c369Sopenharmony_ci 18803da5c369Sopenharmony_cifeature! { 18813da5c369Sopenharmony_ci#![feature = "fs"] 18823da5c369Sopenharmony_ci/// Creates a regular file which persists even after process termination 18833da5c369Sopenharmony_ci/// 18843da5c369Sopenharmony_ci/// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX` 18853da5c369Sopenharmony_ci/// * returns: tuple of file descriptor and filename 18863da5c369Sopenharmony_ci/// 18873da5c369Sopenharmony_ci/// Err is returned either if no temporary filename could be created or the template doesn't 18883da5c369Sopenharmony_ci/// end with XXXXXX 18893da5c369Sopenharmony_ci/// 18903da5c369Sopenharmony_ci/// See also [mkstemp(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html) 18913da5c369Sopenharmony_ci/// 18923da5c369Sopenharmony_ci/// # Example 18933da5c369Sopenharmony_ci/// 18943da5c369Sopenharmony_ci/// ```rust 18953da5c369Sopenharmony_ci/// use nix::unistd; 18963da5c369Sopenharmony_ci/// 18973da5c369Sopenharmony_ci/// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") { 18983da5c369Sopenharmony_ci/// Ok((fd, path)) => { 18993da5c369Sopenharmony_ci/// unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination 19003da5c369Sopenharmony_ci/// fd 19013da5c369Sopenharmony_ci/// } 19023da5c369Sopenharmony_ci/// Err(e) => panic!("mkstemp failed: {}", e) 19033da5c369Sopenharmony_ci/// }; 19043da5c369Sopenharmony_ci/// // do something with fd 19053da5c369Sopenharmony_ci/// ``` 19063da5c369Sopenharmony_ci#[inline] 19073da5c369Sopenharmony_cipub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> { 19083da5c369Sopenharmony_ci let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?; 19093da5c369Sopenharmony_ci let p = path.as_mut_ptr() as *mut _; 19103da5c369Sopenharmony_ci let fd = unsafe { libc::mkstemp(p) }; 19113da5c369Sopenharmony_ci let last = path.pop(); // drop the trailing nul 19123da5c369Sopenharmony_ci debug_assert!(last == Some(b'\0')); 19133da5c369Sopenharmony_ci let pathname = OsString::from_vec(path); 19143da5c369Sopenharmony_ci Errno::result(fd)?; 19153da5c369Sopenharmony_ci Ok((fd, PathBuf::from(pathname))) 19163da5c369Sopenharmony_ci} 19173da5c369Sopenharmony_ci} 19183da5c369Sopenharmony_ci 19193da5c369Sopenharmony_cifeature! { 19203da5c369Sopenharmony_ci#![all(feature = "fs", feature = "feature")] 19213da5c369Sopenharmony_ci 19223da5c369Sopenharmony_ci/// Variable names for `pathconf` 19233da5c369Sopenharmony_ci/// 19243da5c369Sopenharmony_ci/// Nix uses the same naming convention for these variables as the 19253da5c369Sopenharmony_ci/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility. 19263da5c369Sopenharmony_ci/// That is, `PathconfVar` variables have the same name as the abstract 19273da5c369Sopenharmony_ci/// variables shown in the `pathconf(2)` man page. Usually, it's the same as 19283da5c369Sopenharmony_ci/// the C variable name without the leading `_PC_`. 19293da5c369Sopenharmony_ci/// 19303da5c369Sopenharmony_ci/// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose 19313da5c369Sopenharmony_ci/// not to implement variables that cannot change at runtime. 19323da5c369Sopenharmony_ci/// 19333da5c369Sopenharmony_ci/// # References 19343da5c369Sopenharmony_ci/// 19353da5c369Sopenharmony_ci/// - [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) 19363da5c369Sopenharmony_ci/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) 19373da5c369Sopenharmony_ci/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html) 19383da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 19393da5c369Sopenharmony_ci#[repr(i32)] 19403da5c369Sopenharmony_ci#[non_exhaustive] 19413da5c369Sopenharmony_cipub enum PathconfVar { 19423da5c369Sopenharmony_ci #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux", 19433da5c369Sopenharmony_ci target_os = "netbsd", target_os = "openbsd", target_os = "redox"))] 19443da5c369Sopenharmony_ci /// Minimum number of bits needed to represent, as a signed integer value, 19453da5c369Sopenharmony_ci /// the maximum size of a regular file allowed in the specified directory. 19463da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19473da5c369Sopenharmony_ci FILESIZEBITS = libc::_PC_FILESIZEBITS, 19483da5c369Sopenharmony_ci /// Maximum number of links to a single file. 19493da5c369Sopenharmony_ci LINK_MAX = libc::_PC_LINK_MAX, 19503da5c369Sopenharmony_ci /// Maximum number of bytes in a terminal canonical input line. 19513da5c369Sopenharmony_ci MAX_CANON = libc::_PC_MAX_CANON, 19523da5c369Sopenharmony_ci /// Minimum number of bytes for which space is available in a terminal input 19533da5c369Sopenharmony_ci /// queue; therefore, the maximum number of bytes a conforming application 19543da5c369Sopenharmony_ci /// may require to be typed as input before reading them. 19553da5c369Sopenharmony_ci MAX_INPUT = libc::_PC_MAX_INPUT, 19563da5c369Sopenharmony_ci /// Maximum number of bytes in a filename (not including the terminating 19573da5c369Sopenharmony_ci /// null of a filename string). 19583da5c369Sopenharmony_ci NAME_MAX = libc::_PC_NAME_MAX, 19593da5c369Sopenharmony_ci /// Maximum number of bytes the implementation will store as a pathname in a 19603da5c369Sopenharmony_ci /// user-supplied buffer of unspecified size, including the terminating null 19613da5c369Sopenharmony_ci /// character. Minimum number the implementation will accept as the maximum 19623da5c369Sopenharmony_ci /// number of bytes in a pathname. 19633da5c369Sopenharmony_ci PATH_MAX = libc::_PC_PATH_MAX, 19643da5c369Sopenharmony_ci /// Maximum number of bytes that is guaranteed to be atomic when writing to 19653da5c369Sopenharmony_ci /// a pipe. 19663da5c369Sopenharmony_ci PIPE_BUF = libc::_PC_PIPE_BUF, 19673da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "illumos", 19683da5c369Sopenharmony_ci target_os = "linux", target_os = "netbsd", target_os = "openbsd", 19693da5c369Sopenharmony_ci target_os = "redox", target_os = "solaris"))] 19703da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19713da5c369Sopenharmony_ci /// Symbolic links can be created. 19723da5c369Sopenharmony_ci POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS, 19733da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 19743da5c369Sopenharmony_ci target_os = "linux", target_os = "openbsd", target_os = "redox"))] 19753da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19763da5c369Sopenharmony_ci /// Minimum number of bytes of storage actually allocated for any portion of 19773da5c369Sopenharmony_ci /// a file. 19783da5c369Sopenharmony_ci POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN, 19793da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 19803da5c369Sopenharmony_ci target_os = "linux", target_os = "openbsd"))] 19813da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19823da5c369Sopenharmony_ci /// Recommended increment for file transfer sizes between the 19833da5c369Sopenharmony_ci /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values. 19843da5c369Sopenharmony_ci POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE, 19853da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 19863da5c369Sopenharmony_ci target_os = "linux", target_os = "openbsd", target_os = "redox"))] 19873da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19883da5c369Sopenharmony_ci /// Maximum recommended file transfer size. 19893da5c369Sopenharmony_ci POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE, 19903da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 19913da5c369Sopenharmony_ci target_os = "linux", target_os = "openbsd", target_os = "redox"))] 19923da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19933da5c369Sopenharmony_ci /// Minimum recommended file transfer size. 19943da5c369Sopenharmony_ci POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE, 19953da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 19963da5c369Sopenharmony_ci target_os = "linux", target_os = "openbsd", target_os = "redox"))] 19973da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 19983da5c369Sopenharmony_ci /// Recommended file transfer buffer alignment. 19993da5c369Sopenharmony_ci POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN, 20003da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 20013da5c369Sopenharmony_ci target_os = "illumos", target_os = "linux", target_os = "netbsd", 20023da5c369Sopenharmony_ci target_os = "openbsd", target_os = "redox", target_os = "solaris"))] 20033da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 20043da5c369Sopenharmony_ci /// Maximum number of bytes in a symbolic link. 20053da5c369Sopenharmony_ci SYMLINK_MAX = libc::_PC_SYMLINK_MAX, 20063da5c369Sopenharmony_ci /// The use of `chown` and `fchown` is restricted to a process with 20073da5c369Sopenharmony_ci /// appropriate privileges, and to changing the group ID of a file only to 20083da5c369Sopenharmony_ci /// the effective group ID of the process or to one of its supplementary 20093da5c369Sopenharmony_ci /// group IDs. 20103da5c369Sopenharmony_ci _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED, 20113da5c369Sopenharmony_ci /// Pathname components longer than {NAME_MAX} generate an error. 20123da5c369Sopenharmony_ci _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC, 20133da5c369Sopenharmony_ci /// This symbol shall be defined to be the value of a character that shall 20143da5c369Sopenharmony_ci /// disable terminal special character handling. 20153da5c369Sopenharmony_ci _POSIX_VDISABLE = libc::_PC_VDISABLE, 20163da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 20173da5c369Sopenharmony_ci target_os = "illumos", target_os = "linux", target_os = "openbsd", 20183da5c369Sopenharmony_ci target_os = "redox", target_os = "solaris"))] 20193da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 20203da5c369Sopenharmony_ci /// Asynchronous input or output operations may be performed for the 20213da5c369Sopenharmony_ci /// associated file. 20223da5c369Sopenharmony_ci _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO, 20233da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 20243da5c369Sopenharmony_ci target_os = "illumos", target_os = "linux", target_os = "openbsd", 20253da5c369Sopenharmony_ci target_os = "redox", target_os = "solaris"))] 20263da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 20273da5c369Sopenharmony_ci /// Prioritized input or output operations may be performed for the 20283da5c369Sopenharmony_ci /// associated file. 20293da5c369Sopenharmony_ci _POSIX_PRIO_IO = libc::_PC_PRIO_IO, 20303da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", 20313da5c369Sopenharmony_ci target_os = "illumos", target_os = "linux", target_os = "netbsd", 20323da5c369Sopenharmony_ci target_os = "openbsd", target_os = "redox", target_os = "solaris"))] 20333da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 20343da5c369Sopenharmony_ci /// Synchronized input or output operations may be performed for the 20353da5c369Sopenharmony_ci /// associated file. 20363da5c369Sopenharmony_ci _POSIX_SYNC_IO = libc::_PC_SYNC_IO, 20373da5c369Sopenharmony_ci #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] 20383da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 20393da5c369Sopenharmony_ci /// The resolution in nanoseconds for all file timestamps. 20403da5c369Sopenharmony_ci _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION 20413da5c369Sopenharmony_ci} 20423da5c369Sopenharmony_ci 20433da5c369Sopenharmony_ci/// Like `pathconf`, but works with file descriptors instead of paths (see 20443da5c369Sopenharmony_ci/// [fpathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)) 20453da5c369Sopenharmony_ci/// 20463da5c369Sopenharmony_ci/// # Parameters 20473da5c369Sopenharmony_ci/// 20483da5c369Sopenharmony_ci/// - `fd`: The file descriptor whose variable should be interrogated 20493da5c369Sopenharmony_ci/// - `var`: The pathconf variable to lookup 20503da5c369Sopenharmony_ci/// 20513da5c369Sopenharmony_ci/// # Returns 20523da5c369Sopenharmony_ci/// 20533da5c369Sopenharmony_ci/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its 20543da5c369Sopenharmony_ci/// implementation level (for option variables). Implementation levels are 20553da5c369Sopenharmony_ci/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 20563da5c369Sopenharmony_ci/// - `Ok(None)`: the variable has no limit (for limit variables) or is 20573da5c369Sopenharmony_ci/// unsupported (for option variables) 20583da5c369Sopenharmony_ci/// - `Err(x)`: an error occurred 20593da5c369Sopenharmony_cipub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> { 20603da5c369Sopenharmony_ci let raw = unsafe { 20613da5c369Sopenharmony_ci Errno::clear(); 20623da5c369Sopenharmony_ci libc::fpathconf(fd, var as c_int) 20633da5c369Sopenharmony_ci }; 20643da5c369Sopenharmony_ci if raw == -1 { 20653da5c369Sopenharmony_ci if errno::errno() == 0 { 20663da5c369Sopenharmony_ci Ok(None) 20673da5c369Sopenharmony_ci } else { 20683da5c369Sopenharmony_ci Err(Errno::last()) 20693da5c369Sopenharmony_ci } 20703da5c369Sopenharmony_ci } else { 20713da5c369Sopenharmony_ci Ok(Some(raw)) 20723da5c369Sopenharmony_ci } 20733da5c369Sopenharmony_ci} 20743da5c369Sopenharmony_ci 20753da5c369Sopenharmony_ci/// Get path-dependent configurable system variables (see 20763da5c369Sopenharmony_ci/// [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)) 20773da5c369Sopenharmony_ci/// 20783da5c369Sopenharmony_ci/// Returns the value of a path-dependent configurable system variable. Most 20793da5c369Sopenharmony_ci/// supported variables also have associated compile-time constants, but POSIX 20803da5c369Sopenharmony_ci/// allows their values to change at runtime. There are generally two types of 20813da5c369Sopenharmony_ci/// `pathconf` variables: options and limits. See [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details. 20823da5c369Sopenharmony_ci/// 20833da5c369Sopenharmony_ci/// # Parameters 20843da5c369Sopenharmony_ci/// 20853da5c369Sopenharmony_ci/// - `path`: Lookup the value of `var` for this file or directory 20863da5c369Sopenharmony_ci/// - `var`: The `pathconf` variable to lookup 20873da5c369Sopenharmony_ci/// 20883da5c369Sopenharmony_ci/// # Returns 20893da5c369Sopenharmony_ci/// 20903da5c369Sopenharmony_ci/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its 20913da5c369Sopenharmony_ci/// implementation level (for option variables). Implementation levels are 20923da5c369Sopenharmony_ci/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 20933da5c369Sopenharmony_ci/// - `Ok(None)`: the variable has no limit (for limit variables) or is 20943da5c369Sopenharmony_ci/// unsupported (for option variables) 20953da5c369Sopenharmony_ci/// - `Err(x)`: an error occurred 20963da5c369Sopenharmony_cipub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>> { 20973da5c369Sopenharmony_ci let raw = path.with_nix_path(|cstr| { 20983da5c369Sopenharmony_ci unsafe { 20993da5c369Sopenharmony_ci Errno::clear(); 21003da5c369Sopenharmony_ci libc::pathconf(cstr.as_ptr(), var as c_int) 21013da5c369Sopenharmony_ci } 21023da5c369Sopenharmony_ci })?; 21033da5c369Sopenharmony_ci if raw == -1 { 21043da5c369Sopenharmony_ci if errno::errno() == 0 { 21053da5c369Sopenharmony_ci Ok(None) 21063da5c369Sopenharmony_ci } else { 21073da5c369Sopenharmony_ci Err(Errno::last()) 21083da5c369Sopenharmony_ci } 21093da5c369Sopenharmony_ci } else { 21103da5c369Sopenharmony_ci Ok(Some(raw)) 21113da5c369Sopenharmony_ci } 21123da5c369Sopenharmony_ci} 21133da5c369Sopenharmony_ci} 21143da5c369Sopenharmony_ci 21153da5c369Sopenharmony_cifeature! { 21163da5c369Sopenharmony_ci#![feature = "feature"] 21173da5c369Sopenharmony_ci 21183da5c369Sopenharmony_ci/// Variable names for `sysconf` 21193da5c369Sopenharmony_ci/// 21203da5c369Sopenharmony_ci/// Nix uses the same naming convention for these variables as the 21213da5c369Sopenharmony_ci/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility. 21223da5c369Sopenharmony_ci/// That is, `SysconfVar` variables have the same name as the abstract variables 21233da5c369Sopenharmony_ci/// shown in the `sysconf(3)` man page. Usually, it's the same as the C 21243da5c369Sopenharmony_ci/// variable name without the leading `_SC_`. 21253da5c369Sopenharmony_ci/// 21263da5c369Sopenharmony_ci/// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been 21273da5c369Sopenharmony_ci/// implemented by all platforms. 21283da5c369Sopenharmony_ci/// 21293da5c369Sopenharmony_ci/// # References 21303da5c369Sopenharmony_ci/// 21313da5c369Sopenharmony_ci/// - [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html) 21323da5c369Sopenharmony_ci/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html) 21333da5c369Sopenharmony_ci/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) 21343da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 21353da5c369Sopenharmony_ci#[repr(i32)] 21363da5c369Sopenharmony_ci#[non_exhaustive] 21373da5c369Sopenharmony_cipub enum SysconfVar { 21383da5c369Sopenharmony_ci /// Maximum number of I/O operations in a single list I/O call supported by 21393da5c369Sopenharmony_ci /// the implementation. 21403da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21413da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21423da5c369Sopenharmony_ci AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX, 21433da5c369Sopenharmony_ci /// Maximum number of outstanding asynchronous I/O operations supported by 21443da5c369Sopenharmony_ci /// the implementation. 21453da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21463da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21473da5c369Sopenharmony_ci AIO_MAX = libc::_SC_AIO_MAX, 21483da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 21493da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 21503da5c369Sopenharmony_ci target_os="openbsd"))] 21513da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21523da5c369Sopenharmony_ci /// The maximum amount by which a process can decrease its asynchronous I/O 21533da5c369Sopenharmony_ci /// priority level from its own scheduling priority. 21543da5c369Sopenharmony_ci AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX, 21553da5c369Sopenharmony_ci /// Maximum length of argument to the exec functions including environment data. 21563da5c369Sopenharmony_ci ARG_MAX = libc::_SC_ARG_MAX, 21573da5c369Sopenharmony_ci /// Maximum number of functions that may be registered with `atexit`. 21583da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 21593da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21603da5c369Sopenharmony_ci ATEXIT_MAX = libc::_SC_ATEXIT_MAX, 21613da5c369Sopenharmony_ci /// Maximum obase values allowed by the bc utility. 21623da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21633da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21643da5c369Sopenharmony_ci BC_BASE_MAX = libc::_SC_BC_BASE_MAX, 21653da5c369Sopenharmony_ci /// Maximum number of elements permitted in an array by the bc utility. 21663da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21673da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21683da5c369Sopenharmony_ci BC_DIM_MAX = libc::_SC_BC_DIM_MAX, 21693da5c369Sopenharmony_ci /// Maximum scale value allowed by the bc utility. 21703da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21713da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21723da5c369Sopenharmony_ci BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX, 21733da5c369Sopenharmony_ci /// Maximum length of a string constant accepted by the bc utility. 21743da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21753da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21763da5c369Sopenharmony_ci BC_STRING_MAX = libc::_SC_BC_STRING_MAX, 21773da5c369Sopenharmony_ci /// Maximum number of simultaneous processes per real user ID. 21783da5c369Sopenharmony_ci CHILD_MAX = libc::_SC_CHILD_MAX, 21793da5c369Sopenharmony_ci // The number of clock ticks per second. 21803da5c369Sopenharmony_ci CLK_TCK = libc::_SC_CLK_TCK, 21813da5c369Sopenharmony_ci /// Maximum number of weights that can be assigned to an entry of the 21823da5c369Sopenharmony_ci /// LC_COLLATE order keyword in the locale definition file 21833da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21843da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21853da5c369Sopenharmony_ci COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX, 21863da5c369Sopenharmony_ci /// Maximum number of timer expiration overruns. 21873da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21883da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21893da5c369Sopenharmony_ci DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX, 21903da5c369Sopenharmony_ci /// Maximum number of expressions that can be nested within parentheses by 21913da5c369Sopenharmony_ci /// the expr utility. 21923da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 21933da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21943da5c369Sopenharmony_ci EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX, 21953da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 21963da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 21973da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 21983da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 21993da5c369Sopenharmony_ci /// Maximum length of a host name (not including the terminating null) as 22003da5c369Sopenharmony_ci /// returned from the `gethostname` function 22013da5c369Sopenharmony_ci HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX, 22023da5c369Sopenharmony_ci /// Maximum number of iovec structures that one process has available for 22033da5c369Sopenharmony_ci /// use with `readv` or `writev`. 22043da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 22053da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22063da5c369Sopenharmony_ci IOV_MAX = libc::_SC_IOV_MAX, 22073da5c369Sopenharmony_ci /// Unless otherwise noted, the maximum length, in bytes, of a utility's 22083da5c369Sopenharmony_ci /// input line (either standard input or another file), when the utility is 22093da5c369Sopenharmony_ci /// described as processing text files. The length includes room for the 22103da5c369Sopenharmony_ci /// trailing newline. 22113da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22123da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22133da5c369Sopenharmony_ci LINE_MAX = libc::_SC_LINE_MAX, 22143da5c369Sopenharmony_ci /// Maximum length of a login name. 22153da5c369Sopenharmony_ci #[cfg(not(target_os = "haiku"))] 22163da5c369Sopenharmony_ci LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX, 22173da5c369Sopenharmony_ci /// Maximum number of simultaneous supplementary group IDs per process. 22183da5c369Sopenharmony_ci NGROUPS_MAX = libc::_SC_NGROUPS_MAX, 22193da5c369Sopenharmony_ci /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers 22203da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 22213da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22223da5c369Sopenharmony_ci GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX, 22233da5c369Sopenharmony_ci /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers 22243da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 22253da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22263da5c369Sopenharmony_ci GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX, 22273da5c369Sopenharmony_ci /// The maximum number of open message queue descriptors a process may hold. 22283da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22293da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22303da5c369Sopenharmony_ci MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX, 22313da5c369Sopenharmony_ci /// The maximum number of message priorities supported by the implementation. 22323da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22333da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22343da5c369Sopenharmony_ci MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX, 22353da5c369Sopenharmony_ci /// A value one greater than the maximum value that the system may assign to 22363da5c369Sopenharmony_ci /// a newly-created file descriptor. 22373da5c369Sopenharmony_ci OPEN_MAX = libc::_SC_OPEN_MAX, 22383da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 22393da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 22403da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22413da5c369Sopenharmony_ci /// The implementation supports the Advisory Information option. 22423da5c369Sopenharmony_ci _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO, 22433da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 22443da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 22453da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 22463da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22473da5c369Sopenharmony_ci /// The implementation supports barriers. 22483da5c369Sopenharmony_ci _POSIX_BARRIERS = libc::_SC_BARRIERS, 22493da5c369Sopenharmony_ci /// The implementation supports asynchronous input and output. 22503da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22513da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22523da5c369Sopenharmony_ci _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO, 22533da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 22543da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 22553da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 22563da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22573da5c369Sopenharmony_ci /// The implementation supports clock selection. 22583da5c369Sopenharmony_ci _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION, 22593da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 22603da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 22613da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 22623da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22633da5c369Sopenharmony_ci /// The implementation supports the Process CPU-Time Clocks option. 22643da5c369Sopenharmony_ci _POSIX_CPUTIME = libc::_SC_CPUTIME, 22653da5c369Sopenharmony_ci /// The implementation supports the File Synchronization option. 22663da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22673da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22683da5c369Sopenharmony_ci _POSIX_FSYNC = libc::_SC_FSYNC, 22693da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 22703da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 22713da5c369Sopenharmony_ci target_os="openbsd", target_os = "solaris"))] 22723da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22733da5c369Sopenharmony_ci /// The implementation supports the IPv6 option. 22743da5c369Sopenharmony_ci _POSIX_IPV6 = libc::_SC_IPV6, 22753da5c369Sopenharmony_ci /// The implementation supports job control. 22763da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 22773da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22783da5c369Sopenharmony_ci _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL, 22793da5c369Sopenharmony_ci /// The implementation supports memory mapped Files. 22803da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22813da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22823da5c369Sopenharmony_ci _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES, 22833da5c369Sopenharmony_ci /// The implementation supports the Process Memory Locking option. 22843da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22853da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22863da5c369Sopenharmony_ci _POSIX_MEMLOCK = libc::_SC_MEMLOCK, 22873da5c369Sopenharmony_ci /// The implementation supports the Range Memory Locking option. 22883da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22893da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22903da5c369Sopenharmony_ci _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE, 22913da5c369Sopenharmony_ci /// The implementation supports memory protection. 22923da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 22933da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22943da5c369Sopenharmony_ci _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION, 22953da5c369Sopenharmony_ci /// The implementation supports the Message Passing option. 22963da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 22973da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 22983da5c369Sopenharmony_ci _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING, 22993da5c369Sopenharmony_ci /// The implementation supports the Monotonic Clock option. 23003da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 23013da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23023da5c369Sopenharmony_ci _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK, 23033da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 23043da5c369Sopenharmony_ci target_os = "illumos", target_os = "ios", target_os="linux", 23053da5c369Sopenharmony_ci target_os = "macos", target_os="openbsd", target_os = "solaris"))] 23063da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23073da5c369Sopenharmony_ci /// The implementation supports the Prioritized Input and Output option. 23083da5c369Sopenharmony_ci _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO, 23093da5c369Sopenharmony_ci /// The implementation supports the Process Scheduling option. 23103da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 23113da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23123da5c369Sopenharmony_ci _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING, 23133da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 23143da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 23153da5c369Sopenharmony_ci target_os="openbsd", target_os = "solaris"))] 23163da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23173da5c369Sopenharmony_ci /// The implementation supports the Raw Sockets option. 23183da5c369Sopenharmony_ci _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS, 23193da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 23203da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 23213da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 23223da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23233da5c369Sopenharmony_ci /// The implementation supports read-write locks. 23243da5c369Sopenharmony_ci _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS, 23253da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd", 23263da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 23273da5c369Sopenharmony_ci target_os = "openbsd"))] 23283da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23293da5c369Sopenharmony_ci /// The implementation supports realtime signals. 23303da5c369Sopenharmony_ci _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS, 23313da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", 23323da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 23333da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd", target_os = "solaris"))] 23343da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23353da5c369Sopenharmony_ci /// The implementation supports the Regular Expression Handling option. 23363da5c369Sopenharmony_ci _POSIX_REGEXP = libc::_SC_REGEXP, 23373da5c369Sopenharmony_ci /// Each process has a saved set-user-ID and a saved set-group-ID. 23383da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 23393da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23403da5c369Sopenharmony_ci _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS, 23413da5c369Sopenharmony_ci /// The implementation supports semaphores. 23423da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 23433da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23443da5c369Sopenharmony_ci _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES, 23453da5c369Sopenharmony_ci /// The implementation supports the Shared Memory Objects option. 23463da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 23473da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23483da5c369Sopenharmony_ci _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS, 23493da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 23503da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 23513da5c369Sopenharmony_ci target_os="openbsd"))] 23523da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23533da5c369Sopenharmony_ci /// The implementation supports the POSIX shell. 23543da5c369Sopenharmony_ci _POSIX_SHELL = libc::_SC_SHELL, 23553da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 23563da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 23573da5c369Sopenharmony_ci target_os="openbsd"))] 23583da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23593da5c369Sopenharmony_ci /// The implementation supports the Spawn option. 23603da5c369Sopenharmony_ci _POSIX_SPAWN = libc::_SC_SPAWN, 23613da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 23623da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 23633da5c369Sopenharmony_ci target_os="openbsd"))] 23643da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23653da5c369Sopenharmony_ci /// The implementation supports spin locks. 23663da5c369Sopenharmony_ci _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS, 23673da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 23683da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 23693da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23703da5c369Sopenharmony_ci /// The implementation supports the Process Sporadic Server option. 23713da5c369Sopenharmony_ci _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER, 23723da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 23733da5c369Sopenharmony_ci target_os="openbsd"))] 23743da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23753da5c369Sopenharmony_ci _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX, 23763da5c369Sopenharmony_ci /// The implementation supports the Synchronized Input and Output option. 23773da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 23783da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23793da5c369Sopenharmony_ci _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO, 23803da5c369Sopenharmony_ci /// The implementation supports the Thread Stack Address Attribute option. 23813da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 23823da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23833da5c369Sopenharmony_ci _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR, 23843da5c369Sopenharmony_ci /// The implementation supports the Thread Stack Size Attribute option. 23853da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 23863da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23873da5c369Sopenharmony_ci _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE, 23883da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 23893da5c369Sopenharmony_ci target_os="netbsd", target_os="openbsd"))] 23903da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23913da5c369Sopenharmony_ci /// The implementation supports the Thread CPU-Time Clocks option. 23923da5c369Sopenharmony_ci _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME, 23933da5c369Sopenharmony_ci /// The implementation supports the Non-Robust Mutex Priority Inheritance 23943da5c369Sopenharmony_ci /// option. 23953da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 23963da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 23973da5c369Sopenharmony_ci _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT, 23983da5c369Sopenharmony_ci /// The implementation supports the Non-Robust Mutex Priority Protection option. 23993da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 24003da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24013da5c369Sopenharmony_ci _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT, 24023da5c369Sopenharmony_ci /// The implementation supports the Thread Execution Scheduling option. 24033da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 24043da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24053da5c369Sopenharmony_ci _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING, 24063da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24073da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 24083da5c369Sopenharmony_ci target_os="openbsd"))] 24093da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24103da5c369Sopenharmony_ci /// The implementation supports the Thread Process-Shared Synchronization 24113da5c369Sopenharmony_ci /// option. 24123da5c369Sopenharmony_ci _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED, 24133da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))] 24143da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24153da5c369Sopenharmony_ci /// The implementation supports the Robust Mutex Priority Inheritance option. 24163da5c369Sopenharmony_ci _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT, 24173da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))] 24183da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24193da5c369Sopenharmony_ci /// The implementation supports the Robust Mutex Priority Protection option. 24203da5c369Sopenharmony_ci _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT, 24213da5c369Sopenharmony_ci /// The implementation supports thread-safe functions. 24223da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 24233da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24243da5c369Sopenharmony_ci _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS, 24253da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24263da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24273da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24283da5c369Sopenharmony_ci /// The implementation supports the Thread Sporadic Server option. 24293da5c369Sopenharmony_ci _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER, 24303da5c369Sopenharmony_ci /// The implementation supports threads. 24313da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 24323da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24333da5c369Sopenharmony_ci _POSIX_THREADS = libc::_SC_THREADS, 24343da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24353da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24363da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24373da5c369Sopenharmony_ci /// The implementation supports timeouts. 24383da5c369Sopenharmony_ci _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS, 24393da5c369Sopenharmony_ci /// The implementation supports timers. 24403da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 24413da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24423da5c369Sopenharmony_ci _POSIX_TIMERS = libc::_SC_TIMERS, 24433da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24443da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24453da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24463da5c369Sopenharmony_ci /// The implementation supports the Trace option. 24473da5c369Sopenharmony_ci _POSIX_TRACE = libc::_SC_TRACE, 24483da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24493da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24503da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24513da5c369Sopenharmony_ci /// The implementation supports the Trace Event Filter option. 24523da5c369Sopenharmony_ci _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER, 24533da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 24543da5c369Sopenharmony_ci target_os="openbsd"))] 24553da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24563da5c369Sopenharmony_ci _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX, 24573da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24583da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24593da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24603da5c369Sopenharmony_ci /// The implementation supports the Trace Inherit option. 24613da5c369Sopenharmony_ci _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT, 24623da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24633da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24643da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24653da5c369Sopenharmony_ci /// The implementation supports the Trace Log option. 24663da5c369Sopenharmony_ci _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG, 24673da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 24683da5c369Sopenharmony_ci target_os="openbsd"))] 24693da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24703da5c369Sopenharmony_ci _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX, 24713da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 24723da5c369Sopenharmony_ci target_os="openbsd"))] 24733da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24743da5c369Sopenharmony_ci _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX, 24753da5c369Sopenharmony_ci #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", 24763da5c369Sopenharmony_ci target_os="openbsd"))] 24773da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24783da5c369Sopenharmony_ci _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX, 24793da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24803da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 24813da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24823da5c369Sopenharmony_ci /// The implementation supports the Typed Memory Objects option. 24833da5c369Sopenharmony_ci _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS, 24843da5c369Sopenharmony_ci /// Integer value indicating version of this standard (C-language binding) 24853da5c369Sopenharmony_ci /// to which the implementation conforms. For implementations conforming to 24863da5c369Sopenharmony_ci /// POSIX.1-2008, the value shall be 200809L. 24873da5c369Sopenharmony_ci _POSIX_VERSION = libc::_SC_VERSION, 24883da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24893da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 24903da5c369Sopenharmony_ci target_os="openbsd"))] 24913da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24923da5c369Sopenharmony_ci /// The implementation provides a C-language compilation environment with 24933da5c369Sopenharmony_ci /// 32-bit `int`, `long`, `pointer`, and `off_t` types. 24943da5c369Sopenharmony_ci _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32, 24953da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 24963da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 24973da5c369Sopenharmony_ci target_os="openbsd"))] 24983da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 24993da5c369Sopenharmony_ci /// The implementation provides a C-language compilation environment with 25003da5c369Sopenharmony_ci /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at 25013da5c369Sopenharmony_ci /// least 64 bits. 25023da5c369Sopenharmony_ci _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG, 25033da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25043da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25053da5c369Sopenharmony_ci target_os="openbsd"))] 25063da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25073da5c369Sopenharmony_ci /// The implementation provides a C-language compilation environment with 25083da5c369Sopenharmony_ci /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types. 25093da5c369Sopenharmony_ci _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64, 25103da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25113da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25123da5c369Sopenharmony_ci target_os="openbsd"))] 25133da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25143da5c369Sopenharmony_ci /// The implementation provides a C-language compilation environment with an 25153da5c369Sopenharmony_ci /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types 25163da5c369Sopenharmony_ci /// using at least 64 bits. 25173da5c369Sopenharmony_ci _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG, 25183da5c369Sopenharmony_ci /// The implementation supports the C-Language Binding option. 25193da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25203da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25213da5c369Sopenharmony_ci _POSIX2_C_BIND = libc::_SC_2_C_BIND, 25223da5c369Sopenharmony_ci /// The implementation supports the C-Language Development Utilities option. 25233da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25243da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25253da5c369Sopenharmony_ci _POSIX2_C_DEV = libc::_SC_2_C_DEV, 25263da5c369Sopenharmony_ci /// The implementation supports the Terminal Characteristics option. 25273da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25283da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25293da5c369Sopenharmony_ci _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM, 25303da5c369Sopenharmony_ci /// The implementation supports the FORTRAN Development Utilities option. 25313da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25323da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25333da5c369Sopenharmony_ci _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV, 25343da5c369Sopenharmony_ci /// The implementation supports the FORTRAN Runtime Utilities option. 25353da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25363da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25373da5c369Sopenharmony_ci _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN, 25383da5c369Sopenharmony_ci /// The implementation supports the creation of locales by the localedef 25393da5c369Sopenharmony_ci /// utility. 25403da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25413da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25423da5c369Sopenharmony_ci _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF, 25433da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25443da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25453da5c369Sopenharmony_ci target_os="openbsd"))] 25463da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25473da5c369Sopenharmony_ci /// The implementation supports the Batch Environment Services and Utilities 25483da5c369Sopenharmony_ci /// option. 25493da5c369Sopenharmony_ci _POSIX2_PBS = libc::_SC_2_PBS, 25503da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25513da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25523da5c369Sopenharmony_ci target_os="openbsd"))] 25533da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25543da5c369Sopenharmony_ci /// The implementation supports the Batch Accounting option. 25553da5c369Sopenharmony_ci _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING, 25563da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25573da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25583da5c369Sopenharmony_ci target_os="openbsd"))] 25593da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25603da5c369Sopenharmony_ci /// The implementation supports the Batch Checkpoint/Restart option. 25613da5c369Sopenharmony_ci _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT, 25623da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25633da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25643da5c369Sopenharmony_ci target_os="openbsd"))] 25653da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25663da5c369Sopenharmony_ci /// The implementation supports the Locate Batch Job Request option. 25673da5c369Sopenharmony_ci _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE, 25683da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25693da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25703da5c369Sopenharmony_ci target_os="openbsd"))] 25713da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25723da5c369Sopenharmony_ci /// The implementation supports the Batch Job Message Request option. 25733da5c369Sopenharmony_ci _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE, 25743da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 25753da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 25763da5c369Sopenharmony_ci target_os="openbsd"))] 25773da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25783da5c369Sopenharmony_ci /// The implementation supports the Track Batch Job Request option. 25793da5c369Sopenharmony_ci _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK, 25803da5c369Sopenharmony_ci /// The implementation supports the Software Development Utilities option. 25813da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25823da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25833da5c369Sopenharmony_ci _POSIX2_SW_DEV = libc::_SC_2_SW_DEV, 25843da5c369Sopenharmony_ci /// The implementation supports the User Portability Utilities option. 25853da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25863da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25873da5c369Sopenharmony_ci _POSIX2_UPE = libc::_SC_2_UPE, 25883da5c369Sopenharmony_ci /// Integer value indicating version of the Shell and Utilities volume of 25893da5c369Sopenharmony_ci /// POSIX.1 to which the implementation conforms. 25903da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25913da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 25923da5c369Sopenharmony_ci _POSIX2_VERSION = libc::_SC_2_VERSION, 25933da5c369Sopenharmony_ci /// The size of a system page in bytes. 25943da5c369Sopenharmony_ci /// 25953da5c369Sopenharmony_ci /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two 25963da5c369Sopenharmony_ci /// enum constants to have the same value, so nix omits `PAGESIZE`. 25973da5c369Sopenharmony_ci PAGE_SIZE = libc::_SC_PAGE_SIZE, 25983da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 25993da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26003da5c369Sopenharmony_ci PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS, 26013da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 26023da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26033da5c369Sopenharmony_ci PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX, 26043da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 26053da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26063da5c369Sopenharmony_ci PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN, 26073da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 26083da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26093da5c369Sopenharmony_ci PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX, 26103da5c369Sopenharmony_ci #[cfg(not(target_os = "haiku"))] 26113da5c369Sopenharmony_ci RE_DUP_MAX = libc::_SC_RE_DUP_MAX, 26123da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26133da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26143da5c369Sopenharmony_ci target_os="openbsd"))] 26153da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26163da5c369Sopenharmony_ci RTSIG_MAX = libc::_SC_RTSIG_MAX, 26173da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 26183da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26193da5c369Sopenharmony_ci SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX, 26203da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26213da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26223da5c369Sopenharmony_ci target_os="openbsd"))] 26233da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26243da5c369Sopenharmony_ci SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX, 26253da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd", 26263da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26273da5c369Sopenharmony_ci target_os = "openbsd"))] 26283da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26293da5c369Sopenharmony_ci SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX, 26303da5c369Sopenharmony_ci STREAM_MAX = libc::_SC_STREAM_MAX, 26313da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 26323da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="netbsd", 26333da5c369Sopenharmony_ci target_os="openbsd"))] 26343da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26353da5c369Sopenharmony_ci SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX, 26363da5c369Sopenharmony_ci #[cfg(not(target_os = "redox"))] 26373da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26383da5c369Sopenharmony_ci TIMER_MAX = libc::_SC_TIMER_MAX, 26393da5c369Sopenharmony_ci TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX, 26403da5c369Sopenharmony_ci TZNAME_MAX = libc::_SC_TZNAME_MAX, 26413da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26423da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26433da5c369Sopenharmony_ci target_os="openbsd"))] 26443da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26453da5c369Sopenharmony_ci /// The implementation supports the X/Open Encryption Option Group. 26463da5c369Sopenharmony_ci _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT, 26473da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26483da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26493da5c369Sopenharmony_ci target_os="openbsd"))] 26503da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26513da5c369Sopenharmony_ci /// The implementation supports the Issue 4, Version 2 Enhanced 26523da5c369Sopenharmony_ci /// Internationalization Option Group. 26533da5c369Sopenharmony_ci _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N, 26543da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26553da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26563da5c369Sopenharmony_ci target_os="openbsd"))] 26573da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26583da5c369Sopenharmony_ci _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY, 26593da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26603da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26613da5c369Sopenharmony_ci target_os="openbsd"))] 26623da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26633da5c369Sopenharmony_ci /// The implementation supports the X/Open Realtime Option Group. 26643da5c369Sopenharmony_ci _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME, 26653da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26663da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26673da5c369Sopenharmony_ci target_os="openbsd"))] 26683da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26693da5c369Sopenharmony_ci /// The implementation supports the X/Open Realtime Threads Option Group. 26703da5c369Sopenharmony_ci _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS, 26713da5c369Sopenharmony_ci /// The implementation supports the Issue 4, Version 2 Shared Memory Option 26723da5c369Sopenharmony_ci /// Group. 26733da5c369Sopenharmony_ci #[cfg(not(any(target_os = "redox", target_os = "haiku")))] 26743da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26753da5c369Sopenharmony_ci _XOPEN_SHM = libc::_SC_XOPEN_SHM, 26763da5c369Sopenharmony_ci #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", 26773da5c369Sopenharmony_ci target_os="linux", target_os = "macos", target_os="openbsd"))] 26783da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26793da5c369Sopenharmony_ci /// The implementation supports the XSI STREAMS Option Group. 26803da5c369Sopenharmony_ci _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS, 26813da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26823da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26833da5c369Sopenharmony_ci target_os="openbsd"))] 26843da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26853da5c369Sopenharmony_ci /// The implementation supports the XSI option 26863da5c369Sopenharmony_ci _XOPEN_UNIX = libc::_SC_XOPEN_UNIX, 26873da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", 26883da5c369Sopenharmony_ci target_os = "ios", target_os="linux", target_os = "macos", 26893da5c369Sopenharmony_ci target_os="openbsd"))] 26903da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 26913da5c369Sopenharmony_ci /// Integer value indicating version of the X/Open Portability Guide to 26923da5c369Sopenharmony_ci /// which the implementation conforms. 26933da5c369Sopenharmony_ci _XOPEN_VERSION = libc::_SC_XOPEN_VERSION, 26943da5c369Sopenharmony_ci /// The number of pages of physical memory. Note that it is possible for 26953da5c369Sopenharmony_ci /// the product of this value to overflow. 26963da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="linux"))] 26973da5c369Sopenharmony_ci _PHYS_PAGES = libc::_SC_PHYS_PAGES, 26983da5c369Sopenharmony_ci /// The number of currently available pages of physical memory. 26993da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="linux"))] 27003da5c369Sopenharmony_ci _AVPHYS_PAGES = libc::_SC_AVPHYS_PAGES, 27013da5c369Sopenharmony_ci /// The number of processors configured. 27023da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="linux"))] 27033da5c369Sopenharmony_ci _NPROCESSORS_CONF = libc::_SC_NPROCESSORS_CONF, 27043da5c369Sopenharmony_ci /// The number of processors currently online (available). 27053da5c369Sopenharmony_ci #[cfg(any(target_os="android", target_os="linux"))] 27063da5c369Sopenharmony_ci _NPROCESSORS_ONLN = libc::_SC_NPROCESSORS_ONLN, 27073da5c369Sopenharmony_ci} 27083da5c369Sopenharmony_ci 27093da5c369Sopenharmony_ci/// Get configurable system variables (see 27103da5c369Sopenharmony_ci/// [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)) 27113da5c369Sopenharmony_ci/// 27123da5c369Sopenharmony_ci/// Returns the value of a configurable system variable. Most supported 27133da5c369Sopenharmony_ci/// variables also have associated compile-time constants, but POSIX 27143da5c369Sopenharmony_ci/// allows their values to change at runtime. There are generally two types of 27153da5c369Sopenharmony_ci/// sysconf variables: options and limits. See sysconf(3) for more details. 27163da5c369Sopenharmony_ci/// 27173da5c369Sopenharmony_ci/// # Returns 27183da5c369Sopenharmony_ci/// 27193da5c369Sopenharmony_ci/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its 27203da5c369Sopenharmony_ci/// implementation level (for option variables). Implementation levels are 27213da5c369Sopenharmony_ci/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 27223da5c369Sopenharmony_ci/// - `Ok(None)`: the variable has no limit (for limit variables) or is 27233da5c369Sopenharmony_ci/// unsupported (for option variables) 27243da5c369Sopenharmony_ci/// - `Err(x)`: an error occurred 27253da5c369Sopenharmony_cipub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> { 27263da5c369Sopenharmony_ci let raw = unsafe { 27273da5c369Sopenharmony_ci Errno::clear(); 27283da5c369Sopenharmony_ci libc::sysconf(var as c_int) 27293da5c369Sopenharmony_ci }; 27303da5c369Sopenharmony_ci if raw == -1 { 27313da5c369Sopenharmony_ci if errno::errno() == 0 { 27323da5c369Sopenharmony_ci Ok(None) 27333da5c369Sopenharmony_ci } else { 27343da5c369Sopenharmony_ci Err(Errno::last()) 27353da5c369Sopenharmony_ci } 27363da5c369Sopenharmony_ci } else { 27373da5c369Sopenharmony_ci Ok(Some(raw)) 27383da5c369Sopenharmony_ci } 27393da5c369Sopenharmony_ci} 27403da5c369Sopenharmony_ci} 27413da5c369Sopenharmony_ci 27423da5c369Sopenharmony_cifeature! { 27433da5c369Sopenharmony_ci#![feature = "fs"] 27443da5c369Sopenharmony_ci 27453da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))] 27463da5c369Sopenharmony_cimod pivot_root { 27473da5c369Sopenharmony_ci use crate::{Result, NixPath}; 27483da5c369Sopenharmony_ci use crate::errno::Errno; 27493da5c369Sopenharmony_ci 27503da5c369Sopenharmony_ci pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>( 27513da5c369Sopenharmony_ci new_root: &P1, put_old: &P2) -> Result<()> { 27523da5c369Sopenharmony_ci let res = new_root.with_nix_path(|new_root| { 27533da5c369Sopenharmony_ci put_old.with_nix_path(|put_old| { 27543da5c369Sopenharmony_ci unsafe { 27553da5c369Sopenharmony_ci libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr()) 27563da5c369Sopenharmony_ci } 27573da5c369Sopenharmony_ci }) 27583da5c369Sopenharmony_ci })??; 27593da5c369Sopenharmony_ci 27603da5c369Sopenharmony_ci Errno::result(res).map(drop) 27613da5c369Sopenharmony_ci } 27623da5c369Sopenharmony_ci} 27633da5c369Sopenharmony_ci} 27643da5c369Sopenharmony_ci 27653da5c369Sopenharmony_ci#[cfg(any( 27663da5c369Sopenharmony_ci target_os = "android", 27673da5c369Sopenharmony_ci target_os = "dragonfly", 27683da5c369Sopenharmony_ci target_os = "freebsd", 27693da5c369Sopenharmony_ci target_os = "linux", 27703da5c369Sopenharmony_ci target_os = "openbsd" 27713da5c369Sopenharmony_ci))] 27723da5c369Sopenharmony_cimod setres { 27733da5c369Sopenharmony_ci feature! { 27743da5c369Sopenharmony_ci #![feature = "user"] 27753da5c369Sopenharmony_ci 27763da5c369Sopenharmony_ci use crate::Result; 27773da5c369Sopenharmony_ci use crate::errno::Errno; 27783da5c369Sopenharmony_ci use super::{Uid, Gid}; 27793da5c369Sopenharmony_ci 27803da5c369Sopenharmony_ci /// Sets the real, effective, and saved uid. 27813da5c369Sopenharmony_ci /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html)) 27823da5c369Sopenharmony_ci /// 27833da5c369Sopenharmony_ci /// * `ruid`: real user id 27843da5c369Sopenharmony_ci /// * `euid`: effective user id 27853da5c369Sopenharmony_ci /// * `suid`: saved user id 27863da5c369Sopenharmony_ci /// * returns: Ok or libc error code. 27873da5c369Sopenharmony_ci /// 27883da5c369Sopenharmony_ci /// Err is returned if the user doesn't have permission to set this UID. 27893da5c369Sopenharmony_ci #[inline] 27903da5c369Sopenharmony_ci pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> { 27913da5c369Sopenharmony_ci let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) }; 27923da5c369Sopenharmony_ci 27933da5c369Sopenharmony_ci Errno::result(res).map(drop) 27943da5c369Sopenharmony_ci } 27953da5c369Sopenharmony_ci 27963da5c369Sopenharmony_ci /// Sets the real, effective, and saved gid. 27973da5c369Sopenharmony_ci /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html)) 27983da5c369Sopenharmony_ci /// 27993da5c369Sopenharmony_ci /// * `rgid`: real group id 28003da5c369Sopenharmony_ci /// * `egid`: effective group id 28013da5c369Sopenharmony_ci /// * `sgid`: saved group id 28023da5c369Sopenharmony_ci /// * returns: Ok or libc error code. 28033da5c369Sopenharmony_ci /// 28043da5c369Sopenharmony_ci /// Err is returned if the user doesn't have permission to set this GID. 28053da5c369Sopenharmony_ci #[inline] 28063da5c369Sopenharmony_ci pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> { 28073da5c369Sopenharmony_ci let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) }; 28083da5c369Sopenharmony_ci 28093da5c369Sopenharmony_ci Errno::result(res).map(drop) 28103da5c369Sopenharmony_ci } 28113da5c369Sopenharmony_ci } 28123da5c369Sopenharmony_ci} 28133da5c369Sopenharmony_ci 28143da5c369Sopenharmony_ci#[cfg(any( 28153da5c369Sopenharmony_ci target_os = "android", 28163da5c369Sopenharmony_ci target_os = "dragonfly", 28173da5c369Sopenharmony_ci target_os = "freebsd", 28183da5c369Sopenharmony_ci target_os = "linux", 28193da5c369Sopenharmony_ci target_os = "openbsd" 28203da5c369Sopenharmony_ci))] 28213da5c369Sopenharmony_cimod getres { 28223da5c369Sopenharmony_ci feature! { 28233da5c369Sopenharmony_ci #![feature = "user"] 28243da5c369Sopenharmony_ci 28253da5c369Sopenharmony_ci use crate::Result; 28263da5c369Sopenharmony_ci use crate::errno::Errno; 28273da5c369Sopenharmony_ci use super::{Uid, Gid}; 28283da5c369Sopenharmony_ci 28293da5c369Sopenharmony_ci /// Real, effective and saved user IDs. 28303da5c369Sopenharmony_ci #[derive(Debug, Copy, Clone, Eq, PartialEq)] 28313da5c369Sopenharmony_ci pub struct ResUid { 28323da5c369Sopenharmony_ci pub real: Uid, 28333da5c369Sopenharmony_ci pub effective: Uid, 28343da5c369Sopenharmony_ci pub saved: Uid 28353da5c369Sopenharmony_ci } 28363da5c369Sopenharmony_ci 28373da5c369Sopenharmony_ci /// Real, effective and saved group IDs. 28383da5c369Sopenharmony_ci #[derive(Debug, Copy, Clone, Eq, PartialEq)] 28393da5c369Sopenharmony_ci pub struct ResGid { 28403da5c369Sopenharmony_ci pub real: Gid, 28413da5c369Sopenharmony_ci pub effective: Gid, 28423da5c369Sopenharmony_ci pub saved: Gid 28433da5c369Sopenharmony_ci } 28443da5c369Sopenharmony_ci 28453da5c369Sopenharmony_ci /// Gets the real, effective, and saved user IDs. 28463da5c369Sopenharmony_ci /// 28473da5c369Sopenharmony_ci /// ([see getresuid(2)](http://man7.org/linux/man-pages/man2/getresuid.2.html)) 28483da5c369Sopenharmony_ci /// 28493da5c369Sopenharmony_ci /// #Returns 28503da5c369Sopenharmony_ci /// 28513da5c369Sopenharmony_ci /// - `Ok((Uid, Uid, Uid))`: tuple of real, effective and saved uids on success. 28523da5c369Sopenharmony_ci /// - `Err(x)`: libc error code on failure. 28533da5c369Sopenharmony_ci /// 28543da5c369Sopenharmony_ci #[inline] 28553da5c369Sopenharmony_ci pub fn getresuid() -> Result<ResUid> { 28563da5c369Sopenharmony_ci let mut ruid = libc::uid_t::max_value(); 28573da5c369Sopenharmony_ci let mut euid = libc::uid_t::max_value(); 28583da5c369Sopenharmony_ci let mut suid = libc::uid_t::max_value(); 28593da5c369Sopenharmony_ci let res = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) }; 28603da5c369Sopenharmony_ci 28613da5c369Sopenharmony_ci Errno::result(res).map(|_| ResUid{ real: Uid(ruid), effective: Uid(euid), saved: Uid(suid) }) 28623da5c369Sopenharmony_ci } 28633da5c369Sopenharmony_ci 28643da5c369Sopenharmony_ci /// Gets the real, effective, and saved group IDs. 28653da5c369Sopenharmony_ci /// 28663da5c369Sopenharmony_ci /// ([see getresgid(2)](http://man7.org/linux/man-pages/man2/getresgid.2.html)) 28673da5c369Sopenharmony_ci /// 28683da5c369Sopenharmony_ci /// #Returns 28693da5c369Sopenharmony_ci /// 28703da5c369Sopenharmony_ci /// - `Ok((Gid, Gid, Gid))`: tuple of real, effective and saved gids on success. 28713da5c369Sopenharmony_ci /// - `Err(x)`: libc error code on failure. 28723da5c369Sopenharmony_ci /// 28733da5c369Sopenharmony_ci #[inline] 28743da5c369Sopenharmony_ci pub fn getresgid() -> Result<ResGid> { 28753da5c369Sopenharmony_ci let mut rgid = libc::gid_t::max_value(); 28763da5c369Sopenharmony_ci let mut egid = libc::gid_t::max_value(); 28773da5c369Sopenharmony_ci let mut sgid = libc::gid_t::max_value(); 28783da5c369Sopenharmony_ci let res = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) }; 28793da5c369Sopenharmony_ci 28803da5c369Sopenharmony_ci Errno::result(res).map(|_| ResGid { real: Gid(rgid), effective: Gid(egid), saved: Gid(sgid) } ) 28813da5c369Sopenharmony_ci } 28823da5c369Sopenharmony_ci } 28833da5c369Sopenharmony_ci} 28843da5c369Sopenharmony_ci 28853da5c369Sopenharmony_ci#[cfg(feature = "fs")] 28863da5c369Sopenharmony_cilibc_bitflags! { 28873da5c369Sopenharmony_ci /// Options for access() 28883da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] 28893da5c369Sopenharmony_ci pub struct AccessFlags : c_int { 28903da5c369Sopenharmony_ci /// Test for existence of file. 28913da5c369Sopenharmony_ci F_OK; 28923da5c369Sopenharmony_ci /// Test for read permission. 28933da5c369Sopenharmony_ci R_OK; 28943da5c369Sopenharmony_ci /// Test for write permission. 28953da5c369Sopenharmony_ci W_OK; 28963da5c369Sopenharmony_ci /// Test for execute (search) permission. 28973da5c369Sopenharmony_ci X_OK; 28983da5c369Sopenharmony_ci } 28993da5c369Sopenharmony_ci} 29003da5c369Sopenharmony_ci 29013da5c369Sopenharmony_cifeature! { 29023da5c369Sopenharmony_ci#![feature = "fs"] 29033da5c369Sopenharmony_ci 29043da5c369Sopenharmony_ci/// Checks the file named by `path` for accessibility according to the flags given by `amode` 29053da5c369Sopenharmony_ci/// See [access(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html) 29063da5c369Sopenharmony_cipub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> { 29073da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 29083da5c369Sopenharmony_ci unsafe { 29093da5c369Sopenharmony_ci libc::access(cstr.as_ptr(), amode.bits) 29103da5c369Sopenharmony_ci } 29113da5c369Sopenharmony_ci })?; 29123da5c369Sopenharmony_ci Errno::result(res).map(drop) 29133da5c369Sopenharmony_ci} 29143da5c369Sopenharmony_ci 29153da5c369Sopenharmony_ci/// Checks the file named by `path` for accessibility according to the flags given by `mode` 29163da5c369Sopenharmony_ci/// 29173da5c369Sopenharmony_ci/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor. 29183da5c369Sopenharmony_ci/// 29193da5c369Sopenharmony_ci/// If `dirfd` is `None`, then `path` is relative to the current working directory. 29203da5c369Sopenharmony_ci/// 29213da5c369Sopenharmony_ci/// # References 29223da5c369Sopenharmony_ci/// 29233da5c369Sopenharmony_ci/// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html) 29243da5c369Sopenharmony_ci// redox: does not appear to support the *at family of syscalls. 29253da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] 29263da5c369Sopenharmony_cipub fn faccessat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: AccessFlags, flags: AtFlags) -> Result<()> { 29273da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 29283da5c369Sopenharmony_ci unsafe { 29293da5c369Sopenharmony_ci libc::faccessat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits(), flags.bits()) 29303da5c369Sopenharmony_ci } 29313da5c369Sopenharmony_ci })?; 29323da5c369Sopenharmony_ci Errno::result(res).map(drop) 29333da5c369Sopenharmony_ci} 29343da5c369Sopenharmony_ci 29353da5c369Sopenharmony_ci/// Checks the file named by `path` for accessibility according to the flags given 29363da5c369Sopenharmony_ci/// by `mode` using effective UID, effective GID and supplementary group lists. 29373da5c369Sopenharmony_ci/// 29383da5c369Sopenharmony_ci/// # References 29393da5c369Sopenharmony_ci/// 29403da5c369Sopenharmony_ci/// * [FreeBSD man page](https://www.freebsd.org/cgi/man.cgi?query=eaccess&sektion=2&n=1) 29413da5c369Sopenharmony_ci/// * [Linux man page](https://man7.org/linux/man-pages/man3/euidaccess.3.html) 29423da5c369Sopenharmony_ci#[cfg(any( 29433da5c369Sopenharmony_ci all(target_os = "linux", not(target_env = "uclibc")), 29443da5c369Sopenharmony_ci target_os = "freebsd", 29453da5c369Sopenharmony_ci target_os = "dragonfly" 29463da5c369Sopenharmony_ci))] 29473da5c369Sopenharmony_cipub fn eaccess<P: ?Sized + NixPath>(path: &P, mode: AccessFlags) -> Result<()> { 29483da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| { 29493da5c369Sopenharmony_ci unsafe { 29503da5c369Sopenharmony_ci libc::eaccess(cstr.as_ptr(), mode.bits) 29513da5c369Sopenharmony_ci } 29523da5c369Sopenharmony_ci })?; 29533da5c369Sopenharmony_ci Errno::result(res).map(drop) 29543da5c369Sopenharmony_ci} 29553da5c369Sopenharmony_ci} 29563da5c369Sopenharmony_ci 29573da5c369Sopenharmony_cifeature! { 29583da5c369Sopenharmony_ci#![feature = "user"] 29593da5c369Sopenharmony_ci 29603da5c369Sopenharmony_ci/// Representation of a User, based on `libc::passwd` 29613da5c369Sopenharmony_ci/// 29623da5c369Sopenharmony_ci/// The reason some fields in this struct are `String` and others are `CString` is because some 29633da5c369Sopenharmony_ci/// fields are based on the user's locale, which could be non-UTF8, while other fields are 29643da5c369Sopenharmony_ci/// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only 29653da5c369Sopenharmony_ci/// contains ASCII. 29663da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 29673da5c369Sopenharmony_ci#[derive(Debug, Clone, Eq, PartialEq)] 29683da5c369Sopenharmony_cipub struct User { 29693da5c369Sopenharmony_ci /// Username 29703da5c369Sopenharmony_ci pub name: String, 29713da5c369Sopenharmony_ci /// User password (probably hashed) 29723da5c369Sopenharmony_ci pub passwd: CString, 29733da5c369Sopenharmony_ci /// User ID 29743da5c369Sopenharmony_ci pub uid: Uid, 29753da5c369Sopenharmony_ci /// Group ID 29763da5c369Sopenharmony_ci pub gid: Gid, 29773da5c369Sopenharmony_ci /// User information 29783da5c369Sopenharmony_ci #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] 29793da5c369Sopenharmony_ci pub gecos: CString, 29803da5c369Sopenharmony_ci /// Home directory 29813da5c369Sopenharmony_ci pub dir: PathBuf, 29823da5c369Sopenharmony_ci /// Path to shell 29833da5c369Sopenharmony_ci pub shell: PathBuf, 29843da5c369Sopenharmony_ci /// Login class 29853da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 29863da5c369Sopenharmony_ci target_os = "fuchsia", 29873da5c369Sopenharmony_ci target_os = "haiku", 29883da5c369Sopenharmony_ci target_os = "illumos", 29893da5c369Sopenharmony_ci target_os = "linux", 29903da5c369Sopenharmony_ci target_os = "solaris")))] 29913da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 29923da5c369Sopenharmony_ci pub class: CString, 29933da5c369Sopenharmony_ci /// Last password change 29943da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 29953da5c369Sopenharmony_ci target_os = "fuchsia", 29963da5c369Sopenharmony_ci target_os = "haiku", 29973da5c369Sopenharmony_ci target_os = "illumos", 29983da5c369Sopenharmony_ci target_os = "linux", 29993da5c369Sopenharmony_ci target_os = "solaris")))] 30003da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 30013da5c369Sopenharmony_ci pub change: libc::time_t, 30023da5c369Sopenharmony_ci /// Expiration time of account 30033da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30043da5c369Sopenharmony_ci target_os = "fuchsia", 30053da5c369Sopenharmony_ci target_os = "haiku", 30063da5c369Sopenharmony_ci target_os = "illumos", 30073da5c369Sopenharmony_ci target_os = "linux", 30083da5c369Sopenharmony_ci target_os = "solaris")))] 30093da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 30103da5c369Sopenharmony_ci pub expire: libc::time_t 30113da5c369Sopenharmony_ci} 30123da5c369Sopenharmony_ci 30133da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] //RedoxFS does not support passwd 30143da5c369Sopenharmony_ciimpl From<&libc::passwd> for User { 30153da5c369Sopenharmony_ci fn from(pw: &libc::passwd) -> User { 30163da5c369Sopenharmony_ci unsafe { 30173da5c369Sopenharmony_ci User { 30183da5c369Sopenharmony_ci name: if pw.pw_name.is_null() { Default::default() } else { CStr::from_ptr(pw.pw_name).to_string_lossy().into_owned() }, 30193da5c369Sopenharmony_ci passwd: if pw.pw_passwd.is_null() { Default::default() } else { CString::new(CStr::from_ptr(pw.pw_passwd).to_bytes()).unwrap() }, 30203da5c369Sopenharmony_ci #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] 30213da5c369Sopenharmony_ci gecos: if pw.pw_gecos.is_null() { Default::default() } else { CString::new(CStr::from_ptr(pw.pw_gecos).to_bytes()).unwrap() }, 30223da5c369Sopenharmony_ci dir: if pw.pw_dir.is_null() { Default::default() } else { PathBuf::from(OsStr::from_bytes(CStr::from_ptr(pw.pw_dir).to_bytes())) }, 30233da5c369Sopenharmony_ci shell: if pw.pw_shell.is_null() { Default::default() } else { PathBuf::from(OsStr::from_bytes(CStr::from_ptr(pw.pw_shell).to_bytes())) }, 30243da5c369Sopenharmony_ci uid: Uid::from_raw(pw.pw_uid), 30253da5c369Sopenharmony_ci gid: Gid::from_raw(pw.pw_gid), 30263da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30273da5c369Sopenharmony_ci target_os = "fuchsia", 30283da5c369Sopenharmony_ci target_os = "haiku", 30293da5c369Sopenharmony_ci target_os = "illumos", 30303da5c369Sopenharmony_ci target_os = "linux", 30313da5c369Sopenharmony_ci target_os = "solaris")))] 30323da5c369Sopenharmony_ci class: CString::new(CStr::from_ptr(pw.pw_class).to_bytes()).unwrap(), 30333da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30343da5c369Sopenharmony_ci target_os = "fuchsia", 30353da5c369Sopenharmony_ci target_os = "haiku", 30363da5c369Sopenharmony_ci target_os = "illumos", 30373da5c369Sopenharmony_ci target_os = "linux", 30383da5c369Sopenharmony_ci target_os = "solaris")))] 30393da5c369Sopenharmony_ci change: pw.pw_change, 30403da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30413da5c369Sopenharmony_ci target_os = "fuchsia", 30423da5c369Sopenharmony_ci target_os = "haiku", 30433da5c369Sopenharmony_ci target_os = "illumos", 30443da5c369Sopenharmony_ci target_os = "linux", 30453da5c369Sopenharmony_ci target_os = "solaris")))] 30463da5c369Sopenharmony_ci expire: pw.pw_expire 30473da5c369Sopenharmony_ci } 30483da5c369Sopenharmony_ci } 30493da5c369Sopenharmony_ci } 30503da5c369Sopenharmony_ci} 30513da5c369Sopenharmony_ci 30523da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 30533da5c369Sopenharmony_ciimpl From<User> for libc::passwd { 30543da5c369Sopenharmony_ci fn from(u: User) -> Self { 30553da5c369Sopenharmony_ci let name = match CString::new(u.name) { 30563da5c369Sopenharmony_ci Ok(n) => n.into_raw(), 30573da5c369Sopenharmony_ci Err(_) => CString::new("").unwrap().into_raw(), 30583da5c369Sopenharmony_ci }; 30593da5c369Sopenharmony_ci let dir = match u.dir.into_os_string().into_string() { 30603da5c369Sopenharmony_ci Ok(s) => CString::new(s.as_str()).unwrap().into_raw(), 30613da5c369Sopenharmony_ci Err(_) => CString::new("").unwrap().into_raw(), 30623da5c369Sopenharmony_ci }; 30633da5c369Sopenharmony_ci let shell = match u.shell.into_os_string().into_string() { 30643da5c369Sopenharmony_ci Ok(s) => CString::new(s.as_str()).unwrap().into_raw(), 30653da5c369Sopenharmony_ci Err(_) => CString::new("").unwrap().into_raw(), 30663da5c369Sopenharmony_ci }; 30673da5c369Sopenharmony_ci Self { 30683da5c369Sopenharmony_ci pw_name: name, 30693da5c369Sopenharmony_ci pw_passwd: u.passwd.into_raw(), 30703da5c369Sopenharmony_ci #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] 30713da5c369Sopenharmony_ci pw_gecos: u.gecos.into_raw(), 30723da5c369Sopenharmony_ci pw_dir: dir, 30733da5c369Sopenharmony_ci pw_shell: shell, 30743da5c369Sopenharmony_ci pw_uid: u.uid.0, 30753da5c369Sopenharmony_ci pw_gid: u.gid.0, 30763da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30773da5c369Sopenharmony_ci target_os = "fuchsia", 30783da5c369Sopenharmony_ci target_os = "haiku", 30793da5c369Sopenharmony_ci target_os = "illumos", 30803da5c369Sopenharmony_ci target_os = "linux", 30813da5c369Sopenharmony_ci target_os = "solaris")))] 30823da5c369Sopenharmony_ci pw_class: u.class.into_raw(), 30833da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30843da5c369Sopenharmony_ci target_os = "fuchsia", 30853da5c369Sopenharmony_ci target_os = "haiku", 30863da5c369Sopenharmony_ci target_os = "illumos", 30873da5c369Sopenharmony_ci target_os = "linux", 30883da5c369Sopenharmony_ci target_os = "solaris")))] 30893da5c369Sopenharmony_ci pw_change: u.change, 30903da5c369Sopenharmony_ci #[cfg(not(any(target_os = "android", 30913da5c369Sopenharmony_ci target_os = "fuchsia", 30923da5c369Sopenharmony_ci target_os = "haiku", 30933da5c369Sopenharmony_ci target_os = "illumos", 30943da5c369Sopenharmony_ci target_os = "linux", 30953da5c369Sopenharmony_ci target_os = "solaris")))] 30963da5c369Sopenharmony_ci pw_expire: u.expire, 30973da5c369Sopenharmony_ci #[cfg(target_os = "illumos")] 30983da5c369Sopenharmony_ci pw_age: CString::new("").unwrap().into_raw(), 30993da5c369Sopenharmony_ci #[cfg(target_os = "illumos")] 31003da5c369Sopenharmony_ci pw_comment: CString::new("").unwrap().into_raw(), 31013da5c369Sopenharmony_ci #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] 31023da5c369Sopenharmony_ci pw_fields: 0, 31033da5c369Sopenharmony_ci } 31043da5c369Sopenharmony_ci } 31053da5c369Sopenharmony_ci} 31063da5c369Sopenharmony_ci 31073da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 31083da5c369Sopenharmony_ciimpl User { 31093da5c369Sopenharmony_ci fn from_anything<F>(f: F) -> Result<Option<Self>> 31103da5c369Sopenharmony_ci where 31113da5c369Sopenharmony_ci F: Fn(*mut libc::passwd, 31123da5c369Sopenharmony_ci *mut c_char, 31133da5c369Sopenharmony_ci libc::size_t, 31143da5c369Sopenharmony_ci *mut *mut libc::passwd) -> libc::c_int 31153da5c369Sopenharmony_ci { 31163da5c369Sopenharmony_ci let buflimit = 1048576; 31173da5c369Sopenharmony_ci let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) { 31183da5c369Sopenharmony_ci Ok(Some(n)) => n as usize, 31193da5c369Sopenharmony_ci Ok(None) | Err(_) => 16384, 31203da5c369Sopenharmony_ci }; 31213da5c369Sopenharmony_ci 31223da5c369Sopenharmony_ci let mut cbuf = Vec::with_capacity(bufsize); 31233da5c369Sopenharmony_ci let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit(); 31243da5c369Sopenharmony_ci let mut res = ptr::null_mut(); 31253da5c369Sopenharmony_ci 31263da5c369Sopenharmony_ci loop { 31273da5c369Sopenharmony_ci let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res); 31283da5c369Sopenharmony_ci if error == 0 { 31293da5c369Sopenharmony_ci if res.is_null() { 31303da5c369Sopenharmony_ci return Ok(None); 31313da5c369Sopenharmony_ci } else { 31323da5c369Sopenharmony_ci let pwd = unsafe { pwd.assume_init() }; 31333da5c369Sopenharmony_ci return Ok(Some(User::from(&pwd))); 31343da5c369Sopenharmony_ci } 31353da5c369Sopenharmony_ci } else if Errno::last() == Errno::ERANGE { 31363da5c369Sopenharmony_ci // Trigger the internal buffer resizing logic. 31373da5c369Sopenharmony_ci reserve_double_buffer_size(&mut cbuf, buflimit)?; 31383da5c369Sopenharmony_ci } else { 31393da5c369Sopenharmony_ci return Err(Errno::last()); 31403da5c369Sopenharmony_ci } 31413da5c369Sopenharmony_ci } 31423da5c369Sopenharmony_ci } 31433da5c369Sopenharmony_ci 31443da5c369Sopenharmony_ci /// Get a user by UID. 31453da5c369Sopenharmony_ci /// 31463da5c369Sopenharmony_ci /// Internally, this function calls 31473da5c369Sopenharmony_ci /// [getpwuid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) 31483da5c369Sopenharmony_ci /// 31493da5c369Sopenharmony_ci /// # Examples 31503da5c369Sopenharmony_ci /// 31513da5c369Sopenharmony_ci /// ``` 31523da5c369Sopenharmony_ci /// use nix::unistd::{Uid, User}; 31533da5c369Sopenharmony_ci /// // Returns an Result<Option<User>>, thus the double unwrap. 31543da5c369Sopenharmony_ci /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap(); 31553da5c369Sopenharmony_ci /// assert_eq!(res.name, "root"); 31563da5c369Sopenharmony_ci /// ``` 31573da5c369Sopenharmony_ci pub fn from_uid(uid: Uid) -> Result<Option<Self>> { 31583da5c369Sopenharmony_ci User::from_anything(|pwd, cbuf, cap, res| { 31593da5c369Sopenharmony_ci unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) } 31603da5c369Sopenharmony_ci }) 31613da5c369Sopenharmony_ci } 31623da5c369Sopenharmony_ci 31633da5c369Sopenharmony_ci /// Get a user by name. 31643da5c369Sopenharmony_ci /// 31653da5c369Sopenharmony_ci /// Internally, this function calls 31663da5c369Sopenharmony_ci /// [getpwnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) 31673da5c369Sopenharmony_ci /// 31683da5c369Sopenharmony_ci /// # Examples 31693da5c369Sopenharmony_ci /// 31703da5c369Sopenharmony_ci /// ``` 31713da5c369Sopenharmony_ci /// use nix::unistd::User; 31723da5c369Sopenharmony_ci /// // Returns an Result<Option<User>>, thus the double unwrap. 31733da5c369Sopenharmony_ci /// let res = User::from_name("root").unwrap().unwrap(); 31743da5c369Sopenharmony_ci /// assert_eq!(res.name, "root"); 31753da5c369Sopenharmony_ci /// ``` 31763da5c369Sopenharmony_ci pub fn from_name(name: &str) -> Result<Option<Self>> { 31773da5c369Sopenharmony_ci let name = match CString::new(name) { 31783da5c369Sopenharmony_ci Ok(c_str) => c_str, 31793da5c369Sopenharmony_ci Err(_nul_error) => return Ok(None), 31803da5c369Sopenharmony_ci }; 31813da5c369Sopenharmony_ci User::from_anything(|pwd, cbuf, cap, res| { 31823da5c369Sopenharmony_ci unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) } 31833da5c369Sopenharmony_ci }) 31843da5c369Sopenharmony_ci } 31853da5c369Sopenharmony_ci} 31863da5c369Sopenharmony_ci 31873da5c369Sopenharmony_ci/// Representation of a Group, based on `libc::group` 31883da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 31893da5c369Sopenharmony_ci#[derive(Debug, Clone, Eq, PartialEq)] 31903da5c369Sopenharmony_cipub struct Group { 31913da5c369Sopenharmony_ci /// Group name 31923da5c369Sopenharmony_ci pub name: String, 31933da5c369Sopenharmony_ci /// Group password 31943da5c369Sopenharmony_ci pub passwd: CString, 31953da5c369Sopenharmony_ci /// Group ID 31963da5c369Sopenharmony_ci pub gid: Gid, 31973da5c369Sopenharmony_ci /// List of Group members 31983da5c369Sopenharmony_ci pub mem: Vec<String> 31993da5c369Sopenharmony_ci} 32003da5c369Sopenharmony_ci 32013da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 32023da5c369Sopenharmony_ciimpl From<&libc::group> for Group { 32033da5c369Sopenharmony_ci fn from(gr: &libc::group) -> Group { 32043da5c369Sopenharmony_ci unsafe { 32053da5c369Sopenharmony_ci Group { 32063da5c369Sopenharmony_ci name: CStr::from_ptr(gr.gr_name).to_string_lossy().into_owned(), 32073da5c369Sopenharmony_ci passwd: CString::new(CStr::from_ptr(gr.gr_passwd).to_bytes()).unwrap(), 32083da5c369Sopenharmony_ci gid: Gid::from_raw(gr.gr_gid), 32093da5c369Sopenharmony_ci mem: Group::members(gr.gr_mem) 32103da5c369Sopenharmony_ci } 32113da5c369Sopenharmony_ci } 32123da5c369Sopenharmony_ci } 32133da5c369Sopenharmony_ci} 32143da5c369Sopenharmony_ci 32153da5c369Sopenharmony_ci#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd 32163da5c369Sopenharmony_ciimpl Group { 32173da5c369Sopenharmony_ci unsafe fn members(mem: *mut *mut c_char) -> Vec<String> { 32183da5c369Sopenharmony_ci let mut ret = Vec::new(); 32193da5c369Sopenharmony_ci 32203da5c369Sopenharmony_ci for i in 0.. { 32213da5c369Sopenharmony_ci let u = mem.offset(i); 32223da5c369Sopenharmony_ci if (*u).is_null() { 32233da5c369Sopenharmony_ci break; 32243da5c369Sopenharmony_ci } else { 32253da5c369Sopenharmony_ci let s = CStr::from_ptr(*u).to_string_lossy().into_owned(); 32263da5c369Sopenharmony_ci ret.push(s); 32273da5c369Sopenharmony_ci } 32283da5c369Sopenharmony_ci } 32293da5c369Sopenharmony_ci 32303da5c369Sopenharmony_ci ret 32313da5c369Sopenharmony_ci } 32323da5c369Sopenharmony_ci 32333da5c369Sopenharmony_ci fn from_anything<F>(f: F) -> Result<Option<Self>> 32343da5c369Sopenharmony_ci where 32353da5c369Sopenharmony_ci F: Fn(*mut libc::group, 32363da5c369Sopenharmony_ci *mut c_char, 32373da5c369Sopenharmony_ci libc::size_t, 32383da5c369Sopenharmony_ci *mut *mut libc::group) -> libc::c_int 32393da5c369Sopenharmony_ci { 32403da5c369Sopenharmony_ci let buflimit = 1048576; 32413da5c369Sopenharmony_ci let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) { 32423da5c369Sopenharmony_ci Ok(Some(n)) => n as usize, 32433da5c369Sopenharmony_ci Ok(None) | Err(_) => 16384, 32443da5c369Sopenharmony_ci }; 32453da5c369Sopenharmony_ci 32463da5c369Sopenharmony_ci let mut cbuf = Vec::with_capacity(bufsize); 32473da5c369Sopenharmony_ci let mut grp = mem::MaybeUninit::<libc::group>::uninit(); 32483da5c369Sopenharmony_ci let mut res = ptr::null_mut(); 32493da5c369Sopenharmony_ci 32503da5c369Sopenharmony_ci loop { 32513da5c369Sopenharmony_ci let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res); 32523da5c369Sopenharmony_ci if error == 0 { 32533da5c369Sopenharmony_ci if res.is_null() { 32543da5c369Sopenharmony_ci return Ok(None); 32553da5c369Sopenharmony_ci } else { 32563da5c369Sopenharmony_ci let grp = unsafe { grp.assume_init() }; 32573da5c369Sopenharmony_ci return Ok(Some(Group::from(&grp))); 32583da5c369Sopenharmony_ci } 32593da5c369Sopenharmony_ci } else if Errno::last() == Errno::ERANGE { 32603da5c369Sopenharmony_ci // Trigger the internal buffer resizing logic. 32613da5c369Sopenharmony_ci reserve_double_buffer_size(&mut cbuf, buflimit)?; 32623da5c369Sopenharmony_ci } else { 32633da5c369Sopenharmony_ci return Err(Errno::last()); 32643da5c369Sopenharmony_ci } 32653da5c369Sopenharmony_ci } 32663da5c369Sopenharmony_ci } 32673da5c369Sopenharmony_ci 32683da5c369Sopenharmony_ci /// Get a group by GID. 32693da5c369Sopenharmony_ci /// 32703da5c369Sopenharmony_ci /// Internally, this function calls 32713da5c369Sopenharmony_ci /// [getgrgid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) 32723da5c369Sopenharmony_ci /// 32733da5c369Sopenharmony_ci /// # Examples 32743da5c369Sopenharmony_ci /// 32753da5c369Sopenharmony_ci // Disable this test on all OS except Linux as root group may not exist. 32763da5c369Sopenharmony_ci #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")] 32773da5c369Sopenharmony_ci #[cfg_attr(target_os = "linux", doc = " ```")] 32783da5c369Sopenharmony_ci /// use nix::unistd::{Gid, Group}; 32793da5c369Sopenharmony_ci /// // Returns an Result<Option<Group>>, thus the double unwrap. 32803da5c369Sopenharmony_ci /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap(); 32813da5c369Sopenharmony_ci /// assert!(res.name == "root"); 32823da5c369Sopenharmony_ci /// ``` 32833da5c369Sopenharmony_ci pub fn from_gid(gid: Gid) -> Result<Option<Self>> { 32843da5c369Sopenharmony_ci Group::from_anything(|grp, cbuf, cap, res| { 32853da5c369Sopenharmony_ci unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) } 32863da5c369Sopenharmony_ci }) 32873da5c369Sopenharmony_ci } 32883da5c369Sopenharmony_ci 32893da5c369Sopenharmony_ci /// Get a group by name. 32903da5c369Sopenharmony_ci /// 32913da5c369Sopenharmony_ci /// Internally, this function calls 32923da5c369Sopenharmony_ci /// [getgrnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) 32933da5c369Sopenharmony_ci /// 32943da5c369Sopenharmony_ci /// # Examples 32953da5c369Sopenharmony_ci /// 32963da5c369Sopenharmony_ci // Disable this test on all OS except Linux as root group may not exist. 32973da5c369Sopenharmony_ci #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")] 32983da5c369Sopenharmony_ci #[cfg_attr(target_os = "linux", doc = " ```")] 32993da5c369Sopenharmony_ci /// use nix::unistd::Group; 33003da5c369Sopenharmony_ci /// // Returns an Result<Option<Group>>, thus the double unwrap. 33013da5c369Sopenharmony_ci /// let res = Group::from_name("root").unwrap().unwrap(); 33023da5c369Sopenharmony_ci /// assert!(res.name == "root"); 33033da5c369Sopenharmony_ci /// ``` 33043da5c369Sopenharmony_ci pub fn from_name(name: &str) -> Result<Option<Self>> { 33053da5c369Sopenharmony_ci let name = match CString::new(name) { 33063da5c369Sopenharmony_ci Ok(c_str) => c_str, 33073da5c369Sopenharmony_ci Err(_nul_error) => return Ok(None), 33083da5c369Sopenharmony_ci }; 33093da5c369Sopenharmony_ci Group::from_anything(|grp, cbuf, cap, res| { 33103da5c369Sopenharmony_ci unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) } 33113da5c369Sopenharmony_ci }) 33123da5c369Sopenharmony_ci } 33133da5c369Sopenharmony_ci} 33143da5c369Sopenharmony_ci} 33153da5c369Sopenharmony_ci 33163da5c369Sopenharmony_cifeature! { 33173da5c369Sopenharmony_ci#![feature = "term"] 33183da5c369Sopenharmony_ci 33193da5c369Sopenharmony_ci/// Get the name of the terminal device that is open on file descriptor fd 33203da5c369Sopenharmony_ci/// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)). 33213da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))] 33223da5c369Sopenharmony_cipub fn ttyname(fd: RawFd) -> Result<PathBuf> { 33233da5c369Sopenharmony_ci const PATH_MAX: usize = libc::PATH_MAX as usize; 33243da5c369Sopenharmony_ci let mut buf = vec![0_u8; PATH_MAX]; 33253da5c369Sopenharmony_ci let c_buf = buf.as_mut_ptr() as *mut libc::c_char; 33263da5c369Sopenharmony_ci 33273da5c369Sopenharmony_ci let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) }; 33283da5c369Sopenharmony_ci if ret != 0 { 33293da5c369Sopenharmony_ci return Err(Errno::from_i32(ret)); 33303da5c369Sopenharmony_ci } 33313da5c369Sopenharmony_ci 33323da5c369Sopenharmony_ci let nul = buf.iter().position(|c| *c == b'\0').unwrap(); 33333da5c369Sopenharmony_ci buf.truncate(nul); 33343da5c369Sopenharmony_ci Ok(OsString::from_vec(buf).into()) 33353da5c369Sopenharmony_ci} 33363da5c369Sopenharmony_ci} 33373da5c369Sopenharmony_ci 33383da5c369Sopenharmony_cifeature! { 33393da5c369Sopenharmony_ci#![all(feature = "socket", feature = "user")] 33403da5c369Sopenharmony_ci 33413da5c369Sopenharmony_ci/// Get the effective user ID and group ID associated with a Unix domain socket. 33423da5c369Sopenharmony_ci/// 33433da5c369Sopenharmony_ci/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid) 33443da5c369Sopenharmony_ci#[cfg(any( 33453da5c369Sopenharmony_ci target_os = "macos", 33463da5c369Sopenharmony_ci target_os = "ios", 33473da5c369Sopenharmony_ci target_os = "freebsd", 33483da5c369Sopenharmony_ci target_os = "openbsd", 33493da5c369Sopenharmony_ci target_os = "netbsd", 33503da5c369Sopenharmony_ci target_os = "dragonfly", 33513da5c369Sopenharmony_ci))] 33523da5c369Sopenharmony_cipub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> { 33533da5c369Sopenharmony_ci let mut uid = 1; 33543da5c369Sopenharmony_ci let mut gid = 1; 33553da5c369Sopenharmony_ci 33563da5c369Sopenharmony_ci let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) }; 33573da5c369Sopenharmony_ci 33583da5c369Sopenharmony_ci Errno::result(ret).map(|_| (Uid(uid), Gid(gid))) 33593da5c369Sopenharmony_ci} 33603da5c369Sopenharmony_ci} 33613da5c369Sopenharmony_ci 33623da5c369Sopenharmony_cifeature! { 33633da5c369Sopenharmony_ci#![all(feature = "fs")] 33643da5c369Sopenharmony_ci 33653da5c369Sopenharmony_ci/// Set the file flags. 33663da5c369Sopenharmony_ci/// 33673da5c369Sopenharmony_ci/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2) 33683da5c369Sopenharmony_ci#[cfg(any( 33693da5c369Sopenharmony_ci target_os = "openbsd", 33703da5c369Sopenharmony_ci target_os = "netbsd", 33713da5c369Sopenharmony_ci target_os = "freebsd", 33723da5c369Sopenharmony_ci target_os = "dragonfly", 33733da5c369Sopenharmony_ci target_os = "macos", 33743da5c369Sopenharmony_ci target_os = "ios" 33753da5c369Sopenharmony_ci))] 33763da5c369Sopenharmony_cipub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> { 33773da5c369Sopenharmony_ci let res = path.with_nix_path(|cstr| unsafe { 33783da5c369Sopenharmony_ci libc::chflags(cstr.as_ptr(), flags.bits()) 33793da5c369Sopenharmony_ci })?; 33803da5c369Sopenharmony_ci 33813da5c369Sopenharmony_ci Errno::result(res).map(drop) 33823da5c369Sopenharmony_ci} 33833da5c369Sopenharmony_ci} 3384