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