Skip to content

Commit

Permalink
Auto merge of #449 - posborne:documentation-improvements, r=kamalmarhubi
Browse files Browse the repository at this point in the history
Documentation improvements

This series of commits starts to fill in documentation that was not previously present for various calls, mostly in unistd for this pass.

r? @kamalmarhubi
  • Loading branch information
homu committed Oct 29, 2016
2 parents b05c1e4 + fdf8ab6 commit ff4484d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 7 deletions.
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,40 @@ use std::fmt;
use std::error;
use libc::PATH_MAX;

/// Nix Result Type
pub type Result<T> = result::Result<T, Error>;

/// Nix Error Type
///
/// The nix error type provides a common way of dealing with
/// various system system/libc calls that might fail. Each
/// error has a corresponding errno (usually the one from the
/// underlying OS) to which it can be mapped in addition to
/// implementing other common traits.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
Sys(errno::Errno),
InvalidPath,
}

impl Error {

/// Create a nix Error from a given errno
pub fn from_errno(errno: errno::Errno) -> Error {
Error::Sys(errno)
}

/// Get the current errno and convert it to a nix Error
pub fn last() -> Error {
Error::Sys(errno::Errno::last())
}

/// Create a new invalid argument error (`EINVAL`)
pub fn invalid_argument() -> Error {
Error::Sys(errno::EINVAL)
}

/// Get the errno associated with this error
pub fn errno(&self) -> errno::Errno {
match *self {
Error::Sys(errno) => errno,
Expand Down
122 changes: 115 additions & 7 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@ use sys::stat::Mode;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

/// Represents the successful result of calling `fork`
///
/// When `fork` is called, the process continues execution in the parent process
/// and in the new child. This return type can be examined to determine whether
/// you are now executing in the parent process or in the child.
#[derive(Clone, Copy)]
pub enum ForkResult {
Parent {
child: pid_t
},
Child
Parent { child: pid_t },
Child,
}

impl ForkResult {

/// Return `true` if this is the child process of the `fork()`
#[inline]
pub fn is_child(&self) -> bool {
match *self {
Expand All @@ -32,31 +37,80 @@ impl ForkResult {
}
}

/// Returns `true` if this is the parent process of the `fork()`
#[inline]
pub fn is_parent(&self) -> bool {
!self.is_child()
}
}

/// Create a new child process duplicating the parent process ([see
/// fork(2)](http://man7.org/linux/man-pages/man2/fork.2.html)).
///
/// After calling the fork system call (successfully) two processes will
/// be created that are identical with the exception of their pid and the
/// return value of this function. As an example:
///
/// ```no_run
/// use nix::unistd::{fork, ForkResult};
///
/// match fork() {
/// Ok(ForkResult::Parent { child, .. }) => {
/// println!("Continuing execution in parent process, new child has pid: {}", child);
/// }
/// Ok(ForkResult::Child) => println!("I'm a new child process"),
/// Err(e) => println!("Fork failed"),
/// }
/// ```
///
/// This will print something like the following (order indeterministic). The
/// thing to note is that you end up with two processes continuing execution
/// immediately after the fork call but with different match arms.
///
/// ```text
/// Continuing execution in parent process, new child has pid: 1234
/// I'm a new child process
/// ```
#[inline]
pub fn fork() -> Result<ForkResult> {
use self::ForkResult::*;
let res = unsafe { libc::fork() };

Errno::result(res).map(|res| match res {
0 => Child,
res => Parent { child: res }
res => Parent { child: res },
})
}

/// Get the pid of this process (see
/// [getpid(2)](http://man7.org/linux/man-pages/man2/getpid.2.html)).
///
/// Since you are running code, there is always a pid to return, so there
/// is no error case that needs to be handled.
#[inline]
pub fn getpid() -> pid_t {
unsafe { libc::getpid() } // no error handling, according to man page: "These functions are always successful."
unsafe { libc::getpid() }
}

/// Get the pid of this processes' parent (see
/// [getpid(2)](http://man7.org/linux/man-pages/man2/getpid.2.html)).
///
/// There is always a parent pid to return, so there is no error case that needs
/// to be handled.
#[inline]
pub fn getppid() -> pid_t {
unsafe { libc::getppid() } // no error handling, according to man page: "These functions are always successful."
}

/// Set a process group ID (see
/// [setpgid(2)](http://man7.org/linux/man-pages/man2/setpgid.2.html)).
///
/// Set the process group id (PGID) of a particular process. If a pid of zero
/// is specified, then the pid of the calling process is used. Process groups
/// may be used to group together a set of processes in order for the OS to
/// apply some operations across the group.
///
/// `setsid()` may be used to create a new process group.
#[inline]
pub fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> {
let res = unsafe { libc::setpgid(pid, pgid) };
Expand All @@ -68,26 +122,64 @@ pub fn getpgid(pid: Option<pid_t>) -> Result<pid_t> {
Errno::result(res)
}

/// Create new session and set process group id (see
/// [setsid(2)](http://man7.org/linux/man-pages/man2/setsid.2.html)).
#[inline]
pub fn setsid() -> Result<pid_t> {
Errno::result(unsafe { libc::setsid() })
}

/// Get the caller's thread ID (see
/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
///
/// This function is only available on Linux based systems. In a single
/// threaded process, the main thread will have the same ID as the process. In
/// a multithreaded process, each thread will have a unique thread id but the
/// same process ID.
///
/// No error handling is required as a thread id should always exist for any
/// process, even if threads are not being used.
#[cfg(any(target_os = "linux", target_os = "android"))]
#[inline]
pub fn gettid() -> pid_t {
unsafe { libc::syscall(libc::SYS_gettid) as pid_t } // no error handling, according to man page: "These functions are always successful."
unsafe { libc::syscall(libc::SYS_gettid) as pid_t }
}

/// Create a copy of the specified file descriptor (see
/// [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
///
/// The new file descriptor will be have a new index but refer to the same
/// resource as the old file descriptor and the old and new file descriptors may
/// be used interchangeably. The new and old file descriptor share the same
/// underlying resource, offset, and file status flags. The actual index used
/// for the file descriptor will be the lowest fd index that is available.
///
/// The two file descriptors do not share file descriptor flags (e.g. `FD_CLOEXEC`).
#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
let res = unsafe { libc::dup(oldfd) };

Errno::result(res)
}

/// Create a copy of the specified file descriptor using the specified fd (see
/// [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
///
/// This function behaves similar to `dup()` except that it will try to use the
/// specified fd instead of allocating a new one. See the man pages for more
/// detail on the exact behavior of this function.
#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
let res = unsafe { libc::dup2(oldfd, newfd) };

Errno::result(res)
}

/// Create a new copy of the specified file descriptor using the specified fd
/// and flags (see [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
///
/// This function behaves similar to `dup2()` but allows for flags to be
/// specified.
pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
dup3_polyfill(oldfd, newfd, flags)
}
Expand All @@ -110,6 +202,11 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
Ok(fd)
}

/// Change the current working directory of the calling process (see
/// [chdir(2)](http://man7.org/linux/man-pages/man2/chdir.2.html)).
///
/// This function may fail in a number of different scenarios. See the man
/// pages for additional details on possible failure cases.
#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
Expand Down Expand Up @@ -213,6 +310,17 @@ pub fn getcwd() -> Result<PathBuf> {
}
}

/// Change the ownership of the file at `path` to be owned by the specified
/// `owner` (user) and `group` (see
/// [chown(2)](http://man7.org/linux/man-pages/man2/lchown.2.html)).
///
/// The owner/group for the provided path name will not be modified if `None` is
/// provided for that argument. Ownership change will be attempted for the path
/// only if `Some` owner/group is provided.
///
/// This call may fail under a number of different situations. See [the man
/// pages](http://man7.org/linux/man-pages/man2/lchown.2.html#ERRORS) for
/// additional details.
#[inline]
pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<uid_t>, group: Option<gid_t>) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
Expand Down

0 comments on commit ff4484d

Please sign in to comment.