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