• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //! Safe wrappers around functions found in libc "unistd.h" header
2  
3  #[cfg(not(target_os = "redox"))]
4  use cfg_if::cfg_if;
5  use crate::errno::{self, Errno};
6  use crate::{Error, Result, NixPath};
7  #[cfg(not(target_os = "redox"))]
8  use crate::fcntl::{AtFlags, at_rawfd};
9  use crate::fcntl::{FdFlag, OFlag, fcntl};
10  use crate::fcntl::FcntlArg::F_SETFD;
11  use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
12             uid_t, gid_t, mode_t, PATH_MAX};
13  use std::{fmt, mem, ptr};
14  use std::convert::Infallible;
15  use std::ffi::{CStr, OsString};
16  #[cfg(not(target_os = "redox"))]
17  use std::ffi::{CString, OsStr};
18  use std::os::unix::ffi::OsStringExt;
19  #[cfg(not(target_os = "redox"))]
20  use std::os::unix::ffi::OsStrExt;
21  use std::os::unix::io::RawFd;
22  use std::path::PathBuf;
23  use crate::sys::stat::Mode;
24  
25  #[cfg(any(target_os = "android", target_os = "linux"))]
26  pub use self::pivot_root::*;
27  
28  #[cfg(any(target_os = "android", target_os = "freebsd",
29            target_os = "linux", target_os = "openbsd"))]
30  pub use self::setres::*;
31  
32  /// User identifier
33  ///
34  /// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
35  /// passing wrong value.
36  #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
37  pub struct Uid(uid_t);
38  
39  impl Uid {
40      /// Creates `Uid` from raw `uid_t`.
from_raw(uid: uid_t) -> Self41      pub fn from_raw(uid: uid_t) -> Self {
42          Uid(uid)
43      }
44  
45      /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
current() -> Self46      pub fn current() -> Self {
47          getuid()
48      }
49  
50      /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
effective() -> Self51      pub fn effective() -> Self {
52          geteuid()
53      }
54  
55      /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
is_root(self) -> bool56      pub fn is_root(self) -> bool {
57          self == ROOT
58      }
59  
60      /// Get the raw `uid_t` wrapped by `self`.
as_raw(self) -> uid_t61      pub fn as_raw(self) -> uid_t {
62          self.0
63      }
64  }
65  
66  impl From<Uid> for uid_t {
from(uid: Uid) -> Self67      fn from(uid: Uid) -> Self {
68          uid.0
69      }
70  }
71  
72  impl fmt::Display for Uid {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result73      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74          fmt::Display::fmt(&self.0, f)
75      }
76  }
77  
78  /// Constant for UID = 0
79  pub const ROOT: Uid = Uid(0);
80  
81  /// Group identifier
82  ///
83  /// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally
84  /// passing wrong value.
85  #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
86  pub struct Gid(gid_t);
87  
88  impl Gid {
89      /// Creates `Gid` from raw `gid_t`.
from_raw(gid: gid_t) -> Self90      pub fn from_raw(gid: gid_t) -> Self {
91          Gid(gid)
92      }
93  
94      /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
current() -> Self95      pub fn current() -> Self {
96          getgid()
97      }
98  
99      /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
effective() -> Self100      pub fn effective() -> Self {
101          getegid()
102      }
103  
104      /// Get the raw `gid_t` wrapped by `self`.
as_raw(self) -> gid_t105      pub fn as_raw(self) -> gid_t {
106          self.0
107      }
108  }
109  
110  impl From<Gid> for gid_t {
from(gid: Gid) -> Self111      fn from(gid: Gid) -> Self {
112          gid.0
113      }
114  }
115  
116  impl fmt::Display for Gid {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result117      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118          fmt::Display::fmt(&self.0, f)
119      }
120  }
121  
122  /// Process identifier
123  ///
124  /// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
125  /// passing wrong value.
126  #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
127  pub struct Pid(pid_t);
128  
129  impl Pid {
130      /// Creates `Pid` from raw `pid_t`.
from_raw(pid: pid_t) -> Self131      pub fn from_raw(pid: pid_t) -> Self {
132          Pid(pid)
133      }
134  
135      /// Returns PID of calling process
this() -> Self136      pub fn this() -> Self {
137          getpid()
138      }
139  
140      /// Returns PID of parent of calling process
parent() -> Self141      pub fn parent() -> Self {
142          getppid()
143      }
144  
145      /// Get the raw `pid_t` wrapped by `self`.
as_raw(self) -> pid_t146      pub fn as_raw(self) -> pid_t {
147          self.0
148      }
149  }
150  
151  impl From<Pid> for pid_t {
from(pid: Pid) -> Self152      fn from(pid: Pid) -> Self {
153          pid.0
154      }
155  }
156  
157  impl fmt::Display for Pid {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result158      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159          fmt::Display::fmt(&self.0, f)
160      }
161  }
162  
163  
164  /// Represents the successful result of calling `fork`
165  ///
166  /// When `fork` is called, the process continues execution in the parent process
167  /// and in the new child.  This return type can be examined to determine whether
168  /// you are now executing in the parent process or in the child.
169  #[derive(Clone, Copy, Debug)]
170  pub enum ForkResult {
171      Parent { child: Pid },
172      Child,
173  }
174  
175  impl ForkResult {
176  
177      /// Return `true` if this is the child process of the `fork()`
178      #[inline]
is_child(self) -> bool179      pub fn is_child(self) -> bool {
180          match self {
181              ForkResult::Child => true,
182              _ => false
183          }
184      }
185  
186      /// Returns `true` if this is the parent process of the `fork()`
187      #[inline]
is_parent(self) -> bool188      pub fn is_parent(self) -> bool {
189          !self.is_child()
190      }
191  }
192  
193  /// Create a new child process duplicating the parent process ([see
194  /// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
195  ///
196  /// After calling the fork system call (successfully) two processes will
197  /// be created that are identical with the exception of their pid and the
198  /// return value of this function.  As an example:
199  ///
200  /// ```no_run
201  /// use nix::unistd::{fork, ForkResult};
202  ///
203  /// match unsafe{fork()} {
204  ///    Ok(ForkResult::Parent { child, .. }) => {
205  ///        println!("Continuing execution in parent process, new child has pid: {}", child);
206  ///    }
207  ///    Ok(ForkResult::Child) => println!("I'm a new child process"),
208  ///    Err(_) => println!("Fork failed"),
209  /// }
210  /// ```
211  ///
212  /// This will print something like the following (order indeterministic).  The
213  /// thing to note is that you end up with two processes continuing execution
214  /// immediately after the fork call but with different match arms.
215  ///
216  /// ```text
217  /// Continuing execution in parent process, new child has pid: 1234
218  /// I'm a new child process
219  /// ```
220  ///
221  /// # Safety
222  ///
223  /// In a multithreaded program, only [async-signal-safe] functions like `pause`
224  /// and `_exit` may be called by the child (the parent isn't restricted). Note
225  /// that memory allocation may **not** be async-signal-safe and thus must be
226  /// prevented.
227  ///
228  /// Those functions are only a small subset of your operating system's API, so
229  /// special care must be taken to only invoke code you can control and audit.
230  ///
231  /// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
232  #[inline]
fork() -> Result<ForkResult>233  pub unsafe fn fork() -> Result<ForkResult> {
234      use self::ForkResult::*;
235      let res = libc::fork();
236  
237      Errno::result(res).map(|res| match res {
238          0 => Child,
239          res => Parent { child: Pid(res) },
240      })
241  }
242  
243  /// Get the pid of this process (see
244  /// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
245  ///
246  /// Since you are running code, there is always a pid to return, so there
247  /// is no error case that needs to be handled.
248  #[inline]
getpid() -> Pid249  pub fn getpid() -> Pid {
250      Pid(unsafe { libc::getpid() })
251  }
252  
253  /// Get the pid of this processes' parent (see
254  /// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
255  ///
256  /// There is always a parent pid to return, so there is no error case that needs
257  /// to be handled.
258  #[inline]
getppid() -> Pid259  pub fn getppid() -> Pid {
260      Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful."
261  }
262  
263  /// Set a process group ID (see
264  /// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
265  ///
266  /// Set the process group id (PGID) of a particular process.  If a pid of zero
267  /// is specified, then the pid of the calling process is used.  Process groups
268  /// may be used to group together a set of processes in order for the OS to
269  /// apply some operations across the group.
270  ///
271  /// `setsid()` may be used to create a new process group.
272  #[inline]
setpgid(pid: Pid, pgid: Pid) -> Result<()>273  pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
274      let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
275      Errno::result(res).map(drop)
276  }
277  #[inline]
getpgid(pid: Option<Pid>) -> Result<Pid>278  pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
279      let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
280      Errno::result(res).map(Pid)
281  }
282  
283  /// Create new session and set process group id (see
284  /// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
285  #[inline]
setsid() -> Result<Pid>286  pub fn setsid() -> Result<Pid> {
287      Errno::result(unsafe { libc::setsid() }).map(Pid)
288  }
289  
290  /// Get the process group ID of a session leader
291  /// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
292  ///
293  /// Obtain the process group ID of the process that is the session leader of the process specified
294  /// by pid. If pid is zero, it specifies the calling process.
295  #[inline]
296  #[cfg(not(target_os = "redox"))]
getsid(pid: Option<Pid>) -> Result<Pid>297  pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
298      let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
299      Errno::result(res).map(Pid)
300  }
301  
302  
303  /// Get the terminal foreground process group (see
304  /// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
305  ///
306  /// Get the group process id (GPID) of the foreground process group on the
307  /// terminal associated to file descriptor (FD).
308  #[inline]
tcgetpgrp(fd: c_int) -> Result<Pid>309  pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
310      let res = unsafe { libc::tcgetpgrp(fd) };
311      Errno::result(res).map(Pid)
312  }
313  /// Set the terminal foreground process group (see
314  /// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
315  ///
316  /// Get the group process id (PGID) to the foreground process group on the
317  /// terminal associated to file descriptor (FD).
318  #[inline]
tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()>319  pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
320      let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) };
321      Errno::result(res).map(drop)
322  }
323  
324  
325  /// Get the group id of the calling process (see
326  ///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
327  ///
328  /// Get the process group id (PGID) of the calling process.
329  /// According to the man page it is always successful.
330  #[inline]
getpgrp() -> Pid331  pub fn getpgrp() -> Pid {
332      Pid(unsafe { libc::getpgrp() })
333  }
334  
335  /// Get the caller's thread ID (see
336  /// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
337  ///
338  /// This function is only available on Linux based systems.  In a single
339  /// threaded process, the main thread will have the same ID as the process.  In
340  /// a multithreaded process, each thread will have a unique thread id but the
341  /// same process ID.
342  ///
343  /// No error handling is required as a thread id should always exist for any
344  /// process, even if threads are not being used.
345  #[cfg(any(target_os = "linux", target_os = "android"))]
346  #[inline]
gettid() -> Pid347  pub fn gettid() -> Pid {
348      Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
349  }
350  
351  /// Create a copy of the specified file descriptor (see
352  /// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
353  ///
354  /// The new file descriptor will be have a new index but refer to the same
355  /// resource as the old file descriptor and the old and new file descriptors may
356  /// be used interchangeably.  The new and old file descriptor share the same
357  /// underlying resource, offset, and file status flags.  The actual index used
358  /// for the file descriptor will be the lowest fd index that is available.
359  ///
360  /// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`).
361  #[inline]
dup(oldfd: RawFd) -> Result<RawFd>362  pub fn dup(oldfd: RawFd) -> Result<RawFd> {
363      let res = unsafe { libc::dup(oldfd) };
364  
365      Errno::result(res)
366  }
367  
368  /// Create a copy of the specified file descriptor using the specified fd (see
369  /// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
370  ///
371  /// This function behaves similar to `dup()` except that it will try to use the
372  /// specified fd instead of allocating a new one.  See the man pages for more
373  /// detail on the exact behavior of this function.
374  #[inline]
dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd>375  pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
376      let res = unsafe { libc::dup2(oldfd, newfd) };
377  
378      Errno::result(res)
379  }
380  
381  /// Create a new copy of the specified file descriptor using the specified fd
382  /// and flags (see [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
383  ///
384  /// This function behaves similar to `dup2()` but allows for flags to be
385  /// specified.
dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd>386  pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
387      dup3_polyfill(oldfd, newfd, flags)
388  }
389  
390  #[inline]
dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd>391  fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
392      if oldfd == newfd {
393          return Err(Error::Sys(Errno::EINVAL));
394      }
395  
396      let fd = dup2(oldfd, newfd)?;
397  
398      if flags.contains(OFlag::O_CLOEXEC) {
399          if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
400              let _ = close(fd);
401              return Err(e);
402          }
403      }
404  
405      Ok(fd)
406  }
407  
408  /// Change the current working directory of the calling process (see
409  /// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
410  ///
411  /// This function may fail in a number of different scenarios.  See the man
412  /// pages for additional details on possible failure cases.
413  #[inline]
chdir<P: ?Sized + NixPath>(path: &P) -> Result<()>414  pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
415      let res = path.with_nix_path(|cstr| {
416          unsafe { libc::chdir(cstr.as_ptr()) }
417      })?;
418  
419      Errno::result(res).map(drop)
420  }
421  
422  /// Change the current working directory of the process to the one
423  /// given as an open file descriptor (see
424  /// [fchdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
425  ///
426  /// This function may fail in a number of different scenarios.  See the man
427  /// pages for additional details on possible failure cases.
428  #[inline]
429  #[cfg(not(target_os = "fuchsia"))]
fchdir(dirfd: RawFd) -> Result<()>430  pub fn fchdir(dirfd: RawFd) -> Result<()> {
431      let res = unsafe { libc::fchdir(dirfd) };
432  
433      Errno::result(res).map(drop)
434  }
435  
436  /// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
437  ///
438  /// # Errors
439  ///
440  /// There are several situations where mkdir might fail:
441  ///
442  /// - current user has insufficient rights in the parent directory
443  /// - the path already exists
444  /// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
445  ///
446  /// # Example
447  ///
448  /// ```rust
449  /// use nix::unistd;
450  /// use nix::sys::stat;
451  /// use tempfile::tempdir;
452  ///
453  /// fn main() {
454  ///     let tmp_dir1 = tempdir().unwrap();
455  ///     let tmp_dir2 = tmp_dir1.path().join("new_dir");
456  ///
457  ///     // create new directory and give read, write and execute rights to the owner
458  ///     match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
459  ///        Ok(_) => println!("created {:?}", tmp_dir2),
460  ///        Err(err) => println!("Error creating directory: {}", err),
461  ///     }
462  /// }
463  /// ```
464  #[inline]
mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()>465  pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
466      let res = path.with_nix_path(|cstr| {
467          unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) }
468      })?;
469  
470      Errno::result(res).map(drop)
471  }
472  
473  /// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
474  ///
475  /// # Errors
476  ///
477  /// There are several situations where mkfifo might fail:
478  ///
479  /// - current user has insufficient rights in the parent directory
480  /// - the path already exists
481  /// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
482  ///
483  /// For a full list consult
484  /// [posix specification](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
485  ///
486  /// # Example
487  ///
488  /// ```rust
489  /// use nix::unistd;
490  /// use nix::sys::stat;
491  /// use tempfile::tempdir;
492  ///
493  /// fn main() {
494  ///     let tmp_dir = tempdir().unwrap();
495  ///     let fifo_path = tmp_dir.path().join("foo.pipe");
496  ///
497  ///     // create new fifo and give read, write and execute rights to the owner
498  ///     match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
499  ///        Ok(_) => println!("created {:?}", fifo_path),
500  ///        Err(err) => println!("Error creating fifo: {}", err),
501  ///     }
502  /// }
503  /// ```
504  #[inline]
505  #[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet
mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()>506  pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
507      let res = path.with_nix_path(|cstr| {
508          unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
509      })?;
510  
511      Errno::result(res).map(drop)
512  }
513  
514  /// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
515  ///
516  /// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
517  ///
518  /// If `dirfd` is `None`, then `path` is relative to the current working directory.
519  ///
520  /// # References
521  ///
522  /// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
523  // mkfifoat is not implemented in OSX or android
524  #[inline]
525  #[cfg(not(any(
526      target_os = "macos", target_os = "ios",
527      target_os = "android", target_os = "redox")))]
mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()>528  pub fn mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()> {
529      let res = path.with_nix_path(|cstr| unsafe {
530          libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t)
531      })?;
532  
533      Errno::result(res).map(drop)
534  }
535  
536  /// Creates a symbolic link at `path2` which points to `path1`.
537  ///
538  /// If `dirfd` has a value, then `path2` is relative to directory associated
539  /// with the file descriptor.
540  ///
541  /// If `dirfd` is `None`, then `path2` is relative to the current working
542  /// directory. This is identical to `libc::symlink(path1, path2)`.
543  ///
544  /// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
545  #[cfg(not(target_os = "redox"))]
symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>( path1: &P1, dirfd: Option<RawFd>, path2: &P2) -> Result<()>546  pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
547      path1: &P1,
548      dirfd: Option<RawFd>,
549      path2: &P2) -> Result<()> {
550      let res =
551          path1.with_nix_path(|path1| {
552              path2.with_nix_path(|path2| {
553                  unsafe {
554                      libc::symlinkat(
555                          path1.as_ptr(),
556                          dirfd.unwrap_or(libc::AT_FDCWD),
557                          path2.as_ptr()
558                      )
559                  }
560              })
561          })??;
562      Errno::result(res).map(drop)
563  }
564  
565  // Double the buffer capacity up to limit. In case it already has
566  // reached the limit, return Errno::ERANGE.
reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()>567  fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
568      use std::cmp::min;
569  
570      if buf.capacity() >= limit {
571          return Err(Error::Sys(Errno::ERANGE))
572      }
573  
574      let capacity = min(buf.capacity() * 2, limit);
575      buf.reserve(capacity);
576  
577      Ok(())
578  }
579  
580  /// Returns the current directory as a `PathBuf`
581  ///
582  /// Err is returned if the current user doesn't have the permission to read or search a component
583  /// of the current path.
584  ///
585  /// # Example
586  ///
587  /// ```rust
588  /// use nix::unistd;
589  ///
590  /// fn main() {
591  ///     // assume that we are allowed to get current directory
592  ///     let dir = unistd::getcwd().unwrap();
593  ///     println!("The current directory is {:?}", dir);
594  /// }
595  /// ```
596  #[inline]
getcwd() -> Result<PathBuf>597  pub fn getcwd() -> Result<PathBuf> {
598      let mut buf = Vec::with_capacity(512);
599      loop {
600          unsafe {
601              let ptr = buf.as_mut_ptr() as *mut c_char;
602  
603              // The buffer must be large enough to store the absolute pathname plus
604              // a terminating null byte, or else null is returned.
605              // To safely handle this we start with a reasonable size (512 bytes)
606              // and double the buffer size upon every error
607              if !libc::getcwd(ptr, buf.capacity()).is_null() {
608                  let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
609                  buf.set_len(len);
610                  buf.shrink_to_fit();
611                  return Ok(PathBuf::from(OsString::from_vec(buf)));
612              } else {
613                  let error = Errno::last();
614                  // ERANGE means buffer was too small to store directory name
615                  if error != Errno::ERANGE {
616                      return Err(Error::Sys(error));
617                  }
618              }
619  
620              // Trigger the internal buffer resizing logic.
621              reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
622          }
623      }
624  }
625  
626  /// Computes the raw UID and GID values to pass to a `*chown` call.
chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::gid_t)627  fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::gid_t) {
628      // According to the POSIX specification, -1 is used to indicate that owner and group
629      // are not to be changed.  Since uid_t and gid_t are unsigned types, we have to wrap
630      // around to get -1.
631      let uid = owner.map(Into::into)
632          .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1));
633      let gid = group.map(Into::into)
634          .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1));
635      (uid, gid)
636  }
637  
638  /// Change the ownership of the file at `path` to be owned by the specified
639  /// `owner` (user) and `group` (see
640  /// [chown(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
641  ///
642  /// The owner/group for the provided path name will not be modified if `None` is
643  /// provided for that argument.  Ownership change will be attempted for the path
644  /// only if `Some` owner/group is provided.
645  #[inline]
chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()>646  pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
647      let res = path.with_nix_path(|cstr| {
648          let (uid, gid) = chown_raw_ids(owner, group);
649          unsafe { libc::chown(cstr.as_ptr(), uid, gid) }
650      })?;
651  
652      Errno::result(res).map(drop)
653  }
654  
655  /// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by
656  /// the specified `owner` (user) and `group` (see
657  /// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)).
658  ///
659  /// The owner/group for the provided file will not be modified if `None` is
660  /// provided for that argument.  Ownership change will be attempted for the path
661  /// only if `Some` owner/group is provided.
662  #[inline]
fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()>663  pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
664      let (uid, gid) = chown_raw_ids(owner, group);
665      let res = unsafe { libc::fchown(fd, uid, gid) };
666      Errno::result(res).map(drop)
667  }
668  
669  /// Flags for `fchownat` function.
670  #[derive(Clone, Copy, Debug)]
671  pub enum FchownatFlags {
672      FollowSymlink,
673      NoFollowSymlink,
674  }
675  
676  /// Change the ownership of the file at `path` to be owned by the specified
677  /// `owner` (user) and `group`.
678  ///
679  /// The owner/group for the provided path name will not be modified if `None` is
680  /// provided for that argument.  Ownership change will be attempted for the path
681  /// only if `Some` owner/group is provided.
682  ///
683  /// The file to be changed is determined relative to the directory associated
684  /// with the file descriptor `dirfd` or the current working directory
685  /// if `dirfd` is `None`.
686  ///
687  /// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
688  /// then the mode of the symbolic link is changed.
689  ///
690  /// `fchownat(None, path, mode, FchownatFlags::NoFollowSymlink)` is identical to
691  /// a call `libc::lchown(path, mode)`.  That's why `lchmod` is unimplemented in
692  /// the `nix` crate.
693  ///
694  /// # References
695  ///
696  /// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
697  #[cfg(not(target_os = "redox"))]
fchownat<P: ?Sized + NixPath>( dirfd: Option<RawFd>, path: &P, owner: Option<Uid>, group: Option<Gid>, flag: FchownatFlags, ) -> Result<()>698  pub fn fchownat<P: ?Sized + NixPath>(
699      dirfd: Option<RawFd>,
700      path: &P,
701      owner: Option<Uid>,
702      group: Option<Gid>,
703      flag: FchownatFlags,
704  ) -> Result<()> {
705      let atflag =
706          match flag {
707              FchownatFlags::FollowSymlink => AtFlags::empty(),
708              FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
709          };
710      let res = path.with_nix_path(|cstr| unsafe {
711          let (uid, gid) = chown_raw_ids(owner, group);
712          libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid,
713                         atflag.bits() as libc::c_int)
714      })?;
715  
716      Errno::result(res).map(drop)
717  }
718  
to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char>719  fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
720      use std::iter::once;
721      args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect()
722  }
723  
724  /// Replace the current process image with a new one (see
725  /// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
726  ///
727  /// See the `::nix::unistd::execve` system call for additional details.  `execv`
728  /// performs the same action but does not allow for customization of the
729  /// environment for the new process.
730  #[inline]
execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible>731  pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
732      let args_p = to_exec_array(argv);
733  
734      unsafe {
735          libc::execv(path.as_ptr(), args_p.as_ptr())
736      };
737  
738      Err(Error::Sys(Errno::last()))
739  }
740  
741  
742  /// Replace the current process image with a new one (see
743  /// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
744  ///
745  /// The execve system call allows for another process to be "called" which will
746  /// replace the current process image.  That is, this process becomes the new
747  /// command that is run. On success, this function will not return. Instead,
748  /// the new program will run until it exits.
749  ///
750  /// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
751  /// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
752  /// in the `args` list is an argument to the new process. Each element in the
753  /// `env` list should be a string in the form "key=value".
754  #[inline]
execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible>755  pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
756      let args_p = to_exec_array(args);
757      let env_p = to_exec_array(env);
758  
759      unsafe {
760          libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
761      };
762  
763      Err(Error::Sys(Errno::last()))
764  }
765  
766  /// Replace the current process image with a new one and replicate shell `PATH`
767  /// searching behavior (see
768  /// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
769  ///
770  /// See `::nix::unistd::execve` for additional details.  `execvp` behaves the
771  /// same as execv except that it will examine the `PATH` environment variables
772  /// for file names not specified with a leading slash.  For example, `execv`
773  /// would not work if "bash" was specified for the path argument, but `execvp`
774  /// would assuming that a bash executable was on the system `PATH`.
775  #[inline]
execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible>776  pub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> {
777      let args_p = to_exec_array(args);
778  
779      unsafe {
780          libc::execvp(filename.as_ptr(), args_p.as_ptr())
781      };
782  
783      Err(Error::Sys(Errno::last()))
784  }
785  
786  /// Replace the current process image with a new one and replicate shell `PATH`
787  /// searching behavior (see
788  /// [`execvpe(3)`](http://man7.org/linux/man-pages/man3/exec.3.html)).
789  ///
790  /// This functions like a combination of `execvp(2)` and `execve(2)` to pass an
791  /// environment and have a search path. See these two for additional
792  /// information.
793  #[cfg(any(target_os = "haiku",
794            target_os = "linux",
795            target_os = "openbsd"))]
execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible>796  pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
797      let args_p = to_exec_array(args);
798      let env_p = to_exec_array(env);
799  
800      unsafe {
801          libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
802      };
803  
804      Err(Error::Sys(Errno::last()))
805  }
806  
807  /// Replace the current process image with a new one (see
808  /// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
809  ///
810  /// The `fexecve` function allows for another process to be "called" which will
811  /// replace the current process image.  That is, this process becomes the new
812  /// command that is run. On success, this function will not return. Instead,
813  /// the new program will run until it exits.
814  ///
815  /// This function is similar to `execve`, except that the program to be executed
816  /// is referenced as a file descriptor instead of a path.
817  // Note for NetBSD and OpenBSD: although rust-lang/libc includes it (under
818  // unix/bsd/netbsdlike/) fexecve is not currently implemented on NetBSD nor on
819  // OpenBSD.
820  #[cfg(any(target_os = "android",
821            target_os = "linux",
822            target_os = "freebsd"))]
823  #[inline]
fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible>824  pub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> {
825      let args_p = to_exec_array(args);
826      let env_p = to_exec_array(env);
827  
828      unsafe {
829          libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
830      };
831  
832      Err(Error::Sys(Errno::last()))
833  }
834  
835  /// Execute program relative to a directory file descriptor (see
836  /// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
837  ///
838  /// The `execveat` function allows for another process to be "called" which will
839  /// replace the current process image.  That is, this process becomes the new
840  /// command that is run. On success, this function will not return. Instead,
841  /// the new program will run until it exits.
842  ///
843  /// This function is similar to `execve`, except that the program to be executed
844  /// is referenced as a file descriptor to the base directory plus a path.
845  #[cfg(any(target_os = "android", target_os = "linux"))]
846  #[inline]
execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA], env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible>847  pub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA],
848                  env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> {
849      let args_p = to_exec_array(args);
850      let env_p = to_exec_array(env);
851  
852      unsafe {
853          libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(),
854                        args_p.as_ptr(), env_p.as_ptr(), flags);
855      };
856  
857      Err(Error::Sys(Errno::last()))
858  }
859  
860  /// Daemonize this process by detaching from the controlling terminal (see
861  /// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
862  ///
863  /// When a process is launched it is typically associated with a parent and it,
864  /// in turn, by its controlling terminal/process.  In order for a process to run
865  /// in the "background" it must daemonize itself by detaching itself.  Under
866  /// posix, this is done by doing the following:
867  ///
868  /// 1. Parent process (this one) forks
869  /// 2. Parent process exits
870  /// 3. Child process continues to run.
871  ///
872  /// `nochdir`:
873  ///
874  /// * `nochdir = true`: The current working directory after daemonizing will
875  ///    be the current working directory.
876  /// *  `nochdir = false`: The current working directory after daemonizing will
877  ///    be the root direcory, `/`.
878  ///
879  /// `noclose`:
880  ///
881  /// * `noclose = true`: The process' current stdin, stdout, and stderr file
882  ///   descriptors will remain identical after daemonizing.
883  /// * `noclose = false`: The process' stdin, stdout, and stderr will point to
884  ///   `/dev/null` after daemonizing.
885  #[cfg(any(target_os = "android",
886            target_os = "dragonfly",
887            target_os = "freebsd",
888            target_os = "linux",
889            target_os = "netbsd",
890            target_os = "openbsd"))]
daemon(nochdir: bool, noclose: bool) -> Result<()>891  pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
892      let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
893      Errno::result(res).map(drop)
894  }
895  
896  /// Set the system host name (see
897  /// [sethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
898  ///
899  /// Given a name, attempt to update the system host name to the given string.
900  /// On some systems, the host name is limited to as few as 64 bytes.  An error
901  /// will be return if the name is not valid or the current process does not have
902  /// permissions to update the host name.
903  #[cfg(not(target_os = "redox"))]
sethostname<S: AsRef<OsStr>>(name: S) -> Result<()>904  pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
905      // Handle some differences in type of the len arg across platforms.
906      cfg_if! {
907          if #[cfg(any(target_os = "dragonfly",
908                       target_os = "freebsd",
909                       target_os = "ios",
910                       target_os = "macos", ))] {
911              type sethostname_len_t = c_int;
912          } else {
913              type sethostname_len_t = size_t;
914          }
915      }
916      let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
917      let len = name.as_ref().len() as sethostname_len_t;
918  
919      let res = unsafe { libc::sethostname(ptr, len) };
920      Errno::result(res).map(drop)
921  }
922  
923  /// Get the host name and store it in the provided buffer, returning a pointer
924  /// the `CStr` in that buffer on success (see
925  /// [gethostname(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
926  ///
927  /// This function call attempts to get the host name for the running system and
928  /// store it in a provided buffer.  The buffer will be populated with bytes up
929  /// to the length of the provided slice including a NUL terminating byte.  If
930  /// the hostname is longer than the length provided, no error will be provided.
931  /// The posix specification does not specify whether implementations will
932  /// null-terminate in this case, but the nix implementation will ensure that the
933  /// buffer is null terminated in this case.
934  ///
935  /// ```no_run
936  /// use nix::unistd;
937  ///
938  /// let mut buf = [0u8; 64];
939  /// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
940  /// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
941  /// println!("Hostname: {}", hostname);
942  /// ```
gethostname(buffer: &mut [u8]) -> Result<&CStr>943  pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
944      let ptr = buffer.as_mut_ptr() as *mut c_char;
945      let len = buffer.len() as size_t;
946  
947      let res = unsafe { libc::gethostname(ptr, len) };
948      Errno::result(res).map(|_| {
949          buffer[len - 1] = 0; // ensure always null-terminated
950          unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
951      })
952  }
953  
954  /// Close a raw file descriptor
955  ///
956  /// Be aware that many Rust types implicitly close-on-drop, including
957  /// `std::fs::File`.  Explicitly closing them with this method too can result in
958  /// a double-close condition, which can cause confusing `EBADF` errors in
959  /// seemingly unrelated code.  Caveat programmer.  See also
960  /// [close(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
961  ///
962  /// # Examples
963  ///
964  /// ```no_run
965  /// use std::os::unix::io::AsRawFd;
966  /// use nix::unistd::close;
967  ///
968  /// fn main() {
969  ///     let f = tempfile::tempfile().unwrap();
970  ///     close(f.as_raw_fd()).unwrap();   // Bad!  f will also close on drop!
971  /// }
972  /// ```
973  ///
974  /// ```rust
975  /// use std::os::unix::io::IntoRawFd;
976  /// use nix::unistd::close;
977  ///
978  /// fn main() {
979  ///     let f = tempfile::tempfile().unwrap();
980  ///     close(f.into_raw_fd()).unwrap(); // Good.  into_raw_fd consumes f
981  /// }
982  /// ```
close(fd: RawFd) -> Result<()>983  pub fn close(fd: RawFd) -> Result<()> {
984      let res = unsafe { libc::close(fd) };
985      Errno::result(res).map(drop)
986  }
987  
988  /// Read from a raw file descriptor.
989  ///
990  /// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
read(fd: RawFd, buf: &mut [u8]) -> Result<usize>991  pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
992      let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
993  
994      Errno::result(res).map(|r| r as usize)
995  }
996  
997  /// Write to a raw file descriptor.
998  ///
999  /// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
write(fd: RawFd, buf: &[u8]) -> Result<usize>1000  pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
1001      let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
1002  
1003      Errno::result(res).map(|r| r as usize)
1004  }
1005  
1006  /// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to.
1007  ///
1008  /// [`lseek`]: ./fn.lseek.html
1009  /// [`lseek64`]: ./fn.lseek64.html
1010  #[repr(i32)]
1011  #[derive(Clone, Copy, Debug)]
1012  pub enum Whence {
1013      /// Specify an offset relative to the start of the file.
1014      SeekSet = libc::SEEK_SET,
1015      /// Specify an offset relative to the current file location.
1016      SeekCur = libc::SEEK_CUR,
1017      /// Specify an offset relative to the end of the file.
1018      SeekEnd = libc::SEEK_END,
1019      /// Specify an offset relative to the next location in the file greater than or
1020      /// equal to offset that contains some data. If offset points to
1021      /// some data, then the file offset is set to offset.
1022      #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
1023      SeekData = libc::SEEK_DATA,
1024      /// Specify an offset relative to the next hole in the file greater than
1025      /// or equal to offset. If offset points into the middle of a hole, then
1026      /// the file offset should be set to offset. If there is no hole past offset,
1027      /// then the file offset should be adjusted to the end of the file (i.e., there
1028      /// is an implicit hole at the end of any file).
1029      #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
1030      SeekHole = libc::SEEK_HOLE
1031  }
1032  
1033  /// Move the read/write file offset.
1034  ///
1035  /// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t>1036  pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
1037      let res = unsafe { libc::lseek(fd, offset, whence as i32) };
1038  
1039      Errno::result(res).map(|r| r as off_t)
1040  }
1041  
1042  #[cfg(any(target_os = "linux", target_os = "android"))]
lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t>1043  pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t> {
1044      let res = unsafe { libc::lseek64(fd, offset, whence as i32) };
1045  
1046      Errno::result(res).map(|r| r as libc::off64_t)
1047  }
1048  
1049  /// Create an interprocess channel.
1050  ///
1051  /// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
pipe() -> Result<(RawFd, RawFd)>1052  pub fn pipe() -> Result<(RawFd, RawFd)> {
1053      unsafe {
1054          let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
1055  
1056          let res = libc::pipe(fds.as_mut_ptr() as *mut c_int);
1057  
1058          Errno::result(res)?;
1059  
1060          Ok((fds.assume_init()[0], fds.assume_init()[1]))
1061      }
1062  }
1063  
1064  /// Like `pipe`, but allows setting certain file descriptor flags.
1065  ///
1066  /// The following flags are supported, and will be set atomically as the pipe is
1067  /// created:
1068  ///
1069  /// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
1070  #[cfg_attr(target_os = "linux", doc = "`O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode.  ")]
1071  #[cfg_attr(target_os = "netbsd", doc = "`O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`.  ")]
1072  /// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
1073  ///
1074  /// See also [pipe(2)](http://man7.org/linux/man-pages/man2/pipe.2.html)
1075  #[cfg(any(target_os = "android",
1076            target_os = "dragonfly",
1077            target_os = "emscripten",
1078            target_os = "freebsd",
1079            target_os = "linux",
1080            target_os = "redox",
1081            target_os = "netbsd",
1082            target_os = "openbsd"))]
pipe2(flags: OFlag) -> Result<(RawFd, RawFd)>1083  pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
1084      let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
1085  
1086      let res = unsafe {
1087          libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits())
1088      };
1089  
1090      Errno::result(res)?;
1091  
1092      unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
1093  }
1094  
1095  /// Truncate a file to a specified length
1096  ///
1097  /// See also
1098  /// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
1099  #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()>1100  pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
1101      let res = path.with_nix_path(|cstr| {
1102          unsafe {
1103              libc::truncate(cstr.as_ptr(), len)
1104          }
1105      })?;
1106  
1107      Errno::result(res).map(drop)
1108  }
1109  
1110  /// Truncate a file to a specified length
1111  ///
1112  /// See also
1113  /// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
ftruncate(fd: RawFd, len: off_t) -> Result<()>1114  pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
1115      Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
1116  }
1117  
isatty(fd: RawFd) -> Result<bool>1118  pub fn isatty(fd: RawFd) -> Result<bool> {
1119      unsafe {
1120          // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
1121          // we return `Ok(false)`
1122          if libc::isatty(fd) == 1 {
1123              Ok(true)
1124          } else {
1125              match Errno::last() {
1126                  Errno::ENOTTY => Ok(false),
1127                  err => Err(Error::Sys(err)),
1128              }
1129          }
1130      }
1131  }
1132  
1133  /// Flags for `linkat` function.
1134  #[derive(Clone, Copy, Debug)]
1135  pub enum LinkatFlags {
1136      SymlinkFollow,
1137      NoSymlinkFollow,
1138  }
1139  
1140  /// Link one file to another file
1141  ///
1142  /// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
1143  /// case of a relative `oldpath`, the path is interpreted relative to the directory associated
1144  /// with file descriptor `olddirfd` instead of the current working directory and similiarly for
1145  /// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
1146  /// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
1147  /// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
1148  /// and/or `newpath` is then interpreted relative to the current working directory of the calling
1149  /// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored.
1150  ///
1151  /// # References
1152  /// See also [linkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
1153  #[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
linkat<P: ?Sized + NixPath>( olddirfd: Option<RawFd>, oldpath: &P, newdirfd: Option<RawFd>, newpath: &P, flag: LinkatFlags, ) -> Result<()>1154  pub fn linkat<P: ?Sized + NixPath>(
1155      olddirfd: Option<RawFd>,
1156      oldpath: &P,
1157      newdirfd: Option<RawFd>,
1158      newpath: &P,
1159      flag: LinkatFlags,
1160  ) -> Result<()> {
1161  
1162      let atflag =
1163          match flag {
1164              LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
1165              LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
1166          };
1167  
1168      let res =
1169          oldpath.with_nix_path(|oldcstr| {
1170              newpath.with_nix_path(|newcstr| {
1171              unsafe {
1172                  libc::linkat(
1173                      at_rawfd(olddirfd),
1174                      oldcstr.as_ptr(),
1175                      at_rawfd(newdirfd),
1176                      newcstr.as_ptr(),
1177                      atflag.bits() as libc::c_int
1178                      )
1179                  }
1180              })
1181          })??;
1182      Errno::result(res).map(drop)
1183  }
1184  
1185  
1186  /// Remove a directory entry
1187  ///
1188  /// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
unlink<P: ?Sized + NixPath>(path: &P) -> Result<()>1189  pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
1190      let res = path.with_nix_path(|cstr| {
1191          unsafe {
1192              libc::unlink(cstr.as_ptr())
1193          }
1194      })?;
1195      Errno::result(res).map(drop)
1196  }
1197  
1198  /// Flags for `unlinkat` function.
1199  #[derive(Clone, Copy, Debug)]
1200  pub enum UnlinkatFlags {
1201      RemoveDir,
1202      NoRemoveDir,
1203  }
1204  
1205  /// Remove a directory entry
1206  ///
1207  /// In the case of a relative path, the directory entry to be removed is determined relative to
1208  /// the directory associated with the file descriptor `dirfd` or the current working directory
1209  /// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is
1210  /// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path`
1211  /// is performed.
1212  ///
1213  /// # References
1214  /// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
1215  #[cfg(not(target_os = "redox"))]
unlinkat<P: ?Sized + NixPath>( dirfd: Option<RawFd>, path: &P, flag: UnlinkatFlags, ) -> Result<()>1216  pub fn unlinkat<P: ?Sized + NixPath>(
1217      dirfd: Option<RawFd>,
1218      path: &P,
1219      flag: UnlinkatFlags,
1220  ) -> Result<()> {
1221      let atflag =
1222          match flag {
1223              UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR,
1224              UnlinkatFlags::NoRemoveDir => AtFlags::empty(),
1225          };
1226      let res = path.with_nix_path(|cstr| {
1227          unsafe {
1228              libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int)
1229          }
1230      })?;
1231      Errno::result(res).map(drop)
1232  }
1233  
1234  
1235  #[inline]
1236  #[cfg(not(target_os = "fuchsia"))]
chroot<P: ?Sized + NixPath>(path: &P) -> Result<()>1237  pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
1238      let res = path.with_nix_path(|cstr| {
1239          unsafe { libc::chroot(cstr.as_ptr()) }
1240      })?;
1241  
1242      Errno::result(res).map(drop)
1243  }
1244  
1245  /// Commit filesystem caches to disk
1246  ///
1247  /// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
1248  #[cfg(any(
1249      target_os = "dragonfly",
1250      target_os = "freebsd",
1251      target_os = "linux",
1252      target_os = "netbsd",
1253      target_os = "openbsd"
1254  ))]
sync()1255  pub fn sync() {
1256      unsafe { libc::sync() };
1257  }
1258  
1259  /// Synchronize changes to a file
1260  ///
1261  /// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
1262  #[inline]
fsync(fd: RawFd) -> Result<()>1263  pub fn fsync(fd: RawFd) -> Result<()> {
1264      let res = unsafe { libc::fsync(fd) };
1265  
1266      Errno::result(res).map(drop)
1267  }
1268  
1269  /// Synchronize the data of a file
1270  ///
1271  /// See also
1272  /// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
1273  // `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
1274  // TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
1275  #[cfg(any(target_os = "linux",
1276            target_os = "android",
1277            target_os = "emscripten"))]
1278  #[inline]
fdatasync(fd: RawFd) -> Result<()>1279  pub fn fdatasync(fd: RawFd) -> Result<()> {
1280      let res = unsafe { libc::fdatasync(fd) };
1281  
1282      Errno::result(res).map(drop)
1283  }
1284  
1285  /// Get a real user ID
1286  ///
1287  /// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
1288  // POSIX requires that getuid is always successful, so no need to check return
1289  // value or errno.
1290  #[inline]
getuid() -> Uid1291  pub fn getuid() -> Uid {
1292      Uid(unsafe { libc::getuid() })
1293  }
1294  
1295  /// Get the effective user ID
1296  ///
1297  /// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
1298  // POSIX requires that geteuid is always successful, so no need to check return
1299  // value or errno.
1300  #[inline]
geteuid() -> Uid1301  pub fn geteuid() -> Uid {
1302      Uid(unsafe { libc::geteuid() })
1303  }
1304  
1305  /// Get the real group ID
1306  ///
1307  /// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
1308  // POSIX requires that getgid is always successful, so no need to check return
1309  // value or errno.
1310  #[inline]
getgid() -> Gid1311  pub fn getgid() -> Gid {
1312      Gid(unsafe { libc::getgid() })
1313  }
1314  
1315  /// Get the effective group ID
1316  ///
1317  /// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
1318  // POSIX requires that getegid is always successful, so no need to check return
1319  // value or errno.
1320  #[inline]
getegid() -> Gid1321  pub fn getegid() -> Gid {
1322      Gid(unsafe { libc::getegid() })
1323  }
1324  
1325  /// Set the effective user ID
1326  ///
1327  /// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
1328  #[inline]
seteuid(euid: Uid) -> Result<()>1329  pub fn seteuid(euid: Uid) -> Result<()> {
1330      let res = unsafe { libc::seteuid(euid.into()) };
1331  
1332      Errno::result(res).map(drop)
1333  }
1334  
1335  /// Set the effective group ID
1336  ///
1337  /// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
1338  #[inline]
setegid(egid: Gid) -> Result<()>1339  pub fn setegid(egid: Gid) -> Result<()> {
1340      let res = unsafe { libc::setegid(egid.into()) };
1341  
1342      Errno::result(res).map(drop)
1343  }
1344  
1345  /// Set the user ID
1346  ///
1347  /// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
1348  #[inline]
setuid(uid: Uid) -> Result<()>1349  pub fn setuid(uid: Uid) -> Result<()> {
1350      let res = unsafe { libc::setuid(uid.into()) };
1351  
1352      Errno::result(res).map(drop)
1353  }
1354  
1355  /// Set the group ID
1356  ///
1357  /// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
1358  #[inline]
setgid(gid: Gid) -> Result<()>1359  pub fn setgid(gid: Gid) -> Result<()> {
1360      let res = unsafe { libc::setgid(gid.into()) };
1361  
1362      Errno::result(res).map(drop)
1363  }
1364  
1365  /// Set the user identity used for filesystem checks per-thread.
1366  /// On both success and failure, this call returns the previous filesystem user
1367  /// ID of the caller.
1368  ///
1369  /// See also [setfsuid(2)](http://man7.org/linux/man-pages/man2/setfsuid.2.html)
1370  #[cfg(any(target_os = "linux", target_os = "android"))]
setfsuid(uid: Uid) -> Uid1371  pub fn setfsuid(uid: Uid) -> Uid {
1372      let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
1373      Uid::from_raw(prev_fsuid as uid_t)
1374  }
1375  
1376  /// Set the group identity used for filesystem checks per-thread.
1377  /// On both success and failure, this call returns the previous filesystem group
1378  /// ID of the caller.
1379  ///
1380  /// See also [setfsgid(2)](http://man7.org/linux/man-pages/man2/setfsgid.2.html)
1381  #[cfg(any(target_os = "linux", target_os = "android"))]
setfsgid(gid: Gid) -> Gid1382  pub fn setfsgid(gid: Gid) -> Gid {
1383      let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
1384      Gid::from_raw(prev_fsgid as gid_t)
1385  }
1386  
1387  /// Get the list of supplementary group IDs of the calling process.
1388  ///
1389  /// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
1390  ///
1391  /// **Note:** This function is not available for Apple platforms. On those
1392  /// platforms, checking group membership should be achieved via communication
1393  /// with the `opendirectoryd` service.
1394  #[cfg(not(any(target_os = "ios", target_os = "macos")))]
getgroups() -> Result<Vec<Gid>>1395  pub fn getgroups() -> Result<Vec<Gid>> {
1396      // First get the maximum number of groups. The value returned
1397      // shall always be greater than or equal to one and less than or
1398      // equal to the value of {NGROUPS_MAX} + 1.
1399      let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
1400          Ok(Some(n)) => (n + 1) as usize,
1401          Ok(None) | Err(_) => <usize>::max_value(),
1402      };
1403  
1404      // Next, get the number of groups so we can size our Vec
1405      let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
1406  
1407      // Now actually get the groups. We try multiple times in case the number of
1408      // groups has changed since the first call to getgroups() and the buffer is
1409      // now too small.
1410      let mut groups = Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize);
1411      loop {
1412          // FIXME: On the platforms we currently support, the `Gid` struct has
1413          // the same representation in memory as a bare `gid_t`. This is not
1414          // necessarily the case on all Rust platforms, though. See RFC 1785.
1415          let ngroups = unsafe {
1416              libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
1417          };
1418  
1419          match Errno::result(ngroups) {
1420              Ok(s) => {
1421                  unsafe { groups.set_len(s as usize) };
1422                  return Ok(groups);
1423              },
1424              Err(Error::Sys(Errno::EINVAL)) => {
1425                  // EINVAL indicates that the buffer size was too
1426                  // small, resize it up to ngroups_max as limit.
1427                  reserve_double_buffer_size(&mut groups, ngroups_max)
1428                      .or(Err(Error::Sys(Errno::EINVAL)))?;
1429              },
1430              Err(e) => return Err(e)
1431          }
1432      }
1433  }
1434  
1435  /// Set the list of supplementary group IDs for the calling process.
1436  ///
1437  /// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
1438  ///
1439  /// **Note:** This function is not available for Apple platforms. On those
1440  /// platforms, group membership management should be achieved via communication
1441  /// with the `opendirectoryd` service.
1442  ///
1443  /// # Examples
1444  ///
1445  /// `setgroups` can be used when dropping privileges from the root user to a
1446  /// specific user and group. For example, given the user `www-data` with UID
1447  /// `33` and the group `backup` with the GID `34`, one could switch the user as
1448  /// follows:
1449  ///
1450  /// ```rust,no_run
1451  /// # use std::error::Error;
1452  /// # use nix::unistd::*;
1453  /// #
1454  /// # fn try_main() -> Result<(), Box<Error>> {
1455  /// let uid = Uid::from_raw(33);
1456  /// let gid = Gid::from_raw(34);
1457  /// setgroups(&[gid])?;
1458  /// setgid(gid)?;
1459  /// setuid(uid)?;
1460  /// #
1461  /// #     Ok(())
1462  /// # }
1463  /// #
1464  /// # try_main().unwrap();
1465  /// ```
1466  #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
setgroups(groups: &[Gid]) -> Result<()>1467  pub fn setgroups(groups: &[Gid]) -> Result<()> {
1468      cfg_if! {
1469          if #[cfg(any(target_os = "dragonfly",
1470                       target_os = "freebsd",
1471                       target_os = "ios",
1472                       target_os = "macos",
1473                       target_os = "netbsd",
1474                       target_os = "openbsd"))] {
1475              type setgroups_ngroups_t = c_int;
1476          } else {
1477              type setgroups_ngroups_t = size_t;
1478          }
1479      }
1480      // FIXME: On the platforms we currently support, the `Gid` struct has the
1481      // same representation in memory as a bare `gid_t`. This is not necessarily
1482      // the case on all Rust platforms, though. See RFC 1785.
1483      let res = unsafe {
1484          libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t)
1485      };
1486  
1487      Errno::result(res).map(drop)
1488  }
1489  
1490  /// Calculate the supplementary group access list.
1491  ///
1492  /// Gets the group IDs of all groups that `user` is a member of. The additional
1493  /// group `group` is also added to the list.
1494  ///
1495  /// [Further reading](http://man7.org/linux/man-pages/man3/getgrouplist.3.html)
1496  ///
1497  /// **Note:** This function is not available for Apple platforms. On those
1498  /// platforms, checking group membership should be achieved via communication
1499  /// with the `opendirectoryd` service.
1500  ///
1501  /// # Errors
1502  ///
1503  /// Although the `getgrouplist()` call does not return any specific
1504  /// errors on any known platforms, this implementation will return a system
1505  /// error of `EINVAL` if the number of groups to be fetched exceeds the
1506  /// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()`
1507  /// and `setgroups()`. Additionally, while some implementations will return a
1508  /// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation
1509  /// will only ever return the complete list or else an error.
1510  #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>>1511  pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
1512      let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
1513          Ok(Some(n)) => n as c_int,
1514          Ok(None) | Err(_) => <c_int>::max_value(),
1515      };
1516      use std::cmp::min;
1517      let mut ngroups = min(ngroups_max, 8);
1518      let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
1519      cfg_if! {
1520          if #[cfg(any(target_os = "ios", target_os = "macos"))] {
1521              type getgrouplist_group_t = c_int;
1522          } else {
1523              type getgrouplist_group_t = gid_t;
1524          }
1525      }
1526      let gid: gid_t = group.into();
1527      loop {
1528          let ret = unsafe {
1529              libc::getgrouplist(user.as_ptr(),
1530                                 gid as getgrouplist_group_t,
1531                                 groups.as_mut_ptr() as *mut getgrouplist_group_t,
1532                                 &mut ngroups)
1533          };
1534  
1535          // BSD systems only return 0 or -1, Linux returns ngroups on success.
1536          if ret >= 0 {
1537              unsafe { groups.set_len(ngroups as usize) };
1538              return Ok(groups);
1539          } else if ret == -1 {
1540              // Returns -1 if ngroups is too small, but does not set errno.
1541              // BSD systems will still fill the groups buffer with as many
1542              // groups as possible, but Linux manpages do not mention this
1543              // behavior.
1544              reserve_double_buffer_size(&mut groups, ngroups_max as usize)
1545                  .or_else(|_| Err(Error::invalid_argument()))?;
1546          }
1547      }
1548  }
1549  
1550  /// Initialize the supplementary group access list.
1551  ///
1552  /// Sets the supplementary group IDs for the calling process using all groups
1553  /// that `user` is a member of. The additional group `group` is also added to
1554  /// the list.
1555  ///
1556  /// [Further reading](http://man7.org/linux/man-pages/man3/initgroups.3.html)
1557  ///
1558  /// **Note:** This function is not available for Apple platforms. On those
1559  /// platforms, group membership management should be achieved via communication
1560  /// with the `opendirectoryd` service.
1561  ///
1562  /// # Examples
1563  ///
1564  /// `initgroups` can be used when dropping privileges from the root user to
1565  /// another user. For example, given the user `www-data`, we could look up the
1566  /// UID and GID for the user in the system's password database (usually found
1567  /// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`,
1568  /// respectively, one could switch the user as follows:
1569  ///
1570  /// ```rust,no_run
1571  /// # use std::error::Error;
1572  /// # use std::ffi::CString;
1573  /// # use nix::unistd::*;
1574  /// #
1575  /// # fn try_main() -> Result<(), Box<Error>> {
1576  /// let user = CString::new("www-data").unwrap();
1577  /// let uid = Uid::from_raw(33);
1578  /// let gid = Gid::from_raw(33);
1579  /// initgroups(&user, gid)?;
1580  /// setgid(gid)?;
1581  /// setuid(uid)?;
1582  /// #
1583  /// #     Ok(())
1584  /// # }
1585  /// #
1586  /// # try_main().unwrap();
1587  /// ```
1588  #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
initgroups(user: &CStr, group: Gid) -> Result<()>1589  pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
1590      cfg_if! {
1591          if #[cfg(any(target_os = "ios", target_os = "macos"))] {
1592              type initgroups_group_t = c_int;
1593          } else {
1594              type initgroups_group_t = gid_t;
1595          }
1596      }
1597      let gid: gid_t = group.into();
1598      let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) };
1599  
1600      Errno::result(res).map(drop)
1601  }
1602  
1603  /// Suspend the thread until a signal is received.
1604  ///
1605  /// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
1606  #[inline]
1607  #[cfg(not(target_os = "redox"))]
pause()1608  pub fn pause() {
1609      unsafe { libc::pause() };
1610  }
1611  
1612  pub mod alarm {
1613      //! Alarm signal scheduling.
1614      //!
1615      //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
1616      //! elapsed, which has to be caught, because the default action for the
1617      //! signal is to terminate the program. This signal also can't be ignored
1618      //! because the system calls like `pause` will not be interrupted, see the
1619      //! second example below.
1620      //!
1621      //! # Examples
1622      //!
1623      //! Canceling an alarm:
1624      //!
1625      //! ```
1626      //! use nix::unistd::alarm;
1627      //!
1628      //! // Set an alarm for 60 seconds from now.
1629      //! alarm::set(60);
1630      //!
1631      //! // Cancel the above set alarm, which returns the number of seconds left
1632      //! // of the previously set alarm.
1633      //! assert_eq!(alarm::cancel(), Some(60));
1634      //! ```
1635      //!
1636      //! Scheduling an alarm and waiting for the signal:
1637      //!
1638  #![cfg_attr(target_os = "redox", doc = " ```rust,ignore")]
1639  #![cfg_attr(not(target_os = "redox"), doc = " ```rust")]
1640      //! use std::time::{Duration, Instant};
1641      //!
1642      //! use nix::unistd::{alarm, pause};
1643      //! use nix::sys::signal::*;
1644      //!
1645      //! // We need to setup an empty signal handler to catch the alarm signal,
1646      //! // otherwise the program will be terminated once the signal is delivered.
1647      //! extern fn signal_handler(_: nix::libc::c_int) { }
1648      //! let sa = SigAction::new(
1649      //!     SigHandler::Handler(signal_handler),
1650      //!     SaFlags::empty(),
1651      //!     SigSet::empty()
1652      //! );
1653      //! unsafe {
1654      //!     sigaction(Signal::SIGALRM, &sa);
1655      //! }
1656      //!
1657      //! // Set an alarm for 1 second from now.
1658      //! alarm::set(1);
1659      //!
1660      //! let start = Instant::now();
1661      //! // Pause the process until the alarm signal is received.
1662      //! let mut sigset = SigSet::empty();
1663      //! sigset.add(Signal::SIGALRM);
1664      //! sigset.wait();
1665      //!
1666      //! assert!(start.elapsed() >= Duration::from_secs(1));
1667      //! ```
1668      //!
1669      //! # References
1670      //!
1671      //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
1672  
1673      /// Schedule an alarm signal.
1674      ///
1675      /// This will cause the system to generate a `SIGALRM` signal for the
1676      /// process after the specified number of seconds have elapsed.
1677      ///
1678      /// Returns the leftover time of a previously set alarm if there was one.
set(secs: libc::c_uint) -> Option<libc::c_uint>1679      pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
1680          assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
1681          alarm(secs)
1682      }
1683  
1684      /// Cancel an previously set alarm signal.
1685      ///
1686      /// Returns the leftover time of a previously set alarm if there was one.
cancel() -> Option<libc::c_uint>1687      pub fn cancel() -> Option<libc::c_uint> {
1688          alarm(0)
1689      }
1690  
alarm(secs: libc::c_uint) -> Option<libc::c_uint>1691      fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
1692          match unsafe { libc::alarm(secs) } {
1693              0 => None,
1694              secs => Some(secs),
1695          }
1696      }
1697  }
1698  
1699  /// Suspend execution for an interval of time
1700  ///
1701  /// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
1702  // Per POSIX, does not fail
1703  #[inline]
sleep(seconds: c_uint) -> c_uint1704  pub fn sleep(seconds: c_uint) -> c_uint {
1705      unsafe { libc::sleep(seconds) }
1706  }
1707  
1708  #[cfg(not(target_os = "redox"))]
1709  pub mod acct {
1710      use crate::{Result, NixPath};
1711      use crate::errno::Errno;
1712      use std::ptr;
1713  
1714      /// Enable process accounting
1715      ///
1716      /// See also [acct(2)](https://linux.die.net/man/2/acct)
enable<P: ?Sized + NixPath>(filename: &P) -> Result<()>1717      pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> {
1718          let res = filename.with_nix_path(|cstr| {
1719              unsafe { libc::acct(cstr.as_ptr()) }
1720          })?;
1721  
1722          Errno::result(res).map(drop)
1723      }
1724  
1725      /// Disable process accounting
disable() -> Result<()>1726      pub fn disable() -> Result<()> {
1727          let res = unsafe { libc::acct(ptr::null()) };
1728  
1729          Errno::result(res).map(drop)
1730      }
1731  }
1732  
1733  /// Creates a regular file which persists even after process termination
1734  ///
1735  /// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX`
1736  /// * returns: tuple of file descriptor and filename
1737  ///
1738  /// Err is returned either if no temporary filename could be created or the template doesn't
1739  /// end with XXXXXX
1740  ///
1741  /// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
1742  ///
1743  /// # Example
1744  ///
1745  /// ```rust
1746  /// use nix::unistd;
1747  ///
1748  /// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
1749  ///     Ok((fd, path)) => {
1750  ///         unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
1751  ///         fd
1752  ///     }
1753  ///     Err(e) => panic!("mkstemp failed: {}", e)
1754  /// };
1755  /// // do something with fd
1756  /// ```
1757  #[inline]
mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)>1758  pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
1759      let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
1760      let p = path.as_mut_ptr() as *mut _;
1761      let fd = unsafe { libc::mkstemp(p) };
1762      let last = path.pop(); // drop the trailing nul
1763      debug_assert!(last == Some(b'\0'));
1764      let pathname = OsString::from_vec(path);
1765      Errno::result(fd)?;
1766      Ok((fd, PathBuf::from(pathname)))
1767  }
1768  
1769  /// Variable names for `pathconf`
1770  ///
1771  /// Nix uses the same naming convention for these variables as the
1772  /// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
1773  /// That is, `PathconfVar` variables have the same name as the abstract
1774  /// variables  shown in the `pathconf(2)` man page.  Usually, it's the same as
1775  /// the C variable name without the leading `_PC_`.
1776  ///
1777  /// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose
1778  /// not to implement variables that cannot change at runtime.
1779  ///
1780  /// # References
1781  ///
1782  /// - [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)
1783  /// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
1784  /// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
1785  #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1786  #[repr(i32)]
1787  pub enum PathconfVar {
1788      #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
1789                target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
1790      /// Minimum number of bits needed to represent, as a signed integer value,
1791      /// the maximum size of a regular file allowed in the specified directory.
1792      FILESIZEBITS = libc::_PC_FILESIZEBITS,
1793      /// Maximum number of links to a single file.
1794      LINK_MAX = libc::_PC_LINK_MAX,
1795      /// Maximum number of bytes in a terminal canonical input line.
1796      MAX_CANON = libc::_PC_MAX_CANON,
1797      /// Minimum number of bytes for which space is available in a terminal input
1798      /// queue; therefore, the maximum number of bytes a conforming application
1799      /// may require to be typed as input before reading them.
1800      MAX_INPUT = libc::_PC_MAX_INPUT,
1801      /// Maximum number of bytes in a filename (not including the terminating
1802      /// null of a filename string).
1803      NAME_MAX = libc::_PC_NAME_MAX,
1804      /// Maximum number of bytes the implementation will store as a pathname in a
1805      /// user-supplied buffer of unspecified size, including the terminating null
1806      /// character. Minimum number the implementation will accept as the maximum
1807      /// number of bytes in a pathname.
1808      PATH_MAX = libc::_PC_PATH_MAX,
1809      /// Maximum number of bytes that is guaranteed to be atomic when writing to
1810      /// a pipe.
1811      PIPE_BUF = libc::_PC_PIPE_BUF,
1812      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux",
1813                target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
1814      /// Symbolic links can be created.
1815      POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
1816      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1817                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1818      /// Minimum number of bytes of storage actually allocated for any portion of
1819      /// a file.
1820      POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
1821      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1822                target_os = "linux", target_os = "openbsd"))]
1823      /// Recommended increment for file transfer sizes between the
1824      /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
1825      POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
1826      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1827                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1828      /// Maximum recommended file transfer size.
1829      POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
1830      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1831                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1832      /// Minimum recommended file transfer size.
1833      POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
1834      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1835                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1836      ///  Recommended file transfer buffer alignment.
1837      POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN,
1838      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1839                target_os = "linux", target_os = "netbsd", target_os = "openbsd",
1840                target_os = "redox"))]
1841      /// Maximum number of bytes in a symbolic link.
1842      SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
1843      /// The use of `chown` and `fchown` is restricted to a process with
1844      /// appropriate privileges, and to changing the group ID of a file only to
1845      /// the effective group ID of the process or to one of its supplementary
1846      /// group IDs.
1847      _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED,
1848      /// Pathname components longer than {NAME_MAX} generate an error.
1849      _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC,
1850      /// This symbol shall be defined to be the value of a character that shall
1851      /// disable terminal special character handling.
1852      _POSIX_VDISABLE = libc::_PC_VDISABLE,
1853      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1854                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1855      /// Asynchronous input or output operations may be performed for the
1856      /// associated file.
1857      _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
1858      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1859                target_os = "linux", target_os = "openbsd", target_os = "redox"))]
1860      /// Prioritized input or output operations may be performed for the
1861      /// associated file.
1862      _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
1863      #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
1864                target_os = "linux", target_os = "netbsd", target_os = "openbsd",
1865                target_os = "redox"))]
1866      /// Synchronized input or output operations may be performed for the
1867      /// associated file.
1868      _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
1869      #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
1870      /// The resolution in nanoseconds for all file timestamps.
1871      _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION
1872  }
1873  
1874  /// Like `pathconf`, but works with file descriptors instead of paths (see
1875  /// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
1876  ///
1877  /// # Parameters
1878  ///
1879  /// - `fd`:   The file descriptor whose variable should be interrogated
1880  /// - `var`:  The pathconf variable to lookup
1881  ///
1882  /// # Returns
1883  ///
1884  /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
1885  ///     implementation level (for option variables).  Implementation levels are
1886  ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
1887  /// - `Ok(None)`: the variable has no limit (for limit variables) or is
1888  ///     unsupported (for option variables)
1889  /// - `Err(x)`: an error occurred
fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>>1890  pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> {
1891      let raw = unsafe {
1892          Errno::clear();
1893          libc::fpathconf(fd, var as c_int)
1894      };
1895      if raw == -1 {
1896          if errno::errno() == 0 {
1897              Ok(None)
1898          } else {
1899              Err(Error::Sys(Errno::last()))
1900          }
1901      } else {
1902          Ok(Some(raw))
1903      }
1904  }
1905  
1906  /// Get path-dependent configurable system variables (see
1907  /// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
1908  ///
1909  /// Returns the value of a path-dependent configurable system variable.  Most
1910  /// supported variables also have associated compile-time constants, but POSIX
1911  /// allows their values to change at runtime.  There are generally two types of
1912  /// `pathconf` variables: options and limits.  See [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
1913  ///
1914  /// # Parameters
1915  ///
1916  /// - `path`: Lookup the value of `var` for this file or directory
1917  /// - `var`:  The `pathconf` variable to lookup
1918  ///
1919  /// # Returns
1920  ///
1921  /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
1922  ///     implementation level (for option variables).  Implementation levels are
1923  ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
1924  /// - `Ok(None)`: the variable has no limit (for limit variables) or is
1925  ///     unsupported (for option variables)
1926  /// - `Err(x)`: an error occurred
pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>>1927  pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>> {
1928      let raw = path.with_nix_path(|cstr| {
1929          unsafe {
1930              Errno::clear();
1931              libc::pathconf(cstr.as_ptr(), var as c_int)
1932          }
1933      })?;
1934      if raw == -1 {
1935          if errno::errno() == 0 {
1936              Ok(None)
1937          } else {
1938              Err(Error::Sys(Errno::last()))
1939          }
1940      } else {
1941          Ok(Some(raw))
1942      }
1943  }
1944  
1945  /// Variable names for `sysconf`
1946  ///
1947  /// Nix uses the same naming convention for these variables as the
1948  /// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
1949  /// That is, `SysconfVar` variables have the same name as the abstract variables
1950  /// shown in the `sysconf(3)` man page.  Usually, it's the same as the C
1951  /// variable name without the leading `_SC_`.
1952  ///
1953  /// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been
1954  /// implemented by all platforms.
1955  ///
1956  /// # References
1957  ///
1958  /// - [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)
1959  /// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
1960  /// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
1961  #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1962  #[repr(i32)]
1963  pub enum SysconfVar {
1964      /// Maximum number of I/O operations in a single list I/O call supported by
1965      /// the implementation.
1966      #[cfg(not(target_os = "redox"))]
1967      AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
1968      /// Maximum number of outstanding asynchronous I/O operations supported by
1969      /// the implementation.
1970      #[cfg(not(target_os = "redox"))]
1971      AIO_MAX = libc::_SC_AIO_MAX,
1972      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
1973                target_os = "ios", target_os="linux", target_os = "macos",
1974                target_os="openbsd"))]
1975      /// The maximum amount by which a process can decrease its asynchronous I/O
1976      /// priority level from its own scheduling priority.
1977      AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
1978      /// Maximum length of argument to the exec functions including environment data.
1979      ARG_MAX = libc::_SC_ARG_MAX,
1980      /// Maximum number of functions that may be registered with `atexit`.
1981      #[cfg(not(target_os = "redox"))]
1982      ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
1983      /// Maximum obase values allowed by the bc utility.
1984      #[cfg(not(target_os = "redox"))]
1985      BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
1986      /// Maximum number of elements permitted in an array by the bc utility.
1987      #[cfg(not(target_os = "redox"))]
1988      BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
1989      /// Maximum scale value allowed by the bc utility.
1990      #[cfg(not(target_os = "redox"))]
1991      BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
1992      /// Maximum length of a string constant accepted by the bc utility.
1993      #[cfg(not(target_os = "redox"))]
1994      BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
1995      /// Maximum number of simultaneous processes per real user ID.
1996      CHILD_MAX = libc::_SC_CHILD_MAX,
1997      // The number of clock ticks per second.
1998      CLK_TCK = libc::_SC_CLK_TCK,
1999      /// Maximum number of weights that can be assigned to an entry of the
2000      /// LC_COLLATE order keyword in the locale definition file
2001      #[cfg(not(target_os = "redox"))]
2002      COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
2003      /// Maximum number of timer expiration overruns.
2004      #[cfg(not(target_os = "redox"))]
2005      DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
2006      /// Maximum number of expressions that can be nested within parentheses by
2007      /// the expr utility.
2008      #[cfg(not(target_os = "redox"))]
2009      EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX,
2010      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2011                target_os="linux", target_os = "macos", target_os="netbsd",
2012                target_os="openbsd"))]
2013      /// Maximum length of a host name (not including the terminating null) as
2014      /// returned from the `gethostname` function
2015      HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
2016      /// Maximum number of iovec structures that one process has available for
2017      /// use with `readv` or `writev`.
2018      #[cfg(not(target_os = "redox"))]
2019      IOV_MAX = libc::_SC_IOV_MAX,
2020      /// Unless otherwise noted, the maximum length, in bytes, of a utility's
2021      /// input line (either standard input or another file), when the utility is
2022      /// described as processing text files. The length includes room for the
2023      /// trailing <newline>.
2024      #[cfg(not(target_os = "redox"))]
2025      LINE_MAX = libc::_SC_LINE_MAX,
2026      /// Maximum length of a login name.
2027      LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
2028      /// Maximum number of simultaneous supplementary group IDs per process.
2029      NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
2030      /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
2031      #[cfg(not(target_os = "redox"))]
2032      GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
2033      /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
2034      #[cfg(not(target_os = "redox"))]
2035      GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
2036      /// The maximum number of open message queue descriptors a process may hold.
2037      #[cfg(not(target_os = "redox"))]
2038      MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
2039      /// The maximum number of message priorities supported by the implementation.
2040      #[cfg(not(target_os = "redox"))]
2041      MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
2042      /// A value one greater than the maximum value that the system may assign to
2043      /// a newly-created file descriptor.
2044      OPEN_MAX = libc::_SC_OPEN_MAX,
2045      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2046                target_os="linux", target_os = "macos", target_os="openbsd"))]
2047      /// The implementation supports the Advisory Information option.
2048      _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO,
2049      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2050                target_os="linux", target_os = "macos", target_os="netbsd",
2051                target_os="openbsd"))]
2052      /// The implementation supports barriers.
2053      _POSIX_BARRIERS = libc::_SC_BARRIERS,
2054      /// The implementation supports asynchronous input and output.
2055      #[cfg(not(target_os = "redox"))]
2056      _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO,
2057      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2058                target_os="linux", target_os = "macos", target_os="netbsd",
2059                target_os="openbsd"))]
2060      /// The implementation supports clock selection.
2061      _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
2062      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2063                target_os="linux", target_os = "macos", target_os="netbsd",
2064                target_os="openbsd"))]
2065      /// The implementation supports the Process CPU-Time Clocks option.
2066      _POSIX_CPUTIME = libc::_SC_CPUTIME,
2067      /// The implementation supports the File Synchronization option.
2068      #[cfg(not(target_os = "redox"))]
2069      _POSIX_FSYNC = libc::_SC_FSYNC,
2070      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2071                target_os="linux", target_os = "macos", target_os="openbsd"))]
2072      /// The implementation supports the IPv6 option.
2073      _POSIX_IPV6 = libc::_SC_IPV6,
2074      /// The implementation supports job control.
2075      #[cfg(not(target_os = "redox"))]
2076      _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
2077      /// The implementation supports memory mapped Files.
2078      #[cfg(not(target_os = "redox"))]
2079      _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
2080      /// The implementation supports the Process Memory Locking option.
2081      #[cfg(not(target_os = "redox"))]
2082      _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
2083      /// The implementation supports the Range Memory Locking option.
2084      #[cfg(not(target_os = "redox"))]
2085      _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
2086      /// The implementation supports memory protection.
2087      #[cfg(not(target_os = "redox"))]
2088      _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
2089      /// The implementation supports the Message Passing option.
2090      #[cfg(not(target_os = "redox"))]
2091      _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
2092      /// The implementation supports the Monotonic Clock option.
2093      #[cfg(not(target_os = "redox"))]
2094      _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK,
2095      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2096                target_os = "ios", target_os="linux", target_os = "macos",
2097                target_os="openbsd"))]
2098      /// The implementation supports the Prioritized Input and Output option.
2099      _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
2100      /// The implementation supports the Process Scheduling option.
2101      #[cfg(not(target_os = "redox"))]
2102      _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING,
2103      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2104                target_os="linux", target_os = "macos", target_os="openbsd"))]
2105      /// The implementation supports the Raw Sockets option.
2106      _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
2107      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2108                target_os="linux", target_os = "macos", target_os="netbsd",
2109                target_os="openbsd"))]
2110      /// The implementation supports read-write locks.
2111      _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS,
2112      #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
2113                target_os = "ios", target_os="linux", target_os = "macos",
2114                target_os = "openbsd"))]
2115      /// The implementation supports realtime signals.
2116      _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS,
2117      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2118                target_os="linux", target_os = "macos", target_os="netbsd",
2119                target_os="openbsd"))]
2120      /// The implementation supports the Regular Expression Handling option.
2121      _POSIX_REGEXP = libc::_SC_REGEXP,
2122      /// Each process has a saved set-user-ID and a saved set-group-ID.
2123      #[cfg(not(target_os = "redox"))]
2124      _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
2125      /// The implementation supports semaphores.
2126      #[cfg(not(target_os = "redox"))]
2127      _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
2128      /// The implementation supports the Shared Memory Objects option.
2129      #[cfg(not(target_os = "redox"))]
2130      _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
2131      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2132                target_os="linux", target_os = "macos", target_os="netbsd",
2133                target_os="openbsd"))]
2134      /// The implementation supports the POSIX shell.
2135      _POSIX_SHELL = libc::_SC_SHELL,
2136      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2137                target_os="linux", target_os = "macos", target_os="netbsd",
2138                target_os="openbsd"))]
2139      /// The implementation supports the Spawn option.
2140      _POSIX_SPAWN = libc::_SC_SPAWN,
2141      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2142                target_os="linux", target_os = "macos", target_os="netbsd",
2143                target_os="openbsd"))]
2144      /// The implementation supports spin locks.
2145      _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
2146      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2147                target_os="linux", target_os = "macos", target_os="openbsd"))]
2148      /// The implementation supports the Process Sporadic Server option.
2149      _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
2150      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2151                target_os="openbsd"))]
2152      _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
2153      /// The implementation supports the Synchronized Input and Output option.
2154      #[cfg(not(target_os = "redox"))]
2155      _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
2156      /// The implementation supports the Thread Stack Address Attribute option.
2157      #[cfg(not(target_os = "redox"))]
2158      _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
2159      /// The implementation supports the Thread Stack Size Attribute option.
2160      #[cfg(not(target_os = "redox"))]
2161      _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
2162      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2163                target_os="netbsd", target_os="openbsd"))]
2164      /// The implementation supports the Thread CPU-Time Clocks option.
2165      _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
2166      /// The implementation supports the Non-Robust Mutex Priority Inheritance
2167      /// option.
2168      #[cfg(not(target_os = "redox"))]
2169      _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
2170      /// The implementation supports the Non-Robust Mutex Priority Protection option.
2171      #[cfg(not(target_os = "redox"))]
2172      _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
2173      /// The implementation supports the Thread Execution Scheduling option.
2174      #[cfg(not(target_os = "redox"))]
2175      _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
2176      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2177                target_os="linux", target_os = "macos", target_os="netbsd",
2178                target_os="openbsd"))]
2179      /// The implementation supports the Thread Process-Shared Synchronization
2180      /// option.
2181      _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
2182      #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
2183      /// The implementation supports the Robust Mutex Priority Inheritance option.
2184      _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
2185      #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
2186      /// The implementation supports the Robust Mutex Priority Protection option.
2187      _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
2188      /// The implementation supports thread-safe functions.
2189      #[cfg(not(target_os = "redox"))]
2190      _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
2191      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2192                target_os="linux", target_os = "macos", target_os="openbsd"))]
2193      /// The implementation supports the Thread Sporadic Server option.
2194      _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
2195      /// The implementation supports threads.
2196      #[cfg(not(target_os = "redox"))]
2197      _POSIX_THREADS = libc::_SC_THREADS,
2198      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2199                target_os="linux", target_os = "macos", target_os="openbsd"))]
2200      /// The implementation supports timeouts.
2201      _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
2202      /// The implementation supports timers.
2203      #[cfg(not(target_os = "redox"))]
2204      _POSIX_TIMERS = libc::_SC_TIMERS,
2205      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2206                target_os="linux", target_os = "macos", target_os="openbsd"))]
2207      /// The implementation supports the Trace option.
2208      _POSIX_TRACE = libc::_SC_TRACE,
2209      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2210                target_os="linux", target_os = "macos", target_os="openbsd"))]
2211      /// The implementation supports the Trace Event Filter option.
2212      _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
2213      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2214                target_os="openbsd"))]
2215      _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
2216      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2217                target_os="linux", target_os = "macos", target_os="openbsd"))]
2218      /// The implementation supports the Trace Inherit option.
2219      _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
2220      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2221                target_os="linux", target_os = "macos", target_os="openbsd"))]
2222      /// The implementation supports the Trace Log option.
2223      _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
2224      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2225                target_os="openbsd"))]
2226      _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
2227      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2228                target_os="openbsd"))]
2229      _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
2230      #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
2231                target_os="openbsd"))]
2232      _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
2233      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2234                target_os="linux", target_os = "macos", target_os="openbsd"))]
2235      /// The implementation supports the Typed Memory Objects option.
2236      _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
2237      /// Integer value indicating version of this standard (C-language binding)
2238      /// to which the implementation conforms. For implementations conforming to
2239      /// POSIX.1-2008, the value shall be 200809L.
2240      _POSIX_VERSION = libc::_SC_VERSION,
2241      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2242                target_os="linux", target_os = "macos", target_os="netbsd",
2243                target_os="openbsd"))]
2244      /// The implementation provides a C-language compilation environment with
2245      /// 32-bit `int`, `long`, `pointer`, and `off_t` types.
2246      _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
2247      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2248                target_os="linux", target_os = "macos", target_os="netbsd",
2249                target_os="openbsd"))]
2250      /// The implementation provides a C-language compilation environment with
2251      /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
2252      /// least 64 bits.
2253      _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
2254      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2255                target_os="linux", target_os = "macos", target_os="netbsd",
2256                target_os="openbsd"))]
2257      /// The implementation provides a C-language compilation environment with
2258      /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
2259      _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
2260      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2261                target_os="linux", target_os = "macos", target_os="netbsd",
2262                target_os="openbsd"))]
2263      /// The implementation provides a C-language compilation environment with an
2264      /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
2265      /// using at least 64 bits.
2266      _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
2267      /// The implementation supports the C-Language Binding option.
2268      #[cfg(not(target_os = "redox"))]
2269      _POSIX2_C_BIND = libc::_SC_2_C_BIND,
2270      /// The implementation supports the C-Language Development Utilities option.
2271      #[cfg(not(target_os = "redox"))]
2272      _POSIX2_C_DEV = libc::_SC_2_C_DEV,
2273      /// The implementation supports the Terminal Characteristics option.
2274      #[cfg(not(target_os = "redox"))]
2275      _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
2276      /// The implementation supports the FORTRAN Development Utilities option.
2277      #[cfg(not(target_os = "redox"))]
2278      _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
2279      /// The implementation supports the FORTRAN Runtime Utilities option.
2280      #[cfg(not(target_os = "redox"))]
2281      _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
2282      /// The implementation supports the creation of locales by the localedef
2283      /// utility.
2284      #[cfg(not(target_os = "redox"))]
2285      _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
2286      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2287                target_os="linux", target_os = "macos", target_os="netbsd",
2288                target_os="openbsd"))]
2289      /// The implementation supports the Batch Environment Services and Utilities
2290      /// option.
2291      _POSIX2_PBS = libc::_SC_2_PBS,
2292      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2293                target_os="linux", target_os = "macos", target_os="netbsd",
2294                target_os="openbsd"))]
2295      /// The implementation supports the Batch Accounting option.
2296      _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
2297      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2298                target_os="linux", target_os = "macos", target_os="netbsd",
2299                target_os="openbsd"))]
2300      /// The implementation supports the Batch Checkpoint/Restart option.
2301      _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
2302      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2303                target_os="linux", target_os = "macos", target_os="netbsd",
2304                target_os="openbsd"))]
2305      /// The implementation supports the Locate Batch Job Request option.
2306      _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
2307      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2308                target_os="linux", target_os = "macos", target_os="netbsd",
2309                target_os="openbsd"))]
2310      /// The implementation supports the Batch Job Message Request option.
2311      _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
2312      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2313                target_os="linux", target_os = "macos", target_os="netbsd",
2314                target_os="openbsd"))]
2315      /// The implementation supports the Track Batch Job Request option.
2316      _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
2317      /// The implementation supports the Software Development Utilities option.
2318      #[cfg(not(target_os = "redox"))]
2319      _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
2320      /// The implementation supports the User Portability Utilities option.
2321      #[cfg(not(target_os = "redox"))]
2322      _POSIX2_UPE = libc::_SC_2_UPE,
2323      /// Integer value indicating version of the Shell and Utilities volume of
2324      /// POSIX.1 to which the implementation conforms.
2325      #[cfg(not(target_os = "redox"))]
2326      _POSIX2_VERSION = libc::_SC_2_VERSION,
2327      /// The size of a system page in bytes.
2328      ///
2329      /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
2330      /// enum constants to have the same value, so nix omits `PAGESIZE`.
2331      PAGE_SIZE = libc::_SC_PAGE_SIZE,
2332      #[cfg(not(target_os = "redox"))]
2333      PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
2334      #[cfg(not(target_os = "redox"))]
2335      PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
2336      #[cfg(not(target_os = "redox"))]
2337      PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
2338      #[cfg(not(target_os = "redox"))]
2339      PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
2340      RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
2341      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2342                target_os = "ios", target_os="linux", target_os = "macos",
2343                target_os="openbsd"))]
2344      RTSIG_MAX = libc::_SC_RTSIG_MAX,
2345      #[cfg(not(target_os = "redox"))]
2346      SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
2347      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2348                target_os = "ios", target_os="linux", target_os = "macos",
2349                target_os="openbsd"))]
2350      SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
2351      #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
2352                target_os = "ios", target_os="linux", target_os = "macos",
2353                target_os = "openbsd"))]
2354      SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
2355      STREAM_MAX = libc::_SC_STREAM_MAX,
2356      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2357                target_os="linux", target_os = "macos", target_os="netbsd",
2358                target_os="openbsd"))]
2359      SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
2360      #[cfg(not(target_os = "redox"))]
2361      TIMER_MAX = libc::_SC_TIMER_MAX,
2362      TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
2363      TZNAME_MAX = libc::_SC_TZNAME_MAX,
2364      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2365                target_os = "ios", target_os="linux", target_os = "macos",
2366                target_os="openbsd"))]
2367      /// The implementation supports the X/Open Encryption Option Group.
2368      _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
2369      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2370                target_os = "ios", target_os="linux", target_os = "macos",
2371                target_os="openbsd"))]
2372      /// The implementation supports the Issue 4, Version 2 Enhanced
2373      /// Internationalization Option Group.
2374      _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
2375      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2376                target_os = "ios", target_os="linux", target_os = "macos",
2377                target_os="openbsd"))]
2378      _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
2379      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2380                target_os = "ios", target_os="linux", target_os = "macos",
2381                target_os="openbsd"))]
2382      /// The implementation supports the X/Open Realtime Option Group.
2383      _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
2384      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2385                target_os = "ios", target_os="linux", target_os = "macos",
2386                target_os="openbsd"))]
2387      /// The implementation supports the X/Open Realtime Threads Option Group.
2388      _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
2389      /// The implementation supports the Issue 4, Version 2 Shared Memory Option
2390      /// Group.
2391      #[cfg(not(target_os = "redox"))]
2392      _XOPEN_SHM = libc::_SC_XOPEN_SHM,
2393      #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
2394                target_os="linux", target_os = "macos", target_os="openbsd"))]
2395      /// The implementation supports the XSI STREAMS Option Group.
2396      _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
2397      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2398                target_os = "ios", target_os="linux", target_os = "macos",
2399                target_os="openbsd"))]
2400      /// The implementation supports the XSI option
2401      _XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
2402      #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
2403                target_os = "ios", target_os="linux", target_os = "macos",
2404                target_os="openbsd"))]
2405      /// Integer value indicating version of the X/Open Portability Guide to
2406      /// which the implementation conforms.
2407      _XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
2408  }
2409  
2410  /// Get configurable system variables (see
2411  /// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
2412  ///
2413  /// Returns the value of a configurable system variable.  Most supported
2414  /// variables also have associated compile-time constants, but POSIX
2415  /// allows their values to change at runtime.  There are generally two types of
2416  /// sysconf variables: options and limits.  See sysconf(3) for more details.
2417  ///
2418  /// # Returns
2419  ///
2420  /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
2421  ///     implementation level (for option variables).  Implementation levels are
2422  ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
2423  /// - `Ok(None)`: the variable has no limit (for limit variables) or is
2424  ///     unsupported (for option variables)
2425  /// - `Err(x)`: an error occurred
sysconf(var: SysconfVar) -> Result<Option<c_long>>2426  pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
2427      let raw = unsafe {
2428          Errno::clear();
2429          libc::sysconf(var as c_int)
2430      };
2431      if raw == -1 {
2432          if errno::errno() == 0 {
2433              Ok(None)
2434          } else {
2435              Err(Error::Sys(Errno::last()))
2436          }
2437      } else {
2438          Ok(Some(raw))
2439      }
2440  }
2441  
2442  #[cfg(any(target_os = "android", target_os = "linux"))]
2443  mod pivot_root {
2444      use crate::{Result, NixPath};
2445      use crate::errno::Errno;
2446  
pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>( new_root: &P1, put_old: &P2) -> Result<()>2447      pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
2448              new_root: &P1, put_old: &P2) -> Result<()> {
2449          let res = new_root.with_nix_path(|new_root| {
2450              put_old.with_nix_path(|put_old| {
2451                  unsafe {
2452                      libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr())
2453                  }
2454              })
2455          })??;
2456  
2457          Errno::result(res).map(drop)
2458      }
2459  }
2460  
2461  #[cfg(any(target_os = "android", target_os = "freebsd",
2462            target_os = "linux", target_os = "openbsd"))]
2463  mod setres {
2464      use crate::Result;
2465      use crate::errno::Errno;
2466      use super::{Uid, Gid};
2467  
2468      /// Sets the real, effective, and saved uid.
2469      /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
2470      ///
2471      /// * `ruid`: real user id
2472      /// * `euid`: effective user id
2473      /// * `suid`: saved user id
2474      /// * returns: Ok or libc error code.
2475      ///
2476      /// Err is returned if the user doesn't have permission to set this UID.
2477      #[inline]
setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()>2478      pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
2479          let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
2480  
2481          Errno::result(res).map(drop)
2482      }
2483  
2484      /// Sets the real, effective, and saved gid.
2485      /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
2486      ///
2487      /// * `rgid`: real group id
2488      /// * `egid`: effective group id
2489      /// * `sgid`: saved group id
2490      /// * returns: Ok or libc error code.
2491      ///
2492      /// Err is returned if the user doesn't have permission to set this GID.
2493      #[inline]
setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()>2494      pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
2495          let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
2496  
2497          Errno::result(res).map(drop)
2498      }
2499  }
2500  
2501  libc_bitflags!{
2502      /// Options for access()
2503      pub struct AccessFlags : c_int {
2504          /// Test for existence of file.
2505          F_OK;
2506          /// Test for read permission.
2507          R_OK;
2508          /// Test for write permission.
2509          W_OK;
2510          /// Test for execute (search) permission.
2511          X_OK;
2512      }
2513  }
2514  
2515  /// Checks the file named by `path` for accessibility according to the flags given by `amode`
2516  /// See [access(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()>2517  pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
2518      let res = path.with_nix_path(|cstr| {
2519          unsafe {
2520              libc::access(cstr.as_ptr(), amode.bits)
2521          }
2522      })?;
2523      Errno::result(res).map(drop)
2524  }
2525  
2526  /// Representation of a User, based on `libc::passwd`
2527  ///
2528  /// The reason some fields in this struct are `String` and others are `CString` is because some
2529  /// fields are based on the user's locale, which could be non-UTF8, while other fields are
2530  /// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only
2531  /// contains ASCII.
2532  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2533  #[derive(Debug, Clone, PartialEq)]
2534  pub struct User {
2535      /// Username
2536      pub name: String,
2537      /// User password (probably encrypted)
2538      pub passwd: CString,
2539      /// User ID
2540      pub uid: Uid,
2541      /// Group ID
2542      pub gid: Gid,
2543      /// User information
2544      #[cfg(not(target_os = "android"))]
2545      pub gecos: CString,
2546      /// Home directory
2547      pub dir: PathBuf,
2548      /// Path to shell
2549      pub shell: PathBuf,
2550      /// Login class
2551      #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2552                    target_os = "linux")))]
2553      pub class: CString,
2554      /// Last password change
2555      #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2556                    target_os = "linux")))]
2557      pub change: libc::time_t,
2558      /// Expiration time of account
2559      #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2560                    target_os = "linux")))]
2561      pub expire: libc::time_t
2562  }
2563  
2564  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2565  impl From<&libc::passwd> for User {
from(pw: &libc::passwd) -> User2566      fn from(pw: &libc::passwd) -> User {
2567          unsafe {
2568              User {
2569                  name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
2570                  passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
2571                  #[cfg(not(target_os = "android"))]
2572                  gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
2573                  dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
2574                  shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
2575                  uid: Uid::from_raw((*pw).pw_uid),
2576                  gid: Gid::from_raw((*pw).pw_gid),
2577                  #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2578                                target_os = "linux")))]
2579                  class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
2580                  #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2581                                target_os = "linux")))]
2582                  change: (*pw).pw_change,
2583                  #[cfg(not(any(target_os = "android", target_os = "fuchsia",
2584                                target_os = "linux")))]
2585                  expire: (*pw).pw_expire
2586              }
2587          }
2588      }
2589  }
2590  
2591  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2592  impl User {
from_anything<F>(f: F) -> Result<Option<Self>> where F: Fn(*mut libc::passwd, *mut libc::c_char, libc::size_t, *mut *mut libc::passwd) -> libc::c_int2593      fn from_anything<F>(f: F) -> Result<Option<Self>>
2594      where
2595          F: Fn(*mut libc::passwd,
2596                *mut libc::c_char,
2597                libc::size_t,
2598                *mut *mut libc::passwd) -> libc::c_int
2599      {
2600          let buflimit = 16384;
2601          let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
2602              Ok(Some(n)) => n as usize,
2603              Ok(None) | Err(_) => buflimit as usize,
2604          };
2605  
2606          let mut cbuf = Vec::with_capacity(bufsize);
2607          let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
2608          let mut res = ptr::null_mut();
2609  
2610          loop {
2611              let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
2612              if error == 0 {
2613                  if res.is_null() {
2614                      return Ok(None);
2615                  } else {
2616                      let pwd = unsafe { pwd.assume_init() };
2617                      return Ok(Some(User::from(&pwd)));
2618                  }
2619              } else if Errno::last() == Errno::ERANGE {
2620                  // Trigger the internal buffer resizing logic.
2621                  reserve_double_buffer_size(&mut cbuf, buflimit)?;
2622              } else {
2623                  return Err(Error::Sys(Errno::last()));
2624              }
2625          }
2626      }
2627  
2628      /// Get a user by UID.
2629      ///
2630      /// Internally, this function calls
2631      /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2632      ///
2633      /// # Examples
2634      ///
2635      /// ```
2636      /// use nix::unistd::{Uid, User};
2637      /// // Returns an Result<Option<User>>, thus the double unwrap.
2638      /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
2639      /// assert!(res.name == "root");
2640      /// ```
from_uid(uid: Uid) -> Result<Option<Self>>2641      pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
2642          User::from_anything(|pwd, cbuf, cap, res| {
2643              unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) }
2644          })
2645      }
2646  
2647      /// Get a user by name.
2648      ///
2649      /// Internally, this function calls
2650      /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2651      ///
2652      /// # Examples
2653      ///
2654      /// ```
2655      /// use nix::unistd::User;
2656      /// // Returns an Result<Option<User>>, thus the double unwrap.
2657      /// let res = User::from_name("root").unwrap().unwrap();
2658      /// assert!(res.name == "root");
2659      /// ```
from_name(name: &str) -> Result<Option<Self>>2660      pub fn from_name(name: &str) -> Result<Option<Self>> {
2661          let name = CString::new(name).unwrap();
2662          User::from_anything(|pwd, cbuf, cap, res| {
2663              unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
2664          })
2665      }
2666  }
2667  
2668  /// Representation of a Group, based on `libc::group`
2669  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2670  #[derive(Debug, Clone, PartialEq)]
2671  pub struct Group {
2672      /// Group name
2673      pub name: String,
2674      /// Group password
2675      pub passwd: CString,
2676      /// Group ID
2677      pub gid: Gid,
2678      /// List of Group members
2679      pub mem: Vec<String>
2680  }
2681  
2682  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2683  impl From<&libc::group> for Group {
from(gr: &libc::group) -> Group2684      fn from(gr: &libc::group) -> Group {
2685          unsafe {
2686              Group {
2687                  name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(),
2688                  passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(),
2689                  gid: Gid::from_raw((*gr).gr_gid),
2690                  mem: Group::members((*gr).gr_mem)
2691              }
2692          }
2693      }
2694  }
2695  
2696  #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2697  impl Group {
members(mem: *mut *mut c_char) -> Vec<String>2698      unsafe fn members(mem: *mut *mut c_char) -> Vec<String> {
2699          let mut ret = Vec::new();
2700  
2701          for i in 0.. {
2702              let u = mem.offset(i);
2703              if (*u).is_null() {
2704                  break;
2705              } else {
2706                  let s = CStr::from_ptr(*u).to_string_lossy().into_owned();
2707                  ret.push(s);
2708              }
2709          }
2710  
2711          ret
2712      }
2713  
from_anything<F>(f: F) -> Result<Option<Self>> where F: Fn(*mut libc::group, *mut libc::c_char, libc::size_t, *mut *mut libc::group) -> libc::c_int2714      fn from_anything<F>(f: F) -> Result<Option<Self>>
2715      where
2716          F: Fn(*mut libc::group,
2717                *mut libc::c_char,
2718                libc::size_t,
2719                *mut *mut libc::group) -> libc::c_int
2720      {
2721          let buflimit = 16384;
2722          let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
2723              Ok(Some(n)) => n as usize,
2724              Ok(None) | Err(_) => buflimit as usize,
2725          };
2726  
2727          let mut cbuf = Vec::with_capacity(bufsize);
2728          let mut grp = mem::MaybeUninit::<libc::group>::uninit();
2729          let mut res = ptr::null_mut();
2730  
2731          loop {
2732              let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
2733              if error == 0 {
2734                  if res.is_null() {
2735                      return Ok(None);
2736                  } else {
2737                      let grp = unsafe { grp.assume_init() };
2738                      return Ok(Some(Group::from(&grp)));
2739                  }
2740              } else if Errno::last() == Errno::ERANGE {
2741                  // Trigger the internal buffer resizing logic.
2742                  reserve_double_buffer_size(&mut cbuf, buflimit)?;
2743              } else {
2744                  return Err(Error::Sys(Errno::last()));
2745              }
2746          }
2747      }
2748  
2749      /// Get a group by GID.
2750      ///
2751      /// Internally, this function calls
2752      /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2753      ///
2754      /// # Examples
2755      ///
2756      // Disable this test on all OS except Linux as root group may not exist.
2757      #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
2758      #[cfg_attr(target_os = "linux", doc = " ```")]
2759      /// use nix::unistd::{Gid, Group};
2760      /// // Returns an Result<Option<Group>>, thus the double unwrap.
2761      /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
2762      /// assert!(res.name == "root");
2763      /// ```
from_gid(gid: Gid) -> Result<Option<Self>>2764      pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
2765          Group::from_anything(|grp, cbuf, cap, res| {
2766              unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) }
2767          })
2768      }
2769  
2770      /// Get a group by name.
2771      ///
2772      /// Internally, this function calls
2773      /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2774      ///
2775      /// # Examples
2776      ///
2777      // Disable this test on all OS except Linux as root group may not exist.
2778      #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
2779      #[cfg_attr(target_os = "linux", doc = " ```")]
2780      /// use nix::unistd::Group;
2781      /// // Returns an Result<Option<Group>>, thus the double unwrap.
2782      /// let res = Group::from_name("root").unwrap().unwrap();
2783      /// assert!(res.name == "root");
2784      /// ```
from_name(name: &str) -> Result<Option<Self>>2785      pub fn from_name(name: &str) -> Result<Option<Self>> {
2786          let name = CString::new(name).unwrap();
2787          Group::from_anything(|grp, cbuf, cap, res| {
2788              unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
2789          })
2790      }
2791  }
2792  
2793  /// Get the name of the terminal device that is open on file descriptor fd
2794  /// (see [`ttyname(3)`](http://man7.org/linux/man-pages/man3/ttyname.3.html)).
2795  #[cfg(not(target_os = "fuchsia"))]
ttyname(fd: RawFd) -> Result<PathBuf>2796  pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
2797      const PATH_MAX: usize = libc::PATH_MAX as usize;
2798      let mut buf = vec![0_u8; PATH_MAX];
2799      let c_buf = buf.as_mut_ptr() as *mut libc::c_char;
2800  
2801      let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
2802      if ret != 0 {
2803          return Err(Error::Sys(Errno::from_i32(ret)));
2804      }
2805  
2806      let nul = buf.iter().position(|c| *c == b'\0').unwrap();
2807      buf.truncate(nul);
2808      Ok(OsString::from_vec(buf).into())
2809  }
2810  
2811  /// Get the effective user ID and group ID associated with a Unix domain socket.
2812  ///
2813  /// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
2814  #[cfg(any(
2815      target_os = "macos",
2816      target_os = "ios",
2817      target_os = "freebsd",
2818      target_os = "openbsd",
2819      target_os = "netbsd",
2820      target_os = "dragonfly",
2821  ))]
getpeereid(fd: RawFd) -> Result<(Uid, Gid)>2822  pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
2823      let mut uid = 1;
2824      let mut gid = 1;
2825  
2826      let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
2827  
2828      Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
2829  }
2830