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