Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation improvements #449

Merged
merged 9 commits into from
Oct 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we doc InvalidPath or just punt on it in hopes we actually kill it soon?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we doc InvalidPath or just punt on it in hopes we actually kill it soon?

I think we can punt on it for now. I avoided since I thought it was likely to change.

#[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,57 +37,144 @@ 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, .. }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, if other members were to ever be added in the future, things will keep working.

/// 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) };
Errno::result(res).map(drop)
}

/// 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 @@ -105,6 +197,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 @@ -208,6 +305,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