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