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