• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Safe wrappers around functions found in libc "unistd.h" header
2 
3 use crate::errno::Errno;
4 
5 #[cfg(any(
6     all(feature = "fs", not(target_os = "redox")),
7     all(feature = "process", linux_android)
8 ))]
9 use crate::fcntl::at_rawfd;
10 #[cfg(not(target_os = "redox"))]
11 #[cfg(feature = "fs")]
12 use crate::fcntl::AtFlags;
13 
14 #[cfg(feature = "fs")]
15 #[cfg(any(
16     linux_android,
17     freebsdlike,
18     solarish,
19     netbsdlike,
20     target_os = "emscripten",
21     target_os = "fuchsia",
22     target_os = "hurd",
23     target_os = "redox",
24 ))]
25 use crate::fcntl::OFlag;
26 #[cfg(all(feature = "fs", bsd))]
27 use crate::sys::stat::FileFlag;
28 #[cfg(feature = "fs")]
29 use crate::sys::stat::Mode;
30 use crate::{Error, NixPath, Result};
31 #[cfg(not(target_os = "redox"))]
32 use cfg_if::cfg_if;
33 use libc::{
34     c_char, c_int, c_long, c_uint, gid_t, mode_t, off_t, pid_t, size_t, uid_t,
35 };
36 use std::convert::Infallible;
37 #[cfg(not(target_os = "redox"))]
38 use std::ffi::CString;
39 use std::ffi::{CStr, OsStr, OsString};
40 use std::os::unix::ffi::{OsStrExt, OsStringExt};
41 use std::os::unix::io::{AsFd, AsRawFd, OwnedFd, RawFd};
42 use std::path::PathBuf;
43 use std::{fmt, mem, ptr};
44 
45 feature! {
46     #![feature = "fs"]
47     #[cfg(linux_android)]
48     pub use self::pivot_root::*;
49 }
50 
51 #[cfg(any(freebsdlike, linux_android, target_os = "openbsd"))]
52 pub use self::setres::*;
53 
54 #[cfg(any(freebsdlike, linux_android, target_os = "openbsd"))]
55 pub use self::getres::*;
56 
57 feature! {
58 #![feature = "user"]
59 
60 /// User identifier
61 ///
62 /// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
63 /// passing wrong value.
64 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
65 pub struct Uid(uid_t);
66 
67 impl Uid {
68     /// Creates `Uid` from raw `uid_t`.
69     pub const fn from_raw(uid: uid_t) -> Self {
70         Uid(uid)
71     }
72 
73     /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
74     #[doc(alias("getuid"))]
75     pub fn current() -> Self {
76         getuid()
77     }
78 
79     /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
80     #[doc(alias("geteuid"))]
81     pub fn effective() -> Self {
82         geteuid()
83     }
84 
85     /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
86     pub const fn is_root(self) -> bool {
87         self.0 == ROOT.0
88     }
89 
90     /// Get the raw `uid_t` wrapped by `self`.
91     pub const fn as_raw(self) -> uid_t {
92         self.0
93     }
94 }
95 
96 impl From<Uid> for uid_t {
97     fn from(uid: Uid) -> Self {
98         uid.0
99     }
100 }
101 
102 impl From<uid_t> for Uid {
103     fn from(uid: uid_t) -> Self {
104         Uid(uid)
105     }
106 }
107 
108 impl fmt::Display for Uid {
109     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110         fmt::Display::fmt(&self.0, f)
111     }
112 }
113 
114 /// Constant for UID = 0
115 pub const ROOT: Uid = Uid(0);
116 
117 /// Group identifier
118 ///
119 /// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally
120 /// passing wrong value.
121 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
122 pub struct Gid(gid_t);
123 
124 impl Gid {
125     /// Creates `Gid` from raw `gid_t`.
126     pub const fn from_raw(gid: gid_t) -> Self {
127         Gid(gid)
128     }
129 
130     /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
131     #[doc(alias("getgid"))]
132     pub fn current() -> Self {
133         getgid()
134     }
135 
136     /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
137     #[doc(alias("getegid"))]
138     pub fn effective() -> Self {
139         getegid()
140     }
141 
142     /// Get the raw `gid_t` wrapped by `self`.
143     pub const fn as_raw(self) -> gid_t {
144         self.0
145     }
146 }
147 
148 impl From<Gid> for gid_t {
149     fn from(gid: Gid) -> Self {
150         gid.0
151     }
152 }
153 
154 impl From<gid_t> for Gid {
155     fn from(gid: gid_t) -> Self {
156         Gid(gid)
157     }
158 }
159 
160 impl fmt::Display for Gid {
161     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162         fmt::Display::fmt(&self.0, f)
163     }
164 }
165 }
166 
167 feature! {
168 #![feature = "process"]
169 /// Process identifier
170 ///
171 /// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
172 /// passing wrong value.
173 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
174 pub struct Pid(pid_t);
175 
176 impl Pid {
177     /// Creates `Pid` from raw `pid_t`.
178     pub const fn from_raw(pid: pid_t) -> Self {
179         Pid(pid)
180     }
181 
182     /// Returns PID of calling process
183     #[doc(alias("getpid"))]
184     pub fn this() -> Self {
185         getpid()
186     }
187 
188     /// Returns PID of parent of calling process
189     #[doc(alias("getppid"))]
190     pub fn parent() -> Self {
191         getppid()
192     }
193 
194     /// Get the raw `pid_t` wrapped by `self`.
195     pub const fn as_raw(self) -> pid_t {
196         self.0
197     }
198 }
199 
200 impl From<Pid> for pid_t {
201     fn from(pid: Pid) -> Self {
202         pid.0
203     }
204 }
205 
206 impl fmt::Display for Pid {
207     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208         fmt::Display::fmt(&self.0, f)
209     }
210 }
211 
212 /// Represents the successful result of calling `fork`
213 ///
214 /// When `fork` is called, the process continues execution in the parent process
215 /// and in the new child.  This return type can be examined to determine whether
216 /// you are now executing in the parent process or in the child.
217 #[derive(Clone, Copy, Debug)]
218 pub enum ForkResult {
219     /// This is the parent process of the fork.
220     Parent {
221         /// The PID of the fork's child process
222         child: Pid
223     },
224     /// This is the child process of the fork.
225     Child,
226 }
227 
228 impl ForkResult {
229     /// Return `true` if this is the child process of the `fork()`
230     #[inline]
231     pub fn is_child(self) -> bool {
232         matches!(self, ForkResult::Child)
233     }
234 
235     /// Returns `true` if this is the parent process of the `fork()`
236     #[inline]
237     pub fn is_parent(self) -> bool {
238         !self.is_child()
239     }
240 }
241 
242 /// Create a new child process duplicating the parent process ([see
243 /// fork(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
244 ///
245 /// After successfully calling the fork system call, a second process will
246 /// be created which is identical to the original except for the pid and the
247 /// return value of this function.  As an example:
248 ///
249 /// ```
250 /// use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}};
251 ///
252 /// match unsafe{fork()} {
253 ///    Ok(ForkResult::Parent { child, .. }) => {
254 ///        println!("Continuing execution in parent process, new child has pid: {}", child);
255 ///        waitpid(child, None).unwrap();
256 ///    }
257 ///    Ok(ForkResult::Child) => {
258 ///        // Unsafe to use `println!` (or `unwrap`) here. See Safety.
259 ///        write(std::io::stdout(), "I'm a new child process\n".as_bytes()).ok();
260 ///        unsafe { libc::_exit(0) };
261 ///    }
262 ///    Err(_) => println!("Fork failed"),
263 /// }
264 /// ```
265 ///
266 /// This will print something like the following (order nondeterministic).  The
267 /// thing to note is that you end up with two processes continuing execution
268 /// immediately after the fork call but with different match arms.
269 ///
270 /// ```text
271 /// Continuing execution in parent process, new child has pid: 1234
272 /// I'm a new child process
273 /// ```
274 ///
275 /// # Safety
276 ///
277 /// In a multithreaded program, only [async-signal-safe] functions like `pause`
278 /// and `_exit` may be called by the child (the parent isn't restricted). Note
279 /// that memory allocation may **not** be async-signal-safe and thus must be
280 /// prevented.
281 ///
282 /// Those functions are only a small subset of your operating system's API, so
283 /// special care must be taken to only invoke code you can control and audit.
284 ///
285 /// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
286 #[inline]
287 pub unsafe fn fork() -> Result<ForkResult> {
288     use self::ForkResult::*;
289     let res = unsafe { libc::fork() };
290 
291     Errno::result(res).map(|res| match res {
292         0 => Child,
293         res => Parent { child: Pid(res) },
294     })
295 }
296 
297 /// Get the pid of this process (see
298 /// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
299 ///
300 /// Since you are running code, there is always a pid to return, so there
301 /// is no error case that needs to be handled.
302 #[inline]
303 pub fn getpid() -> Pid {
304     Pid(unsafe { libc::getpid() })
305 }
306 
307 /// Get the pid of this processes' parent (see
308 /// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
309 ///
310 /// There is always a parent pid to return, so there is no error case that needs
311 /// to be handled.
312 #[inline]
313 pub fn getppid() -> Pid {
314     Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful."
315 }
316 
317 /// Set a process group ID (see
318 /// [setpgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
319 ///
320 /// Set the process group id (PGID) of a particular process.  If a pid of zero
321 /// is specified, then the pid of the calling process is used.  Process groups
322 /// may be used to group together a set of processes in order for the OS to
323 /// apply some operations across the group.
324 ///
325 /// `setsid()` may be used to create a new process group.
326 #[inline]
327 pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
328     let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
329     Errno::result(res).map(drop)
330 }
331 /// Get process group
332 ///
333 /// See Also [`getpgid`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgid.html)
334 #[inline]
335 pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
336     let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
337     Errno::result(res).map(Pid)
338 }
339 
340 /// Create new session and set process group id (see
341 /// [setsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
342 #[inline]
343 pub fn setsid() -> Result<Pid> {
344     Errno::result(unsafe { libc::setsid() }).map(Pid)
345 }
346 
347 /// Get the process group ID of a session leader
348 /// [getsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
349 ///
350 /// Obtain the process group ID of the process that is the session leader of the process specified
351 /// by pid. If pid is zero, it specifies the calling process.
352 #[inline]
353 #[cfg(not(target_os = "redox"))]
354 pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
355     let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
356     Errno::result(res).map(Pid)
357 }
358 }
359 
360 feature! {
361 #![all(feature = "process", feature = "term")]
362 /// Get the terminal foreground process group (see
363 /// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
364 ///
365 /// Get the group process id (GPID) of the foreground process group on the
366 /// terminal associated to file descriptor (FD).
367 #[inline]
368 pub fn tcgetpgrp<F: AsFd>(fd: F) -> Result<Pid> {
369     let res = unsafe { libc::tcgetpgrp(fd.as_fd().as_raw_fd()) };
370     Errno::result(res).map(Pid)
371 }
372 /// Set the terminal foreground process group (see
373 /// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
374 ///
375 /// Get the group process id (PGID) to the foreground process group on the
376 /// terminal associated to file descriptor (FD).
377 #[inline]
378 pub fn tcsetpgrp<F: AsFd>(fd: F, pgrp: Pid) -> Result<()> {
379     let res = unsafe { libc::tcsetpgrp(fd.as_fd().as_raw_fd(), pgrp.into()) };
380     Errno::result(res).map(drop)
381 }
382 }
383 
384 feature! {
385 #![feature = "process"]
386 /// Get the group id of the calling process (see
387 ///[getpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
388 ///
389 /// Get the process group id (PGID) of the calling process.
390 /// According to the man page it is always successful.
391 #[inline]
392 pub fn getpgrp() -> Pid {
393     Pid(unsafe { libc::getpgrp() })
394 }
395 
396 /// Get the caller's thread ID (see
397 /// [gettid(2)](https://man7.org/linux/man-pages/man2/gettid.2.html).
398 ///
399 /// This function is only available on Linux based systems.  In a single
400 /// threaded process, the main thread will have the same ID as the process.  In
401 /// a multithreaded process, each thread will have a unique thread id but the
402 /// same process ID.
403 ///
404 /// No error handling is required as a thread id should always exist for any
405 /// process, even if threads are not being used.
406 #[cfg(linux_android)]
407 #[inline]
408 pub fn gettid() -> Pid {
409     Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
410 }
411 }
412 
413 feature! {
414 #![feature = "fs"]
415 /// Create a copy of the specified file descriptor (see
416 /// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
417 ///
418 /// The new file descriptor will have a new index but refer to the same
419 /// resource as the old file descriptor and the old and new file descriptors may
420 /// be used interchangeably.  The new and old file descriptor share the same
421 /// underlying resource, offset, and file status flags.  The actual index used
422 /// for the file descriptor will be the lowest fd index that is available.
423 ///
424 /// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`).
425 #[inline]
426 pub fn dup(oldfd: RawFd) -> Result<RawFd> {
427     let res = unsafe { libc::dup(oldfd) };
428 
429     Errno::result(res)
430 }
431 
432 /// Create a copy of the specified file descriptor using the specified fd (see
433 /// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
434 ///
435 /// This function behaves similar to `dup()` except that it will try to use the
436 /// specified fd instead of allocating a new one.  See the man pages for more
437 /// detail on the exact behavior of this function.
438 #[inline]
439 pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
440     let res = unsafe { libc::dup2(oldfd, newfd) };
441 
442     Errno::result(res)
443 }
444 
445 /// Create a new copy of the specified file descriptor using the specified fd
446 /// and flags (see [`dup(2)`](https://man7.org/linux/man-pages/man2/dup.2.html)).
447 ///
448 /// This function behaves similar to `dup2()` but allows for flags to be
449 /// specified.
450 #[cfg(any(
451     netbsdlike,
452     solarish,
453     target_os = "freebsd",
454     target_os = "fuchsia",
455     target_os = "hurd",
456     target_os = "linux"
457 ))]
458 pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
459     let res = unsafe { libc::dup3(oldfd, newfd, flags.bits()) };
460 
461     Errno::result(res)
462 }
463 
464 /// Change the current working directory of the calling process (see
465 /// [chdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
466 ///
467 /// This function may fail in a number of different scenarios.  See the man
468 /// pages for additional details on possible failure cases.
469 #[inline]
470 pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
471     let res =
472         path.with_nix_path(|cstr| unsafe { libc::chdir(cstr.as_ptr()) })?;
473 
474     Errno::result(res).map(drop)
475 }
476 
477 /// Change the current working directory of the process to the one
478 /// given as an open file descriptor (see
479 /// [fchdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
480 ///
481 /// This function may fail in a number of different scenarios.  See the man
482 /// pages for additional details on possible failure cases.
483 #[inline]
484 #[cfg(not(target_os = "fuchsia"))]
485 pub fn fchdir(dirfd: RawFd) -> Result<()> {
486     let res = unsafe { libc::fchdir(dirfd) };
487 
488     Errno::result(res).map(drop)
489 }
490 
491 /// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
492 ///
493 /// # Errors
494 ///
495 /// There are several situations where mkdir might fail:
496 ///
497 /// - current user has insufficient rights in the parent directory
498 /// - the path already exists
499 /// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
500 ///
501 /// # Example
502 ///
503 /// ```rust
504 /// use nix::unistd;
505 /// use nix::sys::stat;
506 /// use tempfile::tempdir;
507 ///
508 /// let tmp_dir1 = tempdir().unwrap();
509 /// let tmp_dir2 = tmp_dir1.path().join("new_dir");
510 ///
511 /// // create new directory and give read, write and execute rights to the owner
512 /// match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
513 ///    Ok(_) => println!("created {:?}", tmp_dir2),
514 ///    Err(err) => println!("Error creating directory: {}", err),
515 /// }
516 /// ```
517 #[inline]
518 pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
519     let res = path.with_nix_path(|cstr| unsafe {
520         libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t)
521     })?;
522 
523     Errno::result(res).map(drop)
524 }
525 
526 /// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
527 ///
528 /// # Errors
529 ///
530 /// There are several situations where mkfifo might fail:
531 ///
532 /// - current user has insufficient rights in the parent directory
533 /// - the path already exists
534 /// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
535 ///
536 /// For a full list consult
537 /// [posix specification](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
538 ///
539 /// # Example
540 ///
541 /// ```rust
542 /// use nix::unistd;
543 /// use nix::sys::stat;
544 /// use tempfile::tempdir;
545 ///
546 /// let tmp_dir = tempdir().unwrap();
547 /// let fifo_path = tmp_dir.path().join("foo.pipe");
548 ///
549 /// // create new fifo and give read, write and execute rights to the owner
550 /// match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
551 ///    Ok(_) => println!("created {:?}", fifo_path),
552 ///    Err(err) => println!("Error creating fifo: {}", err),
553 /// }
554 /// ```
555 #[inline]
556 #[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet
557 pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
558     let res = path.with_nix_path(|cstr| unsafe {
559         libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t)
560     })?;
561 
562     Errno::result(res).map(drop)
563 }
564 
565 /// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
566 ///
567 /// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
568 ///
569 /// If `dirfd` is `None`, then `path` is relative to the current working directory.
570 ///
571 /// # References
572 ///
573 /// [mkfifoat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
574 // mkfifoat is not implemented in OSX or android
575 #[inline]
576 #[cfg(not(any(
577     apple_targets,
578     target_os = "haiku",
579     target_os = "android",
580     target_os = "redox"
581 )))]
582 pub fn mkfifoat<P: ?Sized + NixPath>(
583     dirfd: Option<RawFd>,
584     path: &P,
585     mode: Mode,
586 ) -> Result<()> {
587     let res = path.with_nix_path(|cstr| unsafe {
588         libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t)
589     })?;
590 
591     Errno::result(res).map(drop)
592 }
593 
594 /// Creates a symbolic link at `path2` which points to `path1`.
595 ///
596 /// If `dirfd` has a value, then `path2` is relative to directory associated
597 /// with the file descriptor.
598 ///
599 /// If `dirfd` is `None`, then `path2` is relative to the current working
600 /// directory. This is identical to `libc::symlink(path1, path2)`.
601 ///
602 /// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
603 #[cfg(not(target_os = "redox"))]
604 pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
605     path1: &P1,
606     dirfd: Option<RawFd>,
607     path2: &P2,
608 ) -> Result<()> {
609     let res = path1.with_nix_path(|path1| {
610         path2.with_nix_path(|path2| unsafe {
611             libc::symlinkat(
612                 path1.as_ptr(),
613                 dirfd.unwrap_or(libc::AT_FDCWD),
614                 path2.as_ptr(),
615             )
616         })
617     })??;
618     Errno::result(res).map(drop)
619 }
620 }
621 
622 // Double the buffer capacity up to limit. In case it already has
623 // reached the limit, return Errno::ERANGE.
624 #[cfg(any(feature = "fs", feature = "user"))]
reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()>625 fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
626     use std::cmp::min;
627 
628     if buf.capacity() >= limit {
629         return Err(Errno::ERANGE);
630     }
631 
632     let capacity = min(buf.capacity() * 2, limit);
633     buf.reserve(capacity);
634 
635     Ok(())
636 }
637 
638 feature! {
639 #![feature = "fs"]
640 
641 /// Returns the current directory as a `PathBuf`
642 ///
643 /// Err is returned if the current user doesn't have the permission to read or search a component
644 /// of the current path.
645 ///
646 /// # Example
647 ///
648 /// ```rust
649 /// use nix::unistd;
650 ///
651 /// // assume that we are allowed to get current directory
652 /// let dir = unistd::getcwd().unwrap();
653 /// println!("The current directory is {:?}", dir);
654 /// ```
655 #[inline]
656 pub fn getcwd() -> Result<PathBuf> {
657     let mut buf = Vec::<u8>::with_capacity(512);
658     loop {
659         unsafe {
660             let ptr = buf.as_mut_ptr().cast();
661 
662             // The buffer must be large enough to store the absolute pathname plus
663             // a terminating null byte, or else null is returned.
664             // To safely handle this we start with a reasonable size (512 bytes)
665             // and double the buffer size upon every error
666             if !libc::getcwd(ptr, buf.capacity()).is_null() {
667                 let len = CStr::from_ptr(buf.as_ptr().cast())
668                     .to_bytes()
669                     .len();
670                 buf.set_len(len);
671                 buf.shrink_to_fit();
672                 return Ok(PathBuf::from(OsString::from_vec(buf)));
673             } else {
674                 let error = Errno::last();
675                 // ERANGE means buffer was too small to store directory name
676                 if error != Errno::ERANGE {
677                     return Err(error);
678                 }
679             }
680 
681             #[cfg(not(target_os = "hurd"))]
682             const PATH_MAX: usize = libc::PATH_MAX as usize;
683             #[cfg(target_os = "hurd")]
684             const PATH_MAX: usize = 1024; // Hurd does not define a hard limit, so try a guess first
685 
686             // Trigger the internal buffer resizing logic.
687             reserve_double_buffer_size(&mut buf, PATH_MAX)?;
688         }
689     }
690 }
691 }
692 
693 feature! {
694 #![all(feature = "user", feature = "fs")]
695 
696 /// Computes the raw UID and GID values to pass to a `*chown` call.
697 // The cast is not unnecessary on all platforms.
698 #[allow(clippy::unnecessary_cast)]
699 fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (uid_t, gid_t) {
700     // According to the POSIX specification, -1 is used to indicate that owner and group
701     // are not to be changed.  Since uid_t and gid_t are unsigned types, we have to wrap
702     // around to get -1.
703     let uid = owner
704         .map(Into::into)
705         .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1));
706     let gid = group
707         .map(Into::into)
708         .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1));
709     (uid, gid)
710 }
711 
712 /// Change the ownership of the file at `path` to be owned by the specified
713 /// `owner` (user) and `group` (see
714 /// [chown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
715 ///
716 /// The owner/group for the provided path name will not be modified if `None` is
717 /// provided for that argument.  Ownership change will be attempted for the path
718 /// only if `Some` owner/group is provided.
719 #[inline]
720 pub fn chown<P: ?Sized + NixPath>(
721     path: &P,
722     owner: Option<Uid>,
723     group: Option<Gid>,
724 ) -> Result<()> {
725     let res = path.with_nix_path(|cstr| {
726         let (uid, gid) = chown_raw_ids(owner, group);
727         unsafe { libc::chown(cstr.as_ptr(), uid, gid) }
728     })?;
729 
730     Errno::result(res).map(drop)
731 }
732 
733 /// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by
734 /// the specified `owner` (user) and `group` (see
735 /// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)).
736 ///
737 /// The owner/group for the provided file will not be modified if `None` is
738 /// provided for that argument.  Ownership change will be attempted for the path
739 /// only if `Some` owner/group is provided.
740 #[inline]
741 pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
742     let (uid, gid) = chown_raw_ids(owner, group);
743     let res = unsafe { libc::fchown(fd, uid, gid) };
744     Errno::result(res).map(drop)
745 }
746 
747 // Just a wrapper around `AtFlags` so that we can help our users migrate.
748 #[allow(missing_docs)]
749 #[cfg(not(target_os = "redox"))]
750 pub type FchownatFlags = AtFlags;
751 #[allow(missing_docs)]
752 #[cfg(not(target_os = "redox"))]
753 impl FchownatFlags {
754     #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
755     #[allow(non_upper_case_globals)]
756     pub const FollowSymlink: FchownatFlags = FchownatFlags::empty();
757     #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
758     #[allow(non_upper_case_globals)]
759     pub const NoFollowSymlink: FchownatFlags = FchownatFlags::AT_SYMLINK_NOFOLLOW;
760 }
761 
762 /// Change the ownership of the file at `path` to be owned by the specified
763 /// `owner` (user) and `group`.
764 ///
765 /// The owner/group for the provided path name will not be modified if `None` is
766 /// provided for that argument.  Ownership change will be attempted for the path
767 /// only if `Some` owner/group is provided.
768 ///
769 /// The file to be changed is determined relative to the directory associated
770 /// with the file descriptor `dirfd` or the current working directory
771 /// if `dirfd` is `None`.
772 ///
773 /// If `flag` is `AtFlags::AT_SYMLINK_NOFOLLOW` and `path` names a symbolic link,
774 /// then the mode of the symbolic link is changed.
775 ///
776 /// `fchownat(None, path, owner, group, AtFlags::AT_SYMLINK_NOFOLLOW)` is identical to
777 /// a call `libc::lchown(path, owner, group)`.  That's why `lchown` is unimplemented in
778 /// the `nix` crate.
779 ///
780 /// # References
781 ///
782 /// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
783 #[cfg(not(target_os = "redox"))]
784 pub fn fchownat<P: ?Sized + NixPath>(
785     dirfd: Option<RawFd>,
786     path: &P,
787     owner: Option<Uid>,
788     group: Option<Gid>,
789     flag: AtFlags,
790 ) -> Result<()> {
791     let res = path.with_nix_path(|cstr| unsafe {
792         let (uid, gid) = chown_raw_ids(owner, group);
793         libc::fchownat(
794             at_rawfd(dirfd),
795             cstr.as_ptr(),
796             uid,
797             gid,
798             flag.bits()
799         )
800     })?;
801 
802     Errno::result(res).map(drop)
803 }
804 }
805 
806 feature! {
807 #![feature = "process"]
808 fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
809     use std::iter::once;
810     args.iter()
811         .map(|s| s.as_ref().as_ptr())
812         .chain(once(ptr::null()))
813         .collect()
814 }
815 
816 /// Replace the current process image with a new one (see
817 /// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
818 ///
819 /// See the `::nix::unistd::execve` system call for additional details.  `execv`
820 /// performs the same action but does not allow for customization of the
821 /// environment for the new process.
822 #[inline]
823 pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
824     let args_p = to_exec_array(argv);
825 
826     unsafe { libc::execv(path.as_ptr(), args_p.as_ptr()) };
827 
828     Err(Errno::last())
829 }
830 
831 /// Replace the current process image with a new one (see
832 /// [execve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
833 ///
834 /// The execve system call allows for another process to be "called" which will
835 /// replace the current process image.  That is, this process becomes the new
836 /// command that is run. On success, this function will not return. Instead,
837 /// the new program will run until it exits.
838 ///
839 /// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
840 /// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
841 /// in the `args` list is an argument to the new process. Each element in the
842 /// `env` list should be a string in the form "key=value".
843 #[inline]
844 pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(
845     path: &CStr,
846     args: &[SA],
847     env: &[SE],
848 ) -> Result<Infallible> {
849     let args_p = to_exec_array(args);
850     let env_p = to_exec_array(env);
851 
852     unsafe { libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) };
853 
854     Err(Errno::last())
855 }
856 
857 /// Replace the current process image with a new one and replicate shell `PATH`
858 /// searching behavior (see
859 /// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
860 ///
861 /// See `::nix::unistd::execve` for additional details.  `execvp` behaves the
862 /// same as execv except that it will examine the `PATH` environment variables
863 /// for file names not specified with a leading slash.  For example, `execv`
864 /// would not work if "bash" was specified for the path argument, but `execvp`
865 /// would assuming that a bash executable was on the system `PATH`.
866 #[inline]
867 pub fn execvp<S: AsRef<CStr>>(
868     filename: &CStr,
869     args: &[S],
870 ) -> Result<Infallible> {
871     let args_p = to_exec_array(args);
872 
873     unsafe { libc::execvp(filename.as_ptr(), args_p.as_ptr()) };
874 
875     Err(Errno::last())
876 }
877 
878 /// Replace the current process image with a new one and replicate shell `PATH`
879 /// searching behavior (see
880 /// [`execvpe(3)`](https://man7.org/linux/man-pages/man3/exec.3.html)).
881 ///
882 /// This functions like a combination of `execvp(2)` and `execve(2)` to pass an
883 /// environment and have a search path. See these two for additional
884 /// information.
885 #[cfg(any(target_os = "haiku", target_os = "hurd", target_os = "linux", target_os = "openbsd"))]
886 pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(
887     filename: &CStr,
888     args: &[SA],
889     env: &[SE],
890 ) -> Result<Infallible> {
891     let args_p = to_exec_array(args);
892     let env_p = to_exec_array(env);
893 
894     unsafe {
895         libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
896     };
897 
898     Err(Errno::last())
899 }
900 
901 /// Replace the current process image with a new one (see
902 /// [fexecve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
903 ///
904 /// The `fexecve` function allows for another process to be "called" which will
905 /// replace the current process image.  That is, this process becomes the new
906 /// command that is run. On success, this function will not return. Instead,
907 /// the new program will run until it exits.
908 ///
909 /// This function is similar to `execve`, except that the program to be executed
910 /// is referenced as a file descriptor instead of a path.
911 #[cfg(any(linux_android, freebsdlike, target_os = "hurd"))]
912 #[inline]
913 pub fn fexecve<SA: AsRef<CStr>, SE: AsRef<CStr>>(
914     fd: RawFd,
915     args: &[SA],
916     env: &[SE],
917 ) -> Result<Infallible> {
918     let args_p = to_exec_array(args);
919     let env_p = to_exec_array(env);
920 
921     unsafe { libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr()) };
922 
923     Err(Errno::last())
924 }
925 
926 /// Execute program relative to a directory file descriptor (see
927 /// [execveat(2)](https://man7.org/linux/man-pages/man2/execveat.2.html)).
928 ///
929 /// The `execveat` function allows for another process to be "called" which will
930 /// replace the current process image.  That is, this process becomes the new
931 /// command that is run. On success, this function will not return. Instead,
932 /// the new program will run until it exits.
933 ///
934 /// This function is similar to `execve`, except that the program to be executed
935 /// is referenced as a file descriptor to the base directory plus a path.
936 #[cfg(linux_android)]
937 #[inline]
938 pub fn execveat<SA: AsRef<CStr>, SE: AsRef<CStr>>(
939     dirfd: Option<RawFd>,
940     pathname: &CStr,
941     args: &[SA],
942     env: &[SE],
943     flags: super::fcntl::AtFlags,
944 ) -> Result<Infallible> {
945     let dirfd = at_rawfd(dirfd);
946     let args_p = to_exec_array(args);
947     let env_p = to_exec_array(env);
948 
949     unsafe {
950         libc::syscall(
951             libc::SYS_execveat,
952             dirfd,
953             pathname.as_ptr(),
954             args_p.as_ptr(),
955             env_p.as_ptr(),
956             flags,
957         );
958     };
959 
960     Err(Errno::last())
961 }
962 
963 /// Daemonize this process by detaching from the controlling terminal (see
964 /// [daemon(3)](https://man7.org/linux/man-pages/man3/daemon.3.html)).
965 ///
966 /// When a process is launched it is typically associated with a parent and it,
967 /// in turn, by its controlling terminal/process.  In order for a process to run
968 /// in the "background" it must daemonize itself by detaching itself.  Under
969 /// posix, this is done by doing the following:
970 ///
971 /// 1. Parent process (this one) forks
972 /// 2. Parent process exits
973 /// 3. Child process continues to run.
974 ///
975 /// `nochdir`:
976 ///
977 /// * `nochdir = true`: The current working directory after daemonizing will
978 ///    be the current working directory.
979 /// *  `nochdir = false`: The current working directory after daemonizing will
980 ///    be the root direcory, `/`.
981 ///
982 /// `noclose`:
983 ///
984 /// * `noclose = true`: The process' current stdin, stdout, and stderr file
985 ///   descriptors will remain identical after daemonizing.
986 /// * `noclose = false`: The process' stdin, stdout, and stderr will point to
987 ///   `/dev/null` after daemonizing.
988 #[cfg(any(
989         linux_android,
990         freebsdlike,
991         solarish,
992         netbsdlike
993 ))]
994 pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
995     let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
996     Errno::result(res).map(drop)
997 }
998 }
999 
1000 feature! {
1001 #![feature = "hostname"]
1002 
1003 /// Set the system host name (see
1004 /// [sethostname(2)](https://man7.org/linux/man-pages/man2/gethostname.2.html)).
1005 ///
1006 /// Given a name, attempt to update the system host name to the given string.
1007 /// On some systems, the host name is limited to as few as 64 bytes.  An error
1008 /// will be returned if the name is not valid or the current process does not
1009 /// have permissions to update the host name.
1010 #[cfg(not(target_os = "redox"))]
1011 pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
1012     // Handle some differences in type of the len arg across platforms.
1013     cfg_if! {
1014         if #[cfg(any(freebsdlike,
1015                      solarish,
1016                      apple_targets,
1017                      target_os = "aix"))] {
1018             type sethostname_len_t = c_int;
1019         } else {
1020             type sethostname_len_t = size_t;
1021         }
1022     }
1023     let ptr = name.as_ref().as_bytes().as_ptr().cast();
1024     let len = name.as_ref().len() as sethostname_len_t;
1025 
1026     let res = unsafe { libc::sethostname(ptr, len) };
1027     Errno::result(res).map(drop)
1028 }
1029 
1030 /// Get the host name and store it in an internally allocated buffer, returning an
1031 /// `OsString` on success (see
1032 /// [gethostname(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
1033 ///
1034 /// This function call attempts to get the host name for the running system and
1035 /// store it in an internal buffer, returning it as an `OsString` if successful.
1036 ///
1037 /// ```no_run
1038 /// use nix::unistd;
1039 ///
1040 /// let hostname = unistd::gethostname().expect("Failed getting hostname");
1041 /// let hostname = hostname.into_string().expect("Hostname wasn't valid UTF-8");
1042 /// println!("Hostname: {}", hostname);
1043 /// ```
1044 pub fn gethostname() -> Result<OsString> {
1045     // The capacity is the max length of a hostname plus the NUL terminator.
1046     let mut buffer: Vec<u8> = Vec::with_capacity(256);
1047     let ptr = buffer.as_mut_ptr().cast();
1048     let len = buffer.capacity() as size_t;
1049 
1050     let res = unsafe { libc::gethostname(ptr, len) };
1051     Errno::result(res).map(|_| {
1052         unsafe {
1053             buffer.as_mut_ptr().wrapping_add(len - 1).write(0); // ensure always null-terminated
1054             let len = CStr::from_ptr(buffer.as_ptr().cast()).len();
1055             buffer.set_len(len);
1056         }
1057         OsString::from_vec(buffer)
1058     })
1059 }
1060 }
1061 
1062 /// Close a raw file descriptor
1063 ///
1064 /// Be aware that many Rust types implicitly close-on-drop, including
1065 /// `std::fs::File`.  Explicitly closing them with this method too can result in
1066 /// a double-close condition, which can cause confusing `EBADF` errors in
1067 /// seemingly unrelated code.  Caveat programmer.  See also
1068 /// [close(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
1069 ///
1070 /// # Examples
1071 ///
1072 /// ```no_run
1073 /// use std::os::unix::io::AsRawFd;
1074 /// use nix::unistd::close;
1075 ///
1076 /// let f = tempfile::tempfile().unwrap();
1077 /// close(f.as_raw_fd()).unwrap();   // Bad!  f will also close on drop!
1078 /// ```
1079 ///
1080 /// ```rust
1081 /// use std::os::unix::io::IntoRawFd;
1082 /// use nix::unistd::close;
1083 ///
1084 /// let f = tempfile::tempfile().unwrap();
1085 /// close(f.into_raw_fd()).unwrap(); // Good.  into_raw_fd consumes f
1086 /// ```
close(fd: RawFd) -> Result<()>1087 pub fn close(fd: RawFd) -> Result<()> {
1088     let res = unsafe { libc::close(fd) };
1089     Errno::result(res).map(drop)
1090 }
1091 
1092 /// Read from a raw file descriptor.
1093 ///
1094 /// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
read(fd: RawFd, buf: &mut [u8]) -> Result<usize>1095 pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
1096     let res =
1097         unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as size_t) };
1098 
1099     Errno::result(res).map(|r| r as usize)
1100 }
1101 
1102 /// Write to a raw file descriptor.
1103 ///
1104 /// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> Result<usize>1105 pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> Result<usize> {
1106     let res = unsafe {
1107         libc::write(
1108             fd.as_fd().as_raw_fd(),
1109             buf.as_ptr().cast(),
1110             buf.len() as size_t,
1111         )
1112     };
1113 
1114     Errno::result(res).map(|r| r as usize)
1115 }
1116 
1117 feature! {
1118 #![feature = "fs"]
1119 
1120 /// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to.
1121 ///
1122 /// [`lseek`]: ./fn.lseek.html
1123 /// [`lseek64`]: ./fn.lseek64.html
1124 #[repr(i32)]
1125 #[derive(Clone, Copy, Debug)]
1126 pub enum Whence {
1127     /// Specify an offset relative to the start of the file.
1128     SeekSet = libc::SEEK_SET,
1129     /// Specify an offset relative to the current file location.
1130     SeekCur = libc::SEEK_CUR,
1131     /// Specify an offset relative to the end of the file.
1132     SeekEnd = libc::SEEK_END,
1133     /// Specify an offset relative to the next location in the file greater than or
1134     /// equal to offset that contains some data. If offset points to
1135     /// some data, then the file offset is set to offset.
1136     #[cfg(any(
1137         freebsdlike,
1138         solarish,
1139         target_os = "linux",
1140     ))]
1141     SeekData = libc::SEEK_DATA,
1142     /// Specify an offset relative to the next hole in the file greater than
1143     /// or equal to offset. If offset points into the middle of a hole, then
1144     /// the file offset should be set to offset. If there is no hole past offset,
1145     /// then the file offset should be adjusted to the end of the file (i.e., there
1146     /// is an implicit hole at the end of any file).
1147     #[cfg(any(
1148         freebsdlike,
1149         solarish,
1150         target_os = "linux",
1151     ))]
1152     SeekHole = libc::SEEK_HOLE,
1153 }
1154 
1155 /// Move the read/write file offset.
1156 ///
1157 /// See also [lseek(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
1158 pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
1159     let res = unsafe { libc::lseek(fd, offset, whence as i32) };
1160 
1161     Errno::result(res).map(|r| r as off_t)
1162 }
1163 
1164 /// Move the read/write file offset.
1165 ///
1166 /// Unlike [`lseek`], it takes a 64-bit argument even on platforms where [`libc::off_t`] is
1167 /// 32 bits.
1168 #[cfg(linux_android)]
1169 pub fn lseek64(
1170     fd: RawFd,
1171     offset: libc::off64_t,
1172     whence: Whence,
1173 ) -> Result<libc::off64_t> {
1174     let res = unsafe { libc::lseek64(fd, offset, whence as i32) };
1175 
1176     Errno::result(res).map(|r| r as libc::off64_t)
1177 }
1178 }
1179 
1180 /// Create an interprocess channel.
1181 ///
1182 /// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error>1183 pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> {
1184     let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
1185 
1186     let res = unsafe { libc::pipe(fds.as_mut_ptr().cast()) };
1187 
1188     Error::result(res)?;
1189 
1190     let [read, write] = unsafe { fds.assume_init() };
1191     Ok((read, write))
1192 }
1193 
1194 feature! {
1195 #![feature = "fs"]
1196 /// Like `pipe`, but allows setting certain file descriptor flags.
1197 ///
1198 /// The following flags are supported, and will be set atomically as the pipe is
1199 /// created:
1200 ///
1201 /// - `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
1202 #[cfg_attr(
1203     target_os = "linux",
1204     doc = "- `O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode."
1205 )]
1206 #[cfg_attr(
1207     target_os = "netbsd",
1208     doc = "- `O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`."
1209 )]
1210 /// - `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
1211 ///
1212 /// See also [pipe(2)](https://man7.org/linux/man-pages/man2/pipe.2.html)
1213 #[cfg(any(
1214     linux_android,
1215     freebsdlike,
1216     solarish,
1217     target_os = "emscripten",
1218     target_os = "hurd",
1219     target_os = "redox",
1220     netbsdlike,
1221 ))]
1222 pub fn pipe2(flags: OFlag) -> Result<(OwnedFd, OwnedFd)> {
1223     let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit();
1224 
1225     let res =
1226         unsafe { libc::pipe2(fds.as_mut_ptr().cast(), flags.bits()) };
1227 
1228     Errno::result(res)?;
1229 
1230     let [read, write] = unsafe { fds.assume_init() };
1231     Ok((read, write))
1232 }
1233 
1234 /// Truncate a file to a specified length
1235 ///
1236 /// See also
1237 /// [truncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
1238 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
1239 pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
1240     let res = path
1241         .with_nix_path(|cstr| unsafe { libc::truncate(cstr.as_ptr(), len) })?;
1242 
1243     Errno::result(res).map(drop)
1244 }
1245 
1246 /// Truncate a file to a specified length
1247 ///
1248 /// See also
1249 /// [ftruncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
1250 pub fn ftruncate<Fd: AsFd>(fd: Fd, len: off_t) -> Result<()> {
1251     Errno::result(unsafe { libc::ftruncate(fd.as_fd().as_raw_fd(), len) }).map(drop)
1252 }
1253 
1254 /// Determines if the file descriptor refers to a valid terminal type device.
1255 pub fn isatty(fd: RawFd) -> Result<bool> {
1256     unsafe {
1257         // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
1258         // we return `Ok(false)`
1259         if libc::isatty(fd) == 1 {
1260             Ok(true)
1261         } else {
1262             match Errno::last() {
1263                 Errno::ENOTTY => Ok(false),
1264                 err => Err(err),
1265             }
1266         }
1267     }
1268 }
1269 
1270 #[allow(missing_docs)]
1271 #[cfg(not(target_os = "redox"))]
1272 pub type LinkatFlags = AtFlags;
1273 #[allow(missing_docs)]
1274 #[cfg(not(target_os = "redox"))]
1275 impl LinkatFlags {
1276     #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
1277     #[allow(non_upper_case_globals)]
1278     pub const SymlinkFollow: LinkatFlags = LinkatFlags::AT_SYMLINK_FOLLOW;
1279     #[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
1280     #[allow(non_upper_case_globals)]
1281     pub const NoSymlinkFollow: LinkatFlags = LinkatFlags::empty();
1282 }
1283 
1284 /// Link one file to another file
1285 ///
1286 /// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
1287 /// case of a relative `oldpath`, the path is interpreted relative to the directory associated
1288 /// with file descriptor `olddirfd` instead of the current working directory and similiarly for
1289 /// `newpath` and file descriptor `newdirfd`. In case `flag` is `AtFlags::AT_SYMLINK_FOLLOW` and
1290 /// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
1291 /// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
1292 /// and/or `newpath` is then interpreted relative to the current working directory of the calling
1293 /// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored.
1294 ///
1295 /// # References
1296 /// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
1297 #[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
1298 pub fn linkat<P: ?Sized + NixPath>(
1299     olddirfd: Option<RawFd>,
1300     oldpath: &P,
1301     newdirfd: Option<RawFd>,
1302     newpath: &P,
1303     flag: AtFlags,
1304 ) -> Result<()> {
1305     let res = oldpath.with_nix_path(|oldcstr| {
1306         newpath.with_nix_path(|newcstr| unsafe {
1307             libc::linkat(
1308                 at_rawfd(olddirfd),
1309                 oldcstr.as_ptr(),
1310                 at_rawfd(newdirfd),
1311                 newcstr.as_ptr(),
1312                 flag.bits(),
1313             )
1314         })
1315     })??;
1316     Errno::result(res).map(drop)
1317 }
1318 
1319 /// Remove a directory entry
1320 ///
1321 /// See also [unlink(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
1322 pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
1323     let res =
1324         path.with_nix_path(|cstr| unsafe { libc::unlink(cstr.as_ptr()) })?;
1325     Errno::result(res).map(drop)
1326 }
1327 
1328 /// Flags for `unlinkat` function.
1329 #[derive(Clone, Copy, Debug)]
1330 pub enum UnlinkatFlags {
1331     /// Remove the directory entry as a directory, not a normal file
1332     RemoveDir,
1333     /// Remove the directory entry as a normal file, not a directory
1334     NoRemoveDir,
1335 }
1336 
1337 /// Remove a directory entry
1338 ///
1339 /// In the case of a relative path, the directory entry to be removed is determined relative to
1340 /// the directory associated with the file descriptor `dirfd` or the current working directory
1341 /// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is
1342 /// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path`
1343 /// is performed.
1344 ///
1345 /// # References
1346 /// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
1347 #[cfg(not(target_os = "redox"))]
1348 pub fn unlinkat<P: ?Sized + NixPath>(
1349     dirfd: Option<RawFd>,
1350     path: &P,
1351     flag: UnlinkatFlags,
1352 ) -> Result<()> {
1353     let atflag = match flag {
1354         UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR,
1355         UnlinkatFlags::NoRemoveDir => AtFlags::empty(),
1356     };
1357     let res = path.with_nix_path(|cstr| unsafe {
1358         libc::unlinkat(
1359             at_rawfd(dirfd),
1360             cstr.as_ptr(),
1361             atflag.bits() as libc::c_int,
1362         )
1363     })?;
1364     Errno::result(res).map(drop)
1365 }
1366 
1367 /// Change a process's root directory
1368 #[inline]
1369 #[cfg(not(target_os = "fuchsia"))]
1370 pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
1371     let res =
1372         path.with_nix_path(|cstr| unsafe { libc::chroot(cstr.as_ptr()) })?;
1373 
1374     Errno::result(res).map(drop)
1375 }
1376 
1377 /// Commit filesystem caches to disk
1378 ///
1379 /// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
1380 #[cfg(any(bsd, linux_android, solarish, target_os = "haiku", target_os = "aix", target_os = "hurd"))]
1381 pub fn sync() {
1382     unsafe { libc::sync() };
1383 }
1384 
1385 /// Commit filesystem caches containing file referred to by the open file
1386 /// descriptor `fd` to disk
1387 ///
1388 /// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html)
1389 #[cfg(any(linux_android, target_os = "hurd"))]
1390 pub fn syncfs(fd: RawFd) -> Result<()> {
1391     let res = unsafe { libc::syncfs(fd) };
1392 
1393     Errno::result(res).map(drop)
1394 }
1395 
1396 /// Synchronize changes to a file
1397 ///
1398 /// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
1399 #[inline]
1400 pub fn fsync(fd: RawFd) -> Result<()> {
1401     let res = unsafe { libc::fsync(fd) };
1402 
1403     Errno::result(res).map(drop)
1404 }
1405 
1406 /// Synchronize the data of a file
1407 ///
1408 /// See also
1409 /// [fdatasync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
1410 #[cfg(any(
1411     linux_android,
1412     solarish,
1413     netbsdlike,
1414     apple_targets,
1415     target_os = "freebsd",
1416     target_os = "emscripten",
1417     target_os = "fuchsia",
1418     target_os = "aix",
1419     target_os = "hurd",
1420 ))]
1421 #[inline]
1422 pub fn fdatasync(fd: RawFd) -> Result<()> {
1423     cfg_if! {
1424         // apple libc supports fdatasync too, albeit not being present in its headers
1425         // [fdatasync](https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/vfs/vfs_syscalls.c#L7728)
1426         if #[cfg(apple_targets)] {
1427             extern "C" {
1428                 fn fdatasync(fd: libc::c_int) -> libc::c_int;
1429             }
1430         } else {
1431             use libc::fdatasync as fdatasync;
1432         }
1433     }
1434     let res = unsafe { fdatasync(fd) };
1435 
1436     Errno::result(res).map(drop)
1437 }
1438 }
1439 
1440 feature! {
1441 #![feature = "user"]
1442 
1443 /// Get a real user ID
1444 ///
1445 /// See also [getuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
1446 // POSIX requires that getuid is always successful, so no need to check return
1447 // value or errno.
1448 #[inline]
1449 pub fn getuid() -> Uid {
1450     Uid(unsafe { libc::getuid() })
1451 }
1452 
1453 /// Get the effective user ID
1454 ///
1455 /// See also [geteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
1456 // POSIX requires that geteuid is always successful, so no need to check return
1457 // value or errno.
1458 #[inline]
1459 pub fn geteuid() -> Uid {
1460     Uid(unsafe { libc::geteuid() })
1461 }
1462 
1463 /// Get the real group ID
1464 ///
1465 /// See also [getgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
1466 // POSIX requires that getgid is always successful, so no need to check return
1467 // value or errno.
1468 #[inline]
1469 pub fn getgid() -> Gid {
1470     Gid(unsafe { libc::getgid() })
1471 }
1472 
1473 /// Get the effective group ID
1474 ///
1475 /// See also [getegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
1476 // POSIX requires that getegid is always successful, so no need to check return
1477 // value or errno.
1478 #[inline]
1479 pub fn getegid() -> Gid {
1480     Gid(unsafe { libc::getegid() })
1481 }
1482 
1483 /// Set the effective user ID
1484 ///
1485 /// See also [seteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
1486 #[inline]
1487 pub fn seteuid(euid: Uid) -> Result<()> {
1488     let res = unsafe { libc::seteuid(euid.into()) };
1489 
1490     Errno::result(res).map(drop)
1491 }
1492 
1493 /// Set the effective group ID
1494 ///
1495 /// See also [setegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
1496 #[inline]
1497 pub fn setegid(egid: Gid) -> Result<()> {
1498     let res = unsafe { libc::setegid(egid.into()) };
1499 
1500     Errno::result(res).map(drop)
1501 }
1502 
1503 /// Set the user ID
1504 ///
1505 /// See also [setuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
1506 #[inline]
1507 pub fn setuid(uid: Uid) -> Result<()> {
1508     let res = unsafe { libc::setuid(uid.into()) };
1509 
1510     Errno::result(res).map(drop)
1511 }
1512 
1513 /// Set the group ID
1514 ///
1515 /// See also [setgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
1516 #[inline]
1517 pub fn setgid(gid: Gid) -> Result<()> {
1518     let res = unsafe { libc::setgid(gid.into()) };
1519 
1520     Errno::result(res).map(drop)
1521 }
1522 }
1523 
1524 feature! {
1525 #![all(feature = "fs", feature = "user")]
1526 /// Set the user identity used for filesystem checks per-thread.
1527 /// On both success and failure, this call returns the previous filesystem user
1528 /// ID of the caller.
1529 ///
1530 /// See also [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html)
1531 #[cfg(linux_android)]
1532 pub fn setfsuid(uid: Uid) -> Uid {
1533     let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
1534     Uid::from_raw(prev_fsuid as uid_t)
1535 }
1536 
1537 /// Set the group identity used for filesystem checks per-thread.
1538 /// On both success and failure, this call returns the previous filesystem group
1539 /// ID of the caller.
1540 ///
1541 /// See also [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html)
1542 #[cfg(linux_android)]
1543 pub fn setfsgid(gid: Gid) -> Gid {
1544     let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
1545     Gid::from_raw(prev_fsgid as gid_t)
1546 }
1547 }
1548 
1549 feature! {
1550 #![feature = "user"]
1551 
1552 /// Get the list of supplementary group IDs of the calling process.
1553 ///
1554 /// [Further reading](https://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
1555 ///
1556 /// **Note:** This function is not available for Apple platforms. On those
1557 /// platforms, checking group membership should be achieved via communication
1558 /// with the `opendirectoryd` service.
1559 #[cfg(not(apple_targets))]
1560 pub fn getgroups() -> Result<Vec<Gid>> {
1561     // First get the maximum number of groups. The value returned
1562     // shall always be greater than or equal to one and less than or
1563     // equal to the value of {NGROUPS_MAX} + 1.
1564     let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
1565         Ok(Some(n)) => (n + 1) as usize,
1566         Ok(None) | Err(_) => usize::MAX,
1567     };
1568 
1569     // Next, get the number of groups so we can size our Vec
1570     let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
1571 
1572     // If there are no supplementary groups, return early.
1573     // This prevents a potential buffer over-read if the number of groups
1574     // increases from zero before the next call. It would return the total
1575     // number of groups beyond the capacity of the buffer.
1576     if ngroups == 0 {
1577         return Ok(Vec::new());
1578     }
1579 
1580     // Now actually get the groups. We try multiple times in case the number of
1581     // groups has changed since the first call to getgroups() and the buffer is
1582     // now too small.
1583     let mut groups =
1584         Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize);
1585     loop {
1586         // FIXME: On the platforms we currently support, the `Gid` struct has
1587         // the same representation in memory as a bare `gid_t`. This is not
1588         // necessarily the case on all Rust platforms, though. See RFC 1785.
1589         let ngroups = unsafe {
1590             libc::getgroups(
1591                 groups.capacity() as c_int,
1592                 groups.as_mut_ptr().cast(),
1593             )
1594         };
1595 
1596         match Errno::result(ngroups) {
1597             Ok(s) => {
1598                 unsafe { groups.set_len(s as usize) };
1599                 return Ok(groups);
1600             }
1601             Err(Errno::EINVAL) => {
1602                 // EINVAL indicates that the buffer size was too
1603                 // small, resize it up to ngroups_max as limit.
1604                 reserve_double_buffer_size(&mut groups, ngroups_max)
1605                     .or(Err(Errno::EINVAL))?;
1606             }
1607             Err(e) => return Err(e),
1608         }
1609     }
1610 }
1611 
1612 /// Set the list of supplementary group IDs for the calling process.
1613 ///
1614 /// [Further reading](https://man7.org/linux/man-pages/man2/getgroups.2.html)
1615 ///
1616 /// **Note:** This function is not available for Apple platforms. On those
1617 /// platforms, group membership management should be achieved via communication
1618 /// with the `opendirectoryd` service.
1619 ///
1620 /// # Examples
1621 ///
1622 /// `setgroups` can be used when dropping privileges from the root user to a
1623 /// specific user and group. For example, given the user `www-data` with UID
1624 /// `33` and the group `backup` with the GID `34`, one could switch the user as
1625 /// follows:
1626 ///
1627 /// ```rust,no_run
1628 /// # use std::error::Error;
1629 /// # use nix::unistd::*;
1630 /// #
1631 /// # fn try_main() -> Result<(), Box<dyn Error>> {
1632 /// let uid = Uid::from_raw(33);
1633 /// let gid = Gid::from_raw(34);
1634 /// setgroups(&[gid])?;
1635 /// setgid(gid)?;
1636 /// setuid(uid)?;
1637 /// #
1638 /// #     Ok(())
1639 /// # }
1640 /// #
1641 /// # try_main().unwrap();
1642 /// ```
1643 #[cfg(not(any(
1644     apple_targets,
1645     target_os = "redox",
1646     target_os = "haiku"
1647 )))]
1648 pub fn setgroups(groups: &[Gid]) -> Result<()> {
1649     cfg_if! {
1650         if #[cfg(any(bsd,
1651                      solarish,
1652                      target_os = "aix"))] {
1653             type setgroups_ngroups_t = c_int;
1654         } else {
1655             type setgroups_ngroups_t = size_t;
1656         }
1657     }
1658     // FIXME: On the platforms we currently support, the `Gid` struct has the
1659     // same representation in memory as a bare `gid_t`. This is not necessarily
1660     // the case on all Rust platforms, though. See RFC 1785.
1661     let res = unsafe {
1662         libc::setgroups(
1663             groups.len() as setgroups_ngroups_t,
1664             groups.as_ptr().cast(),
1665         )
1666     };
1667 
1668     Errno::result(res).map(drop)
1669 }
1670 
1671 /// Calculate the supplementary group access list.
1672 ///
1673 /// Gets the group IDs of all groups that `user` is a member of. The additional
1674 /// group `group` is also added to the list.
1675 ///
1676 /// [Further reading](https://man7.org/linux/man-pages/man3/getgrouplist.3.html)
1677 ///
1678 /// **Note:** This function is not available for Apple platforms. On those
1679 /// platforms, checking group membership should be achieved via communication
1680 /// with the `opendirectoryd` service.
1681 ///
1682 /// # Errors
1683 ///
1684 /// Although the `getgrouplist()` call does not return any specific
1685 /// errors on any known platforms, this implementation will return a system
1686 /// error of `EINVAL` if the number of groups to be fetched exceeds the
1687 /// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()`
1688 /// and `setgroups()`. Additionally, while some implementations will return a
1689 /// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation
1690 /// will only ever return the complete list or else an error.
1691 #[cfg(not(any(
1692     target_os = "aix",
1693     solarish,
1694     apple_targets,
1695     target_os = "redox"
1696 )))]
1697 pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
1698     let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
1699         Ok(Some(n)) => n as c_int,
1700         Ok(None) | Err(_) => c_int::MAX,
1701     };
1702     use std::cmp::min;
1703     let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize);
1704     cfg_if! {
1705         if #[cfg(apple_targets)] {
1706             type getgrouplist_group_t = c_int;
1707         } else {
1708             type getgrouplist_group_t = gid_t;
1709         }
1710     }
1711     let gid: gid_t = group.into();
1712     loop {
1713         let mut ngroups = groups.capacity() as i32;
1714         let ret = unsafe {
1715             libc::getgrouplist(
1716                 user.as_ptr(),
1717                 gid as getgrouplist_group_t,
1718                 groups.as_mut_ptr().cast(),
1719                 &mut ngroups,
1720             )
1721         };
1722 
1723         // BSD systems only return 0 or -1, Linux returns ngroups on success.
1724         if ret >= 0 {
1725             unsafe { groups.set_len(ngroups as usize) };
1726             return Ok(groups);
1727         } else if ret == -1 {
1728             // Returns -1 if ngroups is too small, but does not set errno.
1729             // BSD systems will still fill the groups buffer with as many
1730             // groups as possible, but Linux manpages do not mention this
1731             // behavior.
1732             reserve_double_buffer_size(&mut groups, ngroups_max as usize)
1733                 .map_err(|_| Errno::EINVAL)?;
1734         }
1735     }
1736 }
1737 
1738 /// Initialize the supplementary group access list.
1739 ///
1740 /// Sets the supplementary group IDs for the calling process using all groups
1741 /// that `user` is a member of. The additional group `group` is also added to
1742 /// the list.
1743 ///
1744 /// [Further reading](https://man7.org/linux/man-pages/man3/initgroups.3.html)
1745 ///
1746 /// **Note:** This function is not available for Apple platforms. On those
1747 /// platforms, group membership management should be achieved via communication
1748 /// with the `opendirectoryd` service.
1749 ///
1750 /// # Examples
1751 ///
1752 /// `initgroups` can be used when dropping privileges from the root user to
1753 /// another user. For example, given the user `www-data`, we could look up the
1754 /// UID and GID for the user in the system's password database (usually found
1755 /// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`,
1756 /// respectively, one could switch the user as follows:
1757 ///
1758 /// ```rust,no_run
1759 /// # use std::error::Error;
1760 /// # use std::ffi::CString;
1761 /// # use nix::unistd::*;
1762 /// #
1763 /// # fn try_main() -> Result<(), Box<dyn Error>> {
1764 /// let user = CString::new("www-data").unwrap();
1765 /// let uid = Uid::from_raw(33);
1766 /// let gid = Gid::from_raw(33);
1767 /// initgroups(&user, gid)?;
1768 /// setgid(gid)?;
1769 /// setuid(uid)?;
1770 /// #
1771 /// #     Ok(())
1772 /// # }
1773 /// #
1774 /// # try_main().unwrap();
1775 /// ```
1776 #[cfg(not(any(
1777     apple_targets,
1778     target_os = "redox",
1779     target_os = "haiku"
1780 )))]
1781 pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
1782     cfg_if! {
1783         if #[cfg(apple_targets)] {
1784             type initgroups_group_t = c_int;
1785         } else {
1786             type initgroups_group_t = gid_t;
1787         }
1788     }
1789     let gid: gid_t = group.into();
1790     let res =
1791         unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) };
1792 
1793     Errno::result(res).map(drop)
1794 }
1795 }
1796 
1797 feature! {
1798 #![feature = "signal"]
1799 
1800 /// Suspend the thread until a signal is received.
1801 ///
1802 /// See also [pause(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
1803 #[inline]
1804 #[cfg(not(target_os = "redox"))]
1805 pub fn pause() {
1806     unsafe { libc::pause() };
1807 }
1808 
1809 pub mod alarm {
1810     //! Alarm signal scheduling.
1811     //!
1812     //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
1813     //! elapsed, which has to be caught, because the default action for the
1814     //! signal is to terminate the program. This signal also can't be ignored
1815     //! because the system calls like `pause` will not be interrupted, see the
1816     //! second example below.
1817     //!
1818     //! # Examples
1819     //!
1820     //! Canceling an alarm:
1821     //!
1822     //! ```
1823     //! use nix::unistd::alarm;
1824     //!
1825     //! // Set an alarm for 60 seconds from now.
1826     //! alarm::set(60);
1827     //!
1828     //! // Cancel the above set alarm, which returns the number of seconds left
1829     //! // of the previously set alarm.
1830     //! assert_eq!(alarm::cancel(), Some(60));
1831     //! ```
1832     //!
1833     //! Scheduling an alarm and waiting for the signal:
1834     //!
1835     #![cfg_attr(target_os = "redox", doc = " ```rust,ignore")]
1836     #![cfg_attr(not(target_os = "redox"), doc = " ```rust")]
1837     //! use std::time::{Duration, Instant};
1838     //!
1839     //! use nix::unistd::{alarm, pause};
1840     //! use nix::sys::signal::*;
1841     //!
1842     //! // We need to setup an empty signal handler to catch the alarm signal,
1843     //! // otherwise the program will be terminated once the signal is delivered.
1844     //! extern fn signal_handler(_: nix::libc::c_int) { }
1845     //! let sa = SigAction::new(
1846     //!     SigHandler::Handler(signal_handler),
1847     //!     SaFlags::SA_RESTART,
1848     //!     SigSet::empty()
1849     //! );
1850     //! unsafe {
1851     //!     sigaction(Signal::SIGALRM, &sa);
1852     //! }
1853     //!
1854     //! let start = Instant::now();
1855     //!
1856     //! // Set an alarm for 1 second from now.
1857     //! alarm::set(1);
1858     //!
1859     //! // Pause the process until the alarm signal is received.
1860     //! let mut sigset = SigSet::empty();
1861     //! sigset.add(Signal::SIGALRM);
1862     //! sigset.wait();
1863     //!
1864     //! assert!(start.elapsed() >= Duration::from_secs(1));
1865     //! ```
1866     //!
1867     //! # References
1868     //!
1869     //! See also [alarm(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
1870 
1871     /// Schedule an alarm signal.
1872     ///
1873     /// This will cause the system to generate a `SIGALRM` signal for the
1874     /// process after the specified number of seconds have elapsed.
1875     ///
1876     /// Returns the leftover time of a previously set alarm if there was one.
1877     pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
1878         assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
1879         alarm(secs)
1880     }
1881 
1882     /// Cancel an previously set alarm signal.
1883     ///
1884     /// Returns the leftover time of a previously set alarm if there was one.
1885     pub fn cancel() -> Option<libc::c_uint> {
1886         alarm(0)
1887     }
1888 
1889     fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
1890         match unsafe { libc::alarm(secs) } {
1891             0 => None,
1892             secs => Some(secs),
1893         }
1894     }
1895 }
1896 }
1897 
1898 /// Suspend execution for an interval of time
1899 ///
1900 /// See also [sleep(2)](https://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
1901 // Per POSIX, does not fail
1902 #[inline]
sleep(seconds: c_uint) -> c_uint1903 pub fn sleep(seconds: c_uint) -> c_uint {
1904     unsafe { libc::sleep(seconds) }
1905 }
1906 
1907 feature! {
1908 #![feature = "acct"]
1909 
1910 /// Process accounting
1911 #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
1912 pub mod acct {
1913     use crate::errno::Errno;
1914     use crate::{NixPath, Result};
1915     use std::ptr;
1916 
1917     /// Enable process accounting
1918     ///
1919     /// See also [acct(2)](https://linux.die.net/man/2/acct)
1920     pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> {
1921         let res = filename
1922             .with_nix_path(|cstr| unsafe { libc::acct(cstr.as_ptr()) })?;
1923 
1924         Errno::result(res).map(drop)
1925     }
1926 
1927     /// Disable process accounting
1928     pub fn disable() -> Result<()> {
1929         let res = unsafe { libc::acct(ptr::null()) };
1930 
1931         Errno::result(res).map(drop)
1932     }
1933 }
1934 }
1935 
1936 feature! {
1937 #![feature = "fs"]
1938 /// Creates a regular file which persists even after process termination
1939 ///
1940 /// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX`
1941 /// * returns: tuple of file descriptor and filename
1942 ///
1943 /// Err is returned either if no temporary filename could be created or the template doesn't
1944 /// end with XXXXXX
1945 ///
1946 /// See also [mkstemp(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
1947 ///
1948 /// # Example
1949 ///
1950 /// ```rust
1951 /// use nix::unistd;
1952 ///
1953 /// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
1954 ///     Ok((fd, path)) => {
1955 ///         unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
1956 ///         fd
1957 ///     }
1958 ///     Err(e) => panic!("mkstemp failed: {}", e)
1959 /// };
1960 /// // do something with fd
1961 /// ```
1962 #[inline]
1963 pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
1964     let mut path =
1965         template.with_nix_path(|path| path.to_bytes_with_nul().to_owned())?;
1966     let p = path.as_mut_ptr().cast();
1967     let fd = unsafe { libc::mkstemp(p) };
1968     let last = path.pop(); // drop the trailing nul
1969     debug_assert!(last == Some(b'\0'));
1970     let pathname = OsString::from_vec(path);
1971     Errno::result(fd)?;
1972     Ok((fd, PathBuf::from(pathname)))
1973 }
1974 }
1975 
1976 feature! {
1977 #![all(feature = "fs", feature = "feature")]
1978 
1979 /// Creates a directory which persists even after process termination
1980 ///
1981 /// * `template`: a path whose rightmost characters contain some number of X, e.g. `/tmp/tmpdir_XXXXXX`
1982 /// * returns: filename
1983 ///
1984 /// Err is returned either if no temporary filename could be created or the template had insufficient X
1985 ///
1986 /// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html)
1987 ///
1988 /// ```
1989 /// use nix::unistd;
1990 ///
1991 /// match unistd::mkdtemp("/tmp/tempdir_XXXXXX") {
1992 ///     Ok(_path) => {
1993 ///         // do something with directory
1994 ///     }
1995 ///     Err(e) => panic!("mkdtemp failed: {}", e)
1996 /// };
1997 /// ```
1998 pub fn mkdtemp<P: ?Sized + NixPath>(template: &P) -> Result<PathBuf> {
1999     let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
2000     let p = path.as_mut_ptr() as *mut _;
2001     let p = unsafe { libc::mkdtemp(p) };
2002     if p.is_null() {
2003         return Err(Errno::last());
2004     }
2005     let last = path.pop(); // drop the trailing nul
2006     debug_assert!(last == Some(b'\0'));
2007     let pathname = OsString::from_vec(path);
2008     Ok(PathBuf::from(pathname))
2009 }
2010 
2011 /// Variable names for `pathconf`
2012 ///
2013 /// Nix uses the same naming convention for these variables as the
2014 /// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
2015 /// That is, `PathconfVar` variables have the same name as the abstract
2016 /// variables  shown in the `pathconf(2)` man page.  Usually, it's the same as
2017 /// the C variable name without the leading `_PC_`.
2018 ///
2019 /// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose
2020 /// not to implement variables that cannot change at runtime.
2021 ///
2022 /// # References
2023 ///
2024 /// - [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)
2025 /// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
2026 /// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
2027 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2028 #[repr(i32)]
2029 #[non_exhaustive]
2030 pub enum PathconfVar {
2031     #[cfg(any(
2032         freebsdlike,
2033         netbsdlike,
2034         target_os = "linux",
2035         target_os = "redox"
2036     ))]
2037     /// Minimum number of bits needed to represent, as a signed integer value,
2038     /// the maximum size of a regular file allowed in the specified directory.
2039     FILESIZEBITS = libc::_PC_FILESIZEBITS,
2040     /// Maximum number of links to a single file.
2041     LINK_MAX = libc::_PC_LINK_MAX,
2042     /// Maximum number of bytes in a terminal canonical input line.
2043     MAX_CANON = libc::_PC_MAX_CANON,
2044     /// Minimum number of bytes for which space is available in a terminal input
2045     /// queue; therefore, the maximum number of bytes a conforming application
2046     /// may require to be typed as input before reading them.
2047     MAX_INPUT = libc::_PC_MAX_INPUT,
2048     #[cfg(any(
2049         apple_targets,
2050         solarish,
2051         freebsdlike,
2052         target_os = "netbsd",
2053     ))]
2054     /// If a file system supports the reporting of holes (see lseek(2)),
2055     /// pathconf() and fpathconf() return a positive number that represents the
2056     /// minimum hole size returned in bytes.  The offsets of holes returned will
2057     /// be aligned to this same value.  A special value of 1 is returned if the
2058     /// file system does not specify the minimum hole size but still reports
2059     /// holes.
2060     MIN_HOLE_SIZE = libc::_PC_MIN_HOLE_SIZE,
2061     /// Maximum number of bytes in a filename (not including the terminating
2062     /// null of a filename string).
2063     NAME_MAX = libc::_PC_NAME_MAX,
2064     /// Maximum number of bytes the implementation will store as a pathname in a
2065     /// user-supplied buffer of unspecified size, including the terminating null
2066     /// character. Minimum number the implementation will accept as the maximum
2067     /// number of bytes in a pathname.
2068     PATH_MAX = libc::_PC_PATH_MAX,
2069     /// Maximum number of bytes that is guaranteed to be atomic when writing to
2070     /// a pipe.
2071     PIPE_BUF = libc::_PC_PIPE_BUF,
2072     #[cfg(any(
2073         linux_android,
2074         solarish,
2075         netbsdlike,
2076         target_os = "dragonfly",
2077         target_os = "redox",
2078     ))]
2079     /// Symbolic links can be created.
2080     POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
2081     #[cfg(any(
2082         linux_android,
2083         freebsdlike,
2084         target_os = "openbsd",
2085         target_os = "redox"
2086     ))]
2087     /// Minimum number of bytes of storage actually allocated for any portion of
2088     /// a file.
2089     POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
2090     #[cfg(any(
2091         freebsdlike,
2092         linux_android,
2093         target_os = "openbsd"
2094     ))]
2095     /// Recommended increment for file transfer sizes between the
2096     /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
2097     POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
2098     #[cfg(any(
2099         linux_android,
2100         freebsdlike,
2101         target_os = "openbsd",
2102         target_os = "redox"
2103     ))]
2104     /// Maximum recommended file transfer size.
2105     POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
2106     #[cfg(any(
2107         linux_android,
2108         freebsdlike,
2109         target_os = "openbsd",
2110         target_os = "redox"
2111     ))]
2112     /// Minimum recommended file transfer size.
2113     POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
2114     #[cfg(any(
2115         linux_android,
2116         freebsdlike,
2117         target_os = "openbsd",
2118         target_os = "redox"
2119     ))]
2120     ///  Recommended file transfer buffer alignment.
2121     POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN,
2122     #[cfg(any(
2123         linux_android,
2124         freebsdlike,
2125         solarish,
2126         netbsdlike,
2127         target_os = "redox",
2128     ))]
2129     /// Maximum number of bytes in a symbolic link.
2130     SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
2131     /// The use of `chown` and `fchown` is restricted to a process with
2132     /// appropriate privileges, and to changing the group ID of a file only to
2133     /// the effective group ID of the process or to one of its supplementary
2134     /// group IDs.
2135     _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED,
2136     /// Pathname components longer than {NAME_MAX} generate an error.
2137     _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC,
2138     /// This symbol shall be defined to be the value of a character that shall
2139     /// disable terminal special character handling.
2140     _POSIX_VDISABLE = libc::_PC_VDISABLE,
2141     #[cfg(any(
2142         linux_android,
2143         freebsdlike,
2144         solarish,
2145         target_os = "openbsd",
2146         target_os = "redox",
2147     ))]
2148     /// Asynchronous input or output operations may be performed for the
2149     /// associated file.
2150     _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
2151     #[cfg(any(
2152         linux_android,
2153         freebsdlike,
2154         solarish,
2155         target_os = "openbsd",
2156         target_os = "redox",
2157     ))]
2158     /// Prioritized input or output operations may be performed for the
2159     /// associated file.
2160     _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
2161     #[cfg(any(
2162         linux_android,
2163         freebsdlike,
2164         solarish,
2165         netbsdlike,
2166         target_os = "redox",
2167     ))]
2168     /// Synchronized input or output operations may be performed for the
2169     /// associated file.
2170     _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
2171     #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
2172     /// The resolution in nanoseconds for all file timestamps.
2173     _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION,
2174 }
2175 
2176 /// Like `pathconf`, but works with file descriptors instead of paths (see
2177 /// [fpathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
2178 ///
2179 /// # Parameters
2180 ///
2181 /// - `fd`:   The file descriptor whose variable should be interrogated
2182 /// - `var`:  The pathconf variable to lookup
2183 ///
2184 /// # Returns
2185 ///
2186 /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
2187 ///     implementation level (for option variables).  Implementation levels are
2188 ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
2189 /// - `Ok(None)`: the variable has no limit (for limit variables) or is
2190 ///     unsupported (for option variables)
2191 /// - `Err(x)`: an error occurred
2192 pub fn fpathconf<F: AsFd>(fd: F, var: PathconfVar) -> Result<Option<c_long>> {
2193     let raw = unsafe {
2194         Errno::clear();
2195         libc::fpathconf(fd.as_fd().as_raw_fd(), var as c_int)
2196     };
2197     if raw == -1 {
2198         if Errno::last_raw() == 0 {
2199             Ok(None)
2200         } else {
2201             Err(Errno::last())
2202         }
2203     } else {
2204         Ok(Some(raw))
2205     }
2206 }
2207 
2208 /// Get path-dependent configurable system variables (see
2209 /// [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
2210 ///
2211 /// Returns the value of a path-dependent configurable system variable.  Most
2212 /// supported variables also have associated compile-time constants, but POSIX
2213 /// allows their values to change at runtime.  There are generally two types of
2214 /// `pathconf` variables: options and limits.  See [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
2215 ///
2216 /// # Parameters
2217 ///
2218 /// - `path`: Lookup the value of `var` for this file or directory
2219 /// - `var`:  The `pathconf` variable to lookup
2220 ///
2221 /// # Returns
2222 ///
2223 /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
2224 ///     implementation level (for option variables).  Implementation levels are
2225 ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
2226 /// - `Ok(None)`: the variable has no limit (for limit variables) or is
2227 ///     unsupported (for option variables)
2228 /// - `Err(x)`: an error occurred
2229 pub fn pathconf<P: ?Sized + NixPath>(
2230     path: &P,
2231     var: PathconfVar,
2232 ) -> Result<Option<c_long>> {
2233     let raw = path.with_nix_path(|cstr| unsafe {
2234         Errno::clear();
2235         libc::pathconf(cstr.as_ptr(), var as c_int)
2236     })?;
2237     if raw == -1 {
2238         if Errno::last_raw() == 0 {
2239             Ok(None)
2240         } else {
2241             Err(Errno::last())
2242         }
2243     } else {
2244         Ok(Some(raw))
2245     }
2246 }
2247 }
2248 
2249 feature! {
2250 #![feature = "feature"]
2251 
2252 /// Variable names for `sysconf`
2253 ///
2254 /// Nix uses the same naming convention for these variables as the
2255 /// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
2256 /// That is, `SysconfVar` variables have the same name as the abstract variables
2257 /// shown in the `sysconf(3)` man page.  Usually, it's the same as the C
2258 /// variable name without the leading `_SC_`.
2259 ///
2260 /// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been
2261 /// implemented by all platforms.
2262 ///
2263 /// # References
2264 ///
2265 /// - [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)
2266 /// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
2267 /// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
2268 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2269 #[repr(i32)]
2270 #[non_exhaustive]
2271 pub enum SysconfVar {
2272     /// Maximum number of I/O operations in a single list I/O call supported by
2273     /// the implementation.
2274     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2275     AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
2276     /// Maximum number of outstanding asynchronous I/O operations supported by
2277     /// the implementation.
2278     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2279     AIO_MAX = libc::_SC_AIO_MAX,
2280     #[cfg(any(
2281         linux_android,
2282         freebsdlike,
2283         apple_targets,
2284         target_os = "openbsd"
2285     ))]
2286     /// The maximum amount by which a process can decrease its asynchronous I/O
2287     /// priority level from its own scheduling priority.
2288     AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
2289     /// Maximum length of argument to the exec functions including environment data.
2290     ARG_MAX = libc::_SC_ARG_MAX,
2291     /// Maximum number of functions that may be registered with `atexit`.
2292     #[cfg(not(target_os = "redox"))]
2293     ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
2294     /// Maximum obase values allowed by the bc utility.
2295     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2296     BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
2297     /// Maximum number of elements permitted in an array by the bc utility.
2298     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2299     BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
2300     /// Maximum scale value allowed by the bc utility.
2301     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2302     BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
2303     /// Maximum length of a string constant accepted by the bc utility.
2304     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2305     BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
2306     /// Maximum number of simultaneous processes per real user ID.
2307     CHILD_MAX = libc::_SC_CHILD_MAX,
2308     /// The frequency of the statistics clock in ticks per second.
2309     CLK_TCK = libc::_SC_CLK_TCK,
2310     /// Maximum number of weights that can be assigned to an entry of the
2311     /// LC_COLLATE order keyword in the locale definition file
2312     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2313     COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
2314     /// Maximum number of timer expiration overruns.
2315     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2316     DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
2317     /// Maximum number of expressions that can be nested within parentheses by
2318     /// the expr utility.
2319     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2320     EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX,
2321     #[cfg(any(bsd, solarish, target_os = "linux"))]
2322     /// Maximum length of a host name (not including the terminating null) as
2323     /// returned from the `gethostname` function
2324     HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
2325     /// Maximum number of iovec structures that one process has available for
2326     /// use with `readv` or `writev`.
2327     #[cfg(not(target_os = "redox"))]
2328     IOV_MAX = libc::_SC_IOV_MAX,
2329     /// Unless otherwise noted, the maximum length, in bytes, of a utility's
2330     /// input line (either standard input or another file), when the utility is
2331     /// described as processing text files. The length includes room for the
2332     /// trailing newline.
2333     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2334     LINE_MAX = libc::_SC_LINE_MAX,
2335     /// Maximum length of a login name.
2336     #[cfg(not(target_os = "haiku"))]
2337     LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
2338     /// Maximum number of simultaneous supplementary group IDs per process.
2339     NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
2340     /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
2341     #[cfg(not(target_os = "redox"))]
2342     GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
2343     /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
2344     #[cfg(not(target_os = "redox"))]
2345     GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
2346     /// The maximum number of open message queue descriptors a process may hold.
2347     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2348     MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
2349     /// The maximum number of message priorities supported by the implementation.
2350     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2351     MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
2352     /// A value one greater than the maximum value that the system may assign to
2353     /// a newly-created file descriptor.
2354     OPEN_MAX = libc::_SC_OPEN_MAX,
2355     #[cfg(any(
2356         freebsdlike,
2357         apple_targets,
2358         target_os = "linux",
2359         target_os = "openbsd"
2360     ))]
2361     /// The implementation supports the Advisory Information option.
2362     _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO,
2363     #[cfg(any(bsd, solarish, target_os = "linux"))]
2364     /// The implementation supports barriers.
2365     _POSIX_BARRIERS = libc::_SC_BARRIERS,
2366     /// The implementation supports asynchronous input and output.
2367     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2368     _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO,
2369     #[cfg(any(bsd, solarish, target_os = "linux"))]
2370     /// The implementation supports clock selection.
2371     _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
2372     #[cfg(any(bsd, solarish, target_os = "linux"))]
2373     /// The implementation supports the Process CPU-Time Clocks option.
2374     _POSIX_CPUTIME = libc::_SC_CPUTIME,
2375     /// The implementation supports the File Synchronization option.
2376     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2377     _POSIX_FSYNC = libc::_SC_FSYNC,
2378     #[cfg(any(
2379         freebsdlike,
2380         apple_targets,
2381         solarish,
2382         target_os = "linux",
2383         target_os = "openbsd",
2384     ))]
2385     /// The implementation supports the IPv6 option.
2386     _POSIX_IPV6 = libc::_SC_IPV6,
2387     /// The implementation supports job control.
2388     #[cfg(not(target_os = "redox"))]
2389     _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
2390     /// The implementation supports memory mapped Files.
2391     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2392     _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
2393     /// The implementation supports the Process Memory Locking option.
2394     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2395     _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
2396     /// The implementation supports the Range Memory Locking option.
2397     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2398     _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
2399     /// The implementation supports memory protection.
2400     #[cfg(not(target_os = "redox"))]
2401     _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
2402     /// The implementation supports the Message Passing option.
2403     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2404     _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
2405     /// The implementation supports the Monotonic Clock option.
2406     #[cfg(not(target_os = "redox"))]
2407     _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK,
2408     #[cfg(any(
2409         linux_android,
2410         freebsdlike,
2411         solarish,
2412         apple_targets,
2413         target_os = "openbsd",
2414     ))]
2415     /// The implementation supports the Prioritized Input and Output option.
2416     _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
2417     /// The implementation supports the Process Scheduling option.
2418     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2419     _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING,
2420     #[cfg(any(
2421         freebsdlike,
2422         solarish,
2423         apple_targets,
2424         target_os = "linux",
2425         target_os = "openbsd",
2426     ))]
2427     /// The implementation supports the Raw Sockets option.
2428     _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
2429     #[cfg(any(
2430         bsd,
2431         solarish,
2432         target_os = "linux",
2433     ))]
2434     /// The implementation supports read-write locks.
2435     _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS,
2436     #[cfg(any(
2437         linux_android,
2438         freebsdlike,
2439         apple_targets,
2440         target_os = "openbsd"
2441     ))]
2442     /// The implementation supports realtime signals.
2443     _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS,
2444     #[cfg(any(
2445         bsd,
2446         solarish,
2447         target_os = "linux",
2448     ))]
2449     /// The implementation supports the Regular Expression Handling option.
2450     _POSIX_REGEXP = libc::_SC_REGEXP,
2451     /// Each process has a saved set-user-ID and a saved set-group-ID.
2452     #[cfg(not(target_os = "redox"))]
2453     _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
2454     /// The implementation supports semaphores.
2455     #[cfg(not(target_os = "redox"))]
2456     _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
2457     /// The implementation supports the Shared Memory Objects option.
2458     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2459     _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
2460     #[cfg(any(bsd, target_os = "linux",))]
2461     /// The implementation supports the POSIX shell.
2462     _POSIX_SHELL = libc::_SC_SHELL,
2463     #[cfg(any(bsd, target_os = "linux",))]
2464     /// The implementation supports the Spawn option.
2465     _POSIX_SPAWN = libc::_SC_SPAWN,
2466     #[cfg(any(bsd, target_os = "linux",))]
2467     /// The implementation supports spin locks.
2468     _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
2469     #[cfg(any(
2470         freebsdlike,
2471         apple_targets,
2472         target_os = "linux",
2473         target_os = "openbsd"
2474     ))]
2475     /// The implementation supports the Process Sporadic Server option.
2476     _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
2477     /// The number of replenishment operations that can be simultaneously pending for a particular
2478     /// sporadic server scheduler.
2479     #[cfg(any(
2480         apple_targets,
2481         target_os = "linux",
2482         target_os = "openbsd"
2483     ))]
2484     _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
2485     /// The implementation supports the Synchronized Input and Output option.
2486     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2487     _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
2488     /// The implementation supports the Thread Stack Address Attribute option.
2489     #[cfg(not(target_os = "redox"))]
2490     _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
2491     /// The implementation supports the Thread Stack Size Attribute option.
2492     #[cfg(not(target_os = "redox"))]
2493     _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
2494     #[cfg(any(
2495         apple_targets,
2496         target_os = "linux",
2497         netbsdlike,
2498     ))]
2499     /// The implementation supports the Thread CPU-Time Clocks option.
2500     _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
2501     /// The implementation supports the Non-Robust Mutex Priority Inheritance
2502     /// option.
2503     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2504     _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
2505     /// The implementation supports the Non-Robust Mutex Priority Protection option.
2506     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2507     _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
2508     /// The implementation supports the Thread Execution Scheduling option.
2509     #[cfg(not(target_os = "redox"))]
2510     _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
2511     #[cfg(any(bsd, target_os = "linux"))]
2512     /// The implementation supports the Thread Process-Shared Synchronization
2513     /// option.
2514     _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
2515     #[cfg(any(
2516         target_os = "dragonfly",
2517         target_os = "linux",
2518         target_os = "openbsd"
2519     ))]
2520     /// The implementation supports the Robust Mutex Priority Inheritance option.
2521     _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
2522     #[cfg(any(
2523         target_os = "dragonfly",
2524         target_os = "linux",
2525         target_os = "openbsd"
2526     ))]
2527     /// The implementation supports the Robust Mutex Priority Protection option.
2528     _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
2529     /// The implementation supports thread-safe functions.
2530     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2531     _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
2532     #[cfg(any(
2533         freebsdlike,
2534         apple_targets,
2535         target_os = "linux",
2536         target_os = "openbsd"
2537     ))]
2538     /// The implementation supports the Thread Sporadic Server option.
2539     _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
2540     /// The implementation supports threads.
2541     #[cfg(not(target_os = "redox"))]
2542     _POSIX_THREADS = libc::_SC_THREADS,
2543     #[cfg(any(
2544         freebsdlike,
2545         apple_targets,
2546         target_os = "linux",
2547         target_os = "openbsd"
2548     ))]
2549     /// The implementation supports timeouts.
2550     _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
2551     /// The implementation supports timers.
2552     #[cfg(not(target_os = "redox"))]
2553     _POSIX_TIMERS = libc::_SC_TIMERS,
2554     #[cfg(any(
2555         freebsdlike,
2556         apple_targets,
2557         target_os = "linux",
2558         target_os = "openbsd"
2559     ))]
2560     /// The implementation supports the Trace option.
2561     _POSIX_TRACE = libc::_SC_TRACE,
2562     #[cfg(any(
2563         freebsdlike,
2564         apple_targets,
2565         target_os = "linux",
2566         target_os = "openbsd"
2567     ))]
2568     /// The implementation supports the Trace Event Filter option.
2569     _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
2570     /// Maximum size of a trace event name in characters.
2571     #[cfg(any(
2572         apple_targets,
2573         target_os = "linux",
2574         target_os = "openbsd"
2575     ))]
2576     _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
2577     #[cfg(any(
2578         freebsdlike,
2579         apple_targets,
2580         target_os = "linux",
2581         target_os = "openbsd"
2582     ))]
2583     /// The implementation supports the Trace Inherit option.
2584     _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
2585     #[cfg(any(
2586         freebsdlike,
2587         apple_targets,
2588         target_os = "linux",
2589         target_os = "openbsd"
2590     ))]
2591     /// The implementation supports the Trace Log option.
2592     _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
2593     /// The length in bytes of a trace generation version string or a trace stream name.
2594     #[cfg(any(
2595         apple_targets,
2596         target_os = "linux",
2597         target_os = "openbsd"
2598     ))]
2599     _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
2600     /// Maximum number of times `posix_trace_create` may be called from the same or different
2601     /// processes.
2602     #[cfg(any(
2603         apple_targets,
2604         target_os = "linux",
2605         target_os = "openbsd"
2606     ))]
2607     _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
2608     /// Maximum number of user trace event type identifiers for a single process.
2609     #[cfg(any(
2610         apple_targets,
2611         target_os = "linux",
2612         target_os = "openbsd"
2613     ))]
2614     _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
2615     #[cfg(any(
2616         freebsdlike,
2617         apple_targets,
2618         target_os = "linux",
2619         target_os = "openbsd"
2620     ))]
2621     /// The implementation supports the Typed Memory Objects option.
2622     _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
2623     /// Integer value indicating version of this standard (C-language binding)
2624     /// to which the implementation conforms. For implementations conforming to
2625     /// POSIX.1-2008, the value shall be 200809L.
2626     _POSIX_VERSION = libc::_SC_VERSION,
2627     #[cfg(any(bsd, target_os = "linux"))]
2628     /// The implementation provides a C-language compilation environment with
2629     /// 32-bit `int`, `long`, `pointer`, and `off_t` types.
2630     _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
2631     #[cfg(any(bsd, target_os = "linux"))]
2632     /// The implementation provides a C-language compilation environment with
2633     /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
2634     /// least 64 bits.
2635     _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
2636     #[cfg(any(bsd, target_os = "linux"))]
2637     /// The implementation provides a C-language compilation environment with
2638     /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
2639     _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
2640     #[cfg(any(bsd, target_os = "linux"))]
2641     /// The implementation provides a C-language compilation environment with an
2642     /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
2643     /// using at least 64 bits.
2644     _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
2645     /// The implementation supports the C-Language Binding option.
2646     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2647     _POSIX2_C_BIND = libc::_SC_2_C_BIND,
2648     /// The implementation supports the C-Language Development Utilities option.
2649     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2650     _POSIX2_C_DEV = libc::_SC_2_C_DEV,
2651     /// The implementation supports the Terminal Characteristics option.
2652     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2653     _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
2654     /// The implementation supports the FORTRAN Development Utilities option.
2655     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2656     _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
2657     /// The implementation supports the FORTRAN Runtime Utilities option.
2658     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2659     _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
2660     /// The implementation supports the creation of locales by the localedef
2661     /// utility.
2662     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2663     _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
2664     #[cfg(any(bsd, target_os = "linux"))]
2665     /// The implementation supports the Batch Environment Services and Utilities
2666     /// option.
2667     _POSIX2_PBS = libc::_SC_2_PBS,
2668     #[cfg(any(bsd, target_os = "linux"))]
2669     /// The implementation supports the Batch Accounting option.
2670     _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
2671     #[cfg(any(bsd, target_os = "linux"))]
2672     /// The implementation supports the Batch Checkpoint/Restart option.
2673     _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
2674     #[cfg(any(bsd, target_os = "linux"))]
2675     /// The implementation supports the Locate Batch Job Request option.
2676     _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
2677     #[cfg(any(bsd, target_os = "linux"))]
2678     /// The implementation supports the Batch Job Message Request option.
2679     _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
2680     #[cfg(any(bsd, target_os = "linux"))]
2681     /// The implementation supports the Track Batch Job Request option.
2682     _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
2683     /// The implementation supports the Software Development Utilities option.
2684     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2685     _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
2686     /// The implementation supports the User Portability Utilities option.
2687     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2688     _POSIX2_UPE = libc::_SC_2_UPE,
2689     /// Integer value indicating version of the Shell and Utilities volume of
2690     /// POSIX.1 to which the implementation conforms.
2691     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2692     _POSIX2_VERSION = libc::_SC_2_VERSION,
2693     /// The size of a system page in bytes.
2694     ///
2695     /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
2696     /// enum constants to have the same value, so nix omits `PAGESIZE`.
2697     PAGE_SIZE = libc::_SC_PAGE_SIZE,
2698     /// Maximum number of attempts made to destroy a thread's thread-specific data values on thread
2699     /// exit.
2700     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2701     PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
2702     /// Maximum number of data keys that can be created by a process.
2703     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2704     PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
2705     /// Minimum size in bytes of thread stack storage.
2706     #[cfg(not(target_os = "redox"))]
2707     PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
2708     /// Maximum number of threads that can be created per process.
2709     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2710     PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
2711     /// The maximum number of repeated occurrences of a regular expression permitted when using
2712     /// interval notation.
2713     #[cfg(not(target_os = "haiku"))]
2714     RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
2715     /// Maximum number of realtime signals reserved for application use.
2716     #[cfg(any(
2717         linux_android,
2718         freebsdlike,
2719         apple_targets,
2720         target_os = "openbsd"
2721     ))]
2722     RTSIG_MAX = libc::_SC_RTSIG_MAX,
2723     /// Maximum number of semaphores that a process may have.
2724     #[cfg(not(target_os = "redox"))]
2725     SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
2726     /// The maximum value a semaphore may have.
2727     #[cfg(any(
2728         linux_android,
2729         freebsdlike,
2730         apple_targets,
2731         target_os = "openbsd"
2732     ))]
2733     SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
2734     /// Maximum number of queued signals that a process may send and have pending at the
2735     /// receiver(s) at any time.
2736     #[cfg(any(
2737         linux_android,
2738         freebsdlike,
2739         apple_targets,
2740         target_os = "openbsd"
2741     ))]
2742     SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
2743     /// The minimum maximum number of streams that a process may have open at any one time.
2744     STREAM_MAX = libc::_SC_STREAM_MAX,
2745     /// Maximum number of symbolic links that can be reliably traversed in the resolution of a
2746     /// pathname in the absence of a loop.
2747     #[cfg(any(bsd, target_os = "linux"))]
2748     SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
2749     /// Maximum number of timers per process supported.
2750     #[cfg(not(target_os = "redox"))]
2751     TIMER_MAX = libc::_SC_TIMER_MAX,
2752     /// Maximum length of terminal device name.
2753     TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
2754     /// The minimum maximum number of types supported for the name of a timezone.
2755     TZNAME_MAX = libc::_SC_TZNAME_MAX,
2756     #[cfg(any(
2757         linux_android,
2758         freebsdlike,
2759         apple_targets,
2760         target_os = "openbsd"
2761     ))]
2762     /// The implementation supports the X/Open Encryption Option Group.
2763     _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
2764     #[cfg(any(
2765         linux_android,
2766         freebsdlike,
2767         apple_targets,
2768         target_os = "openbsd"
2769     ))]
2770     /// The implementation supports the Issue 4, Version 2 Enhanced
2771     /// Internationalization Option Group.
2772     _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
2773     #[cfg(any(
2774         linux_android,
2775         freebsdlike,
2776         apple_targets,
2777         target_os = "openbsd"
2778     ))]
2779     /// The implementation supports the XOpen Legacy Option group.
2780     ///
2781     /// See Also <https://pubs.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap02.html>
2782     _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
2783     #[cfg(any(
2784         linux_android,
2785         freebsdlike,
2786         apple_targets,
2787         target_os = "openbsd"
2788     ))]
2789     /// The implementation supports the X/Open Realtime Option Group.
2790     _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
2791     #[cfg(any(
2792         linux_android,
2793         freebsdlike,
2794         apple_targets,
2795         target_os = "openbsd"
2796     ))]
2797     /// The implementation supports the X/Open Realtime Threads Option Group.
2798     _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
2799     /// The implementation supports the Issue 4, Version 2 Shared Memory Option
2800     /// Group.
2801     #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
2802     _XOPEN_SHM = libc::_SC_XOPEN_SHM,
2803     #[cfg(any(
2804         freebsdlike,
2805         apple_targets,
2806         target_os = "linux",
2807         target_os = "openbsd"
2808     ))]
2809     /// The implementation supports the XSI STREAMS Option Group.
2810     _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
2811     #[cfg(any(
2812         linux_android,
2813         freebsdlike,
2814         apple_targets,
2815         target_os = "openbsd"
2816     ))]
2817     /// The implementation supports the XSI option
2818     _XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
2819     #[cfg(any(
2820         linux_android,
2821         freebsdlike,
2822         apple_targets,
2823         target_os = "openbsd"
2824     ))]
2825     /// Integer value indicating version of the X/Open Portability Guide to
2826     /// which the implementation conforms.
2827     _XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
2828     /// The number of pages of physical memory. Note that it is possible for
2829     /// the product of this value to overflow.
2830     #[cfg(linux_android)]
2831     _PHYS_PAGES = libc::_SC_PHYS_PAGES,
2832     /// The number of currently available pages of physical memory.
2833     #[cfg(linux_android)]
2834     _AVPHYS_PAGES = libc::_SC_AVPHYS_PAGES,
2835     /// The number of processors configured.
2836     #[cfg(linux_android)]
2837     _NPROCESSORS_CONF = libc::_SC_NPROCESSORS_CONF,
2838     /// The number of processors currently online (available).
2839     #[cfg(linux_android)]
2840     _NPROCESSORS_ONLN = libc::_SC_NPROCESSORS_ONLN,
2841 }
2842 
2843 /// Get configurable system variables (see
2844 /// [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
2845 ///
2846 /// Returns the value of a configurable system variable.  Most supported
2847 /// variables also have associated compile-time constants, but POSIX
2848 /// allows their values to change at runtime.  There are generally two types of
2849 /// sysconf variables: options and limits.  See sysconf(3) for more details.
2850 ///
2851 /// # Returns
2852 ///
2853 /// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
2854 ///     implementation level (for option variables).  Implementation levels are
2855 ///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
2856 /// - `Ok(None)`: the variable has no limit (for limit variables) or is
2857 ///     unsupported (for option variables)
2858 /// - `Err(x)`: an error occurred
2859 pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
2860     let raw = unsafe {
2861         Errno::clear();
2862         libc::sysconf(var as c_int)
2863     };
2864     if raw == -1 {
2865         if Errno::last_raw() == 0 {
2866             Ok(None)
2867         } else {
2868             Err(Errno::last())
2869         }
2870     } else {
2871         Ok(Some(raw))
2872     }
2873 }
2874 }
2875 
2876 #[cfg(linux_android)]
2877 #[cfg(feature = "fs")]
2878 mod pivot_root {
2879     use crate::errno::Errno;
2880     use crate::{NixPath, Result};
2881 
2882     /// Change the root file system.
2883     ///
2884     /// See Also [`pivot_root`](https://man7.org/linux/man-pages/man2/pivot_root.2.html)
pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>( new_root: &P1, put_old: &P2, ) -> Result<()>2885     pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
2886         new_root: &P1,
2887         put_old: &P2,
2888     ) -> Result<()> {
2889         let res = new_root.with_nix_path(|new_root| {
2890             put_old.with_nix_path(|put_old| unsafe {
2891                 libc::syscall(
2892                     libc::SYS_pivot_root,
2893                     new_root.as_ptr(),
2894                     put_old.as_ptr(),
2895                 )
2896             })
2897         })??;
2898 
2899         Errno::result(res).map(drop)
2900     }
2901 }
2902 
2903 #[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
2904 mod setres {
2905     feature! {
2906     #![feature = "user"]
2907 
2908     use super::{Gid, Uid};
2909     use crate::errno::Errno;
2910     use crate::Result;
2911 
2912     /// Sets the real, effective, and saved uid.
2913     /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
2914     ///
2915     /// * `ruid`: real user id
2916     /// * `euid`: effective user id
2917     /// * `suid`: saved user id
2918     /// * returns: Ok or libc error code.
2919     ///
2920     /// Err is returned if the user doesn't have permission to set this UID.
2921     #[inline]
2922     pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
2923         let res =
2924             unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
2925 
2926         Errno::result(res).map(drop)
2927     }
2928 
2929     /// Sets the real, effective, and saved gid.
2930     /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
2931     ///
2932     /// * `rgid`: real group id
2933     /// * `egid`: effective group id
2934     /// * `sgid`: saved group id
2935     /// * returns: Ok or libc error code.
2936     ///
2937     /// Err is returned if the user doesn't have permission to set this GID.
2938     #[inline]
2939     pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
2940         let res =
2941             unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
2942 
2943         Errno::result(res).map(drop)
2944     }
2945     }
2946 }
2947 
2948 #[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
2949 mod getres {
2950     feature! {
2951     #![feature = "user"]
2952 
2953     use super::{Gid, Uid};
2954     use crate::errno::Errno;
2955     use crate::Result;
2956 
2957     /// Real, effective and saved user IDs.
2958     #[derive(Debug, Copy, Clone, Eq, PartialEq)]
2959     pub struct ResUid {
2960         /// Real UID
2961         pub real: Uid,
2962         /// Effective UID
2963         pub effective: Uid,
2964         /// Saved UID
2965         pub saved: Uid,
2966     }
2967 
2968     /// Real, effective and saved group IDs.
2969     #[derive(Debug, Copy, Clone, Eq, PartialEq)]
2970     pub struct ResGid {
2971         /// Real GID
2972         pub real: Gid,
2973         /// Effective GID
2974         pub effective: Gid,
2975         /// Saved GID
2976         pub saved: Gid,
2977     }
2978 
2979     /// Gets the real, effective, and saved user IDs.
2980     ///
2981     /// ([see getresuid(2)](http://man7.org/linux/man-pages/man2/getresuid.2.html))
2982     ///
2983     /// #Returns
2984     ///
2985     /// - `Ok((Uid, Uid, Uid))`: tuple of real, effective and saved uids on success.
2986     /// - `Err(x)`: libc error code on failure.
2987     ///
2988     #[inline]
2989     pub fn getresuid() -> Result<ResUid> {
2990         let mut ruid = libc::uid_t::MAX;
2991         let mut euid = libc::uid_t::MAX;
2992         let mut suid = libc::uid_t::MAX;
2993         let res = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) };
2994 
2995         Errno::result(res).map(|_| ResUid {
2996             real: Uid(ruid),
2997             effective: Uid(euid),
2998             saved: Uid(suid),
2999         })
3000     }
3001 
3002     /// Gets the real, effective, and saved group IDs.
3003     ///
3004     /// ([see getresgid(2)](http://man7.org/linux/man-pages/man2/getresgid.2.html))
3005     ///
3006     /// #Returns
3007     ///
3008     /// - `Ok((Gid, Gid, Gid))`: tuple of real, effective and saved gids on success.
3009     /// - `Err(x)`: libc error code on failure.
3010     ///
3011     #[inline]
3012     pub fn getresgid() -> Result<ResGid> {
3013         let mut rgid = libc::gid_t::MAX;
3014         let mut egid = libc::gid_t::MAX;
3015         let mut sgid = libc::gid_t::MAX;
3016         let res = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) };
3017 
3018         Errno::result(res).map(|_| ResGid {
3019             real: Gid(rgid),
3020             effective: Gid(egid),
3021             saved: Gid(sgid),
3022         })
3023     }
3024     }
3025 }
3026 
3027 #[cfg(feature = "process")]
3028 #[cfg(target_os = "freebsd")]
3029 libc_bitflags! {
3030     /// Flags for [`rfork`]
3031     ///
3032     /// subset of flags supported by FreeBSD 12.x and onwards
3033     /// with a safe outcome, thus as `RFMEM` can possibly lead to undefined behavior,
3034     /// it is not in the list. And `rfork_thread` is deprecated.
3035     pub struct RforkFlags: libc::c_int {
3036         /// creates a new process.
3037         RFPROC;
3038         /// the child process will detach from the parent.
3039         /// however, no status will be emitted at child's exit.
3040         RFNOWAIT;
3041         /// the file descriptor's table will be copied
3042         RFFDG;
3043         /// a new file descriptor's table will be created
3044         RFCFDG;
3045         /// force sharing the sigacts structure between
3046         /// the child and the parent.
3047         RFSIGSHARE;
3048         /// enables kernel thread support.
3049         RFTHREAD;
3050         /// sets a status to emit at child's exit.
3051         RFTSIGZMB;
3052         /// linux's behavior compatibility setting.
3053         /// emits SIGUSR1 as opposed to SIGCHLD upon child's exit.
3054         RFLINUXTHPN;
3055     }
3056 }
3057 
3058 feature! {
3059 #![feature = "process"]
3060 #[cfg(target_os = "freebsd")]
3061 /// Like [`fork`], `rfork` can be used to have a tigher control about which
3062 /// resources child and parent process will be sharing, file descriptors,
3063 /// address spaces and child exit's behavior.
3064 ///
3065 /// # Safety
3066 ///
3067 /// The same restrictions apply as for [`fork`].
3068 ///
3069 /// # See Also
3070 ///
3071 /// * [rfork(2)](https://man.freebsd.org/cgi/man.cgi?query=rfork)
3072 pub unsafe fn rfork(flags: RforkFlags) -> Result<ForkResult> {
3073     use ForkResult::*;
3074     let res = unsafe { libc::rfork(flags.bits()) };
3075 
3076     Errno::result(res).map(|res| match res {
3077         0 => Child,
3078         res => Parent { child: Pid(res) },
3079     })
3080 }
3081 }
3082 
3083 #[cfg(feature = "fs")]
3084 libc_bitflags! {
3085     /// Options for access()
3086     #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
3087     pub struct AccessFlags : c_int {
3088         /// Test for existence of file.
3089         F_OK;
3090         /// Test for read permission.
3091         R_OK;
3092         /// Test for write permission.
3093         W_OK;
3094         /// Test for execute (search) permission.
3095         X_OK;
3096     }
3097 }
3098 
3099 feature! {
3100 #![feature = "fs"]
3101 
3102 /// Checks the file named by `path` for accessibility according to the flags given by `amode`
3103 /// See [access(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
3104 pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
3105     let res = path.with_nix_path(|cstr| unsafe {
3106         libc::access(cstr.as_ptr(), amode.bits())
3107     })?;
3108     Errno::result(res).map(drop)
3109 }
3110 
3111 /// Checks the file named by `path` for accessibility according to the flags given by `mode`
3112 ///
3113 /// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
3114 ///
3115 /// If `dirfd` is `None`, then `path` is relative to the current working directory.
3116 ///
3117 /// # References
3118 ///
3119 /// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html)
3120 // redox: does not appear to support the *at family of syscalls.
3121 #[cfg(not(target_os = "redox"))]
3122 pub fn faccessat<P: ?Sized + NixPath>(
3123     dirfd: Option<RawFd>,
3124     path: &P,
3125     mode: AccessFlags,
3126     flags: AtFlags,
3127 ) -> Result<()> {
3128     let res = path.with_nix_path(|cstr| unsafe {
3129         libc::faccessat(
3130             at_rawfd(dirfd),
3131             cstr.as_ptr(),
3132             mode.bits(),
3133             flags.bits(),
3134         )
3135     })?;
3136     Errno::result(res).map(drop)
3137 }
3138 
3139 /// Checks the file named by `path` for accessibility according to the flags given
3140 /// by `mode` using effective UID, effective GID and supplementary group lists.
3141 ///
3142 /// # References
3143 ///
3144 /// * [FreeBSD man page](https://www.freebsd.org/cgi/man.cgi?query=eaccess&sektion=2&n=1)
3145 /// * [Linux man page](https://man7.org/linux/man-pages/man3/euidaccess.3.html)
3146 #[cfg(any(
3147     freebsdlike,
3148     all(target_os = "linux", not(target_env = "uclibc")),
3149 ))]
3150 pub fn eaccess<P: ?Sized + NixPath>(path: &P, mode: AccessFlags) -> Result<()> {
3151     let res = path.with_nix_path(|cstr| unsafe {
3152         libc::eaccess(cstr.as_ptr(), mode.bits())
3153     })?;
3154     Errno::result(res).map(drop)
3155 }
3156 }
3157 
3158 feature! {
3159 #![feature = "user"]
3160 
3161 /// Representation of a User, based on `libc::passwd`
3162 ///
3163 /// The reason some fields in this struct are `String` and others are `CString` is because some
3164 /// fields are based on the user's locale, which could be non-UTF8, while other fields are
3165 /// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only
3166 /// contains ASCII.
3167 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3168 #[derive(Debug, Clone, Eq, PartialEq)]
3169 pub struct User {
3170     /// Username
3171     pub name: String,
3172     /// User password (probably hashed)
3173     pub passwd: CString,
3174     /// User ID
3175     pub uid: Uid,
3176     /// Group ID
3177     pub gid: Gid,
3178     /// User information
3179     #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
3180     pub gecos: CString,
3181     /// Home directory
3182     pub dir: PathBuf,
3183     /// Path to shell
3184     pub shell: PathBuf,
3185     /// Login class
3186     #[cfg(not(any(
3187         linux_android,
3188         solarish,
3189         target_os = "aix",
3190         target_os = "fuchsia",
3191         target_os = "haiku",
3192         target_os = "hurd",
3193     )))]
3194     pub class: CString,
3195     /// Last password change
3196     #[cfg(not(any(
3197         linux_android,
3198         solarish,
3199         target_os = "aix",
3200         target_os = "fuchsia",
3201         target_os = "haiku",
3202         target_os = "hurd",
3203     )))]
3204     pub change: libc::time_t,
3205     /// Expiration time of account
3206     #[cfg(not(any(
3207         linux_android,
3208         solarish,
3209         target_os = "aix",
3210         target_os = "fuchsia",
3211         target_os = "haiku",
3212         target_os = "hurd",
3213     )))]
3214     pub expire: libc::time_t,
3215 }
3216 
3217 #[cfg(not(target_os = "redox"))] //RedoxFS does not support passwd
3218 impl From<&libc::passwd> for User {
3219     fn from(pw: &libc::passwd) -> User {
3220         unsafe {
3221             User {
3222                 name: if pw.pw_name.is_null() {
3223                     Default::default()
3224                 } else {
3225                     CStr::from_ptr(pw.pw_name).to_string_lossy().into_owned()
3226                 },
3227                 passwd: if pw.pw_passwd.is_null() {
3228                     Default::default()
3229                 } else {
3230                     CString::new(CStr::from_ptr(pw.pw_passwd).to_bytes())
3231                         .unwrap()
3232                 },
3233                 #[cfg(not(all(
3234                     target_os = "android",
3235                     target_pointer_width = "32"
3236                 )))]
3237                 gecos: if pw.pw_gecos.is_null() {
3238                     Default::default()
3239                 } else {
3240                     CString::new(CStr::from_ptr(pw.pw_gecos).to_bytes())
3241                         .unwrap()
3242                 },
3243                 dir: if pw.pw_dir.is_null() {
3244                     Default::default()
3245                 } else {
3246                     PathBuf::from(OsStr::from_bytes(
3247                         CStr::from_ptr(pw.pw_dir).to_bytes(),
3248                     ))
3249                 },
3250                 shell: if pw.pw_shell.is_null() {
3251                     Default::default()
3252                 } else {
3253                     PathBuf::from(OsStr::from_bytes(
3254                         CStr::from_ptr(pw.pw_shell).to_bytes(),
3255                     ))
3256                 },
3257                 uid: Uid::from_raw(pw.pw_uid),
3258                 gid: Gid::from_raw(pw.pw_gid),
3259                 #[cfg(not(any(
3260                     linux_android,
3261                     solarish,
3262                     target_os = "aix",
3263                     target_os = "fuchsia",
3264                     target_os = "haiku",
3265                     target_os = "hurd",
3266                 )))]
3267                 class: CString::new(CStr::from_ptr(pw.pw_class).to_bytes())
3268                     .unwrap(),
3269                 #[cfg(not(any(
3270                     linux_android,
3271                     solarish,
3272                     target_os = "aix",
3273                     target_os = "fuchsia",
3274                     target_os = "haiku",
3275                     target_os = "hurd",
3276                 )))]
3277                 change: pw.pw_change,
3278                 #[cfg(not(any(
3279                     linux_android,
3280                     solarish,
3281                     target_os = "aix",
3282                     target_os = "fuchsia",
3283                     target_os = "haiku",
3284                     target_os = "hurd",
3285                 )))]
3286                 expire: pw.pw_expire,
3287             }
3288         }
3289     }
3290 }
3291 
3292 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3293 impl From<User> for libc::passwd {
3294     fn from(u: User) -> Self {
3295         let name = match CString::new(u.name) {
3296             Ok(n) => n.into_raw(),
3297             Err(_) => CString::new("").unwrap().into_raw(),
3298         };
3299         let dir = match u.dir.into_os_string().into_string() {
3300             Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
3301             Err(_) => CString::new("").unwrap().into_raw(),
3302         };
3303         let shell = match u.shell.into_os_string().into_string() {
3304             Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
3305             Err(_) => CString::new("").unwrap().into_raw(),
3306         };
3307         Self {
3308             pw_name: name,
3309             pw_passwd: u.passwd.into_raw(),
3310             #[cfg(not(all(
3311                 target_os = "android",
3312                 target_pointer_width = "32"
3313             )))]
3314             pw_gecos: u.gecos.into_raw(),
3315             pw_dir: dir,
3316             pw_shell: shell,
3317             pw_uid: u.uid.0,
3318             pw_gid: u.gid.0,
3319             #[cfg(not(any(
3320                 linux_android,
3321                 solarish,
3322                 target_os = "aix",
3323                 target_os = "fuchsia",
3324                 target_os = "haiku",
3325                 target_os = "hurd",
3326             )))]
3327             pw_class: u.class.into_raw(),
3328             #[cfg(not(any(
3329                 linux_android,
3330                 solarish,
3331                 target_os = "aix",
3332                 target_os = "fuchsia",
3333                 target_os = "haiku",
3334                 target_os = "hurd",
3335             )))]
3336             pw_change: u.change,
3337             #[cfg(not(any(
3338                 linux_android,
3339                 solarish,
3340                 target_os = "aix",
3341                 target_os = "fuchsia",
3342                 target_os = "haiku",
3343                 target_os = "hurd",
3344             )))]
3345             pw_expire: u.expire,
3346             #[cfg(solarish)]
3347             pw_age: CString::new("").unwrap().into_raw(),
3348             #[cfg(solarish)]
3349             pw_comment: CString::new("").unwrap().into_raw(),
3350             #[cfg(freebsdlike)]
3351             pw_fields: 0,
3352         }
3353     }
3354 }
3355 
3356 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3357 impl User {
3358     /// # Safety
3359     ///
3360     /// If `f` writes to its `*mut *mut libc::passwd` parameter, then it must
3361     /// also initialize the value pointed to by its `*mut libc::group`
3362     /// parameter.
3363     unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
3364     where
3365         F: Fn(
3366             *mut libc::passwd,
3367             *mut c_char,
3368             libc::size_t,
3369             *mut *mut libc::passwd,
3370         ) -> libc::c_int,
3371     {
3372         let buflimit = 1048576;
3373         let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
3374             Ok(Some(n)) => n as usize,
3375             Ok(None) | Err(_) => 16384,
3376         };
3377 
3378         let mut cbuf = Vec::with_capacity(bufsize);
3379         let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
3380         let mut res = ptr::null_mut();
3381 
3382         loop {
3383             let error = f(
3384                 pwd.as_mut_ptr(),
3385                 cbuf.as_mut_ptr(),
3386                 cbuf.capacity(),
3387                 &mut res,
3388             );
3389             if error == 0 {
3390                 if res.is_null() {
3391                     return Ok(None);
3392                 } else {
3393                     // SAFETY: `f` guarantees that `pwd` is initialized if `res`
3394                     // is not null.
3395                     let pwd = unsafe { pwd.assume_init() };
3396                     return Ok(Some(User::from(&pwd)));
3397                 }
3398             } else if Errno::last() == Errno::ERANGE {
3399                 // Trigger the internal buffer resizing logic.
3400                 reserve_double_buffer_size(&mut cbuf, buflimit)?;
3401             } else {
3402                 return Err(Errno::last());
3403             }
3404         }
3405     }
3406 
3407     /// Get a user by UID.
3408     ///
3409     /// Internally, this function calls
3410     /// [getpwuid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
3411     ///
3412     /// # Examples
3413     ///
3414     /// ```
3415     /// use nix::unistd::{Uid, User};
3416     /// // Returns an Result<Option<User>>, thus the double unwrap.
3417     /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
3418     /// assert_eq!(res.name, "root");
3419     /// ```
3420     pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
3421         // SAFETY: `getpwuid_r` will write to `res` if it initializes the value
3422         // at `pwd`.
3423         unsafe {
3424             User::from_anything(|pwd, cbuf, cap, res| {
3425                 libc::getpwuid_r(uid.0, pwd, cbuf, cap, res)
3426             })
3427         }
3428     }
3429 
3430     /// Get a user by name.
3431     ///
3432     /// Internally, this function calls
3433     /// [getpwnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwnam_r.html)
3434     ///
3435     /// # Examples
3436     ///
3437     /// ```
3438     /// use nix::unistd::User;
3439     /// // Returns an Result<Option<User>>, thus the double unwrap.
3440     /// let res = User::from_name("root").unwrap().unwrap();
3441     /// assert_eq!(res.name, "root");
3442     /// ```
3443     pub fn from_name(name: &str) -> Result<Option<Self>> {
3444         let name = match CString::new(name) {
3445             Ok(c_str) => c_str,
3446             Err(_nul_error) => return Ok(None),
3447         };
3448         // SAFETY: `getpwnam_r` will write to `res` if it initializes the value
3449         // at `pwd`.
3450         unsafe {
3451             User::from_anything(|pwd, cbuf, cap, res| {
3452                 libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res)
3453             })
3454         }
3455     }
3456 }
3457 
3458 /// Representation of a Group, based on `libc::group`
3459 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3460 #[derive(Debug, Clone, Eq, PartialEq)]
3461 pub struct Group {
3462     /// Group name
3463     pub name: String,
3464     /// Group password
3465     pub passwd: CString,
3466     /// Group ID
3467     pub gid: Gid,
3468     /// List of Group members
3469     pub mem: Vec<String>,
3470 }
3471 
3472 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3473 impl From<&libc::group> for Group {
3474     fn from(gr: &libc::group) -> Group {
3475         unsafe {
3476             Group {
3477                 name: if gr.gr_name.is_null() {
3478                     Default::default()
3479                 } else {
3480                     CStr::from_ptr(gr.gr_name).to_string_lossy().into_owned()
3481                 },
3482                 passwd: if gr.gr_passwd.is_null() {
3483                     Default::default()
3484                 } else {
3485                     CString::new(CStr::from_ptr(gr.gr_passwd).to_bytes())
3486                         .unwrap()
3487                 },
3488                 gid: Gid::from_raw(gr.gr_gid),
3489                 mem: if gr.gr_mem.is_null() {
3490                     Default::default()
3491                 } else {
3492                     Group::members(gr.gr_mem)
3493                 },
3494             }
3495         }
3496     }
3497 }
3498 
3499 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
3500 impl Group {
3501     unsafe fn members(mem: *mut *mut c_char) -> Vec<String> {
3502         let mut ret = Vec::new();
3503 
3504         for i in 0.. {
3505             let u = unsafe { mem.offset(i).read_unaligned() };
3506             if u.is_null() {
3507                 break;
3508             } else {
3509                 let s = unsafe {CStr::from_ptr(u).to_string_lossy().into_owned()};
3510                 ret.push(s);
3511             }
3512         }
3513 
3514         ret
3515     }
3516     /// # Safety
3517     ///
3518     /// If `f` writes to its `*mut *mut libc::group` parameter, then it must
3519     /// also initialize the value pointed to by its `*mut libc::group`
3520     /// parameter.
3521     unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
3522     where
3523         F: Fn(
3524             *mut libc::group,
3525             *mut c_char,
3526             libc::size_t,
3527             *mut *mut libc::group,
3528         ) -> libc::c_int,
3529     {
3530         let buflimit = 1048576;
3531         let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
3532             Ok(Some(n)) => n as usize,
3533             Ok(None) | Err(_) => 16384,
3534         };
3535 
3536         let mut cbuf = Vec::with_capacity(bufsize);
3537         let mut grp = mem::MaybeUninit::<libc::group>::uninit();
3538         let mut res = ptr::null_mut();
3539 
3540         loop {
3541             let error = f(
3542                 grp.as_mut_ptr(),
3543                 cbuf.as_mut_ptr(),
3544                 cbuf.capacity(),
3545                 &mut res,
3546             );
3547             if error == 0 {
3548                 if res.is_null() {
3549                     return Ok(None);
3550                 } else {
3551                     // SAFETY: `f` guarantees that `grp` is initialized if `res`
3552                     // is not null.
3553                     let grp = unsafe { grp.assume_init() };
3554                     return Ok(Some(Group::from(&grp)));
3555                 }
3556             } else if Errno::last() == Errno::ERANGE {
3557                 // Trigger the internal buffer resizing logic.
3558                 reserve_double_buffer_size(&mut cbuf, buflimit)?;
3559             } else {
3560                 return Err(Errno::last());
3561             }
3562         }
3563     }
3564 
3565     /// Get a group by GID.
3566     ///
3567     /// Internally, this function calls
3568     /// [getgrgid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
3569     ///
3570     /// # Examples
3571     ///
3572     // Disable this test on all OS except Linux as root group may not exist.
3573     #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
3574     #[cfg_attr(target_os = "linux", doc = " ```")]
3575     /// use nix::unistd::{Gid, Group};
3576     /// // Returns an Result<Option<Group>>, thus the double unwrap.
3577     /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
3578     /// assert!(res.name == "root");
3579     /// ```
3580     pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
3581         // SAFETY: `getgrgid_r` will write to `res` if it initializes the value
3582         // at `grp`.
3583         unsafe {
3584             Group::from_anything(|grp, cbuf, cap, res| {
3585                 libc::getgrgid_r(gid.0, grp, cbuf, cap, res)
3586             })
3587         }
3588     }
3589 
3590     /// Get a group by name.
3591     ///
3592     /// Internally, this function calls
3593     /// [getgrnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
3594     ///
3595     /// # Examples
3596     ///
3597     // Disable this test on all OS except Linux as root group may not exist.
3598     #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
3599     #[cfg_attr(target_os = "linux", doc = " ```")]
3600     /// use nix::unistd::Group;
3601     /// // Returns an Result<Option<Group>>, thus the double unwrap.
3602     /// let res = Group::from_name("root").unwrap().unwrap();
3603     /// assert!(res.name == "root");
3604     /// ```
3605     pub fn from_name(name: &str) -> Result<Option<Self>> {
3606         let name = match CString::new(name) {
3607             Ok(c_str) => c_str,
3608             Err(_nul_error) => return Ok(None),
3609         };
3610         // SAFETY: `getgrnam_r` will write to `res` if it initializes the value
3611         // at `grp`.
3612         unsafe {
3613             Group::from_anything(|grp, cbuf, cap, res| {
3614                 libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res)
3615             })
3616         }
3617     }
3618 }
3619 }
3620 
3621 feature! {
3622 #![feature = "term"]
3623 
3624 /// Get the name of the terminal device that is open on file descriptor fd
3625 /// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)).
3626 #[cfg(not(target_os = "fuchsia"))]
3627 pub fn ttyname<F: AsFd>(fd: F) -> Result<PathBuf> {
3628     #[cfg(not(target_os = "hurd"))]
3629     const PATH_MAX: usize = libc::PATH_MAX as usize;
3630     #[cfg(target_os = "hurd")]
3631     const PATH_MAX: usize = 1024; // Hurd does not define a hard limit, so try a guess first
3632     let mut buf = vec![0_u8; PATH_MAX];
3633     let c_buf = buf.as_mut_ptr().cast();
3634 
3635     let ret = unsafe { libc::ttyname_r(fd.as_fd().as_raw_fd(), c_buf, buf.len()) };
3636     if ret != 0 {
3637         return Err(Errno::from_raw(ret));
3638     }
3639 
3640     CStr::from_bytes_until_nul(&buf[..])
3641         .map(|s| OsStr::from_bytes(s.to_bytes()).into())
3642         .map_err(|_| Errno::EINVAL)
3643 }
3644 }
3645 
3646 feature! {
3647 #![all(feature = "socket", feature = "user")]
3648 
3649 /// Get the effective user ID and group ID associated with a Unix domain socket.
3650 ///
3651 /// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
3652 #[cfg(bsd)]
3653 pub fn getpeereid<F: AsFd>(fd: F) -> Result<(Uid, Gid)> {
3654     let mut uid = 1;
3655     let mut gid = 1;
3656 
3657     let ret = unsafe { libc::getpeereid(fd.as_fd().as_raw_fd(), &mut uid, &mut gid) };
3658 
3659     Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
3660 }
3661 }
3662 
3663 feature! {
3664 #![all(feature = "fs")]
3665 
3666 /// Set the file flags.
3667 ///
3668 /// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
3669 #[cfg(bsd)]
3670 pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
3671     let res = path.with_nix_path(|cstr| unsafe {
3672         libc::chflags(cstr.as_ptr(), flags.bits())
3673     })?;
3674 
3675     Errno::result(res).map(drop)
3676 }
3677 }
3678