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