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

unistd: Use bindings from libc instead of our own #294

Merged
merged 1 commit into from
Mar 6, 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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ signalfd = []
[dependencies]
libc = "0.2.7"
bitflags = "0.4"
cfg-if = "0.1.0"

[dev-dependencies]
rand = "0.3.8"
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate cfg_if;

pub extern crate libc;

#[cfg(test)]
Expand Down
133 changes: 45 additions & 88 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,14 @@
use {Errno, Error, Result, NixPath};
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t, uid_t, gid_t};
use libc::{self, c_char, c_void, c_int, size_t, pid_t, off_t, uid_t, gid_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
use libc::{c_char, c_int, size_t};
pub use libc::{fork, close, read, write, pipe, ftruncate, unlink, setpgid, getegid, geteuid, getgid, getpid, getppid, getuid, setuid, setgid, chown};

#[allow(improper_ctypes)]
extern {
// duplicate a file descriptor
// doc: http://man7.org/linux/man-pages/man2/dup.2.html
pub fn dup(oldfd: c_int) -> c_int;
pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

// change working directory
// doc: http://man7.org/linux/man-pages/man2/chdir.2.html
pub fn chdir(path: *const c_char) -> c_int;

// Execute PATH with arguments ARGV and environment from `environ'.
// doc: http://man7.org/linux/man-pages/man3/execv.3.html
pub fn execv(path: *const c_char, argv: *const *const c_char) -> c_int;

// execute program
// doc: http://man7.org/linux/man-pages/man2/execve.2.html
pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

// Execute FILE, searching in the `PATH' environment variable if it contains
// no slashes, with arguments ARGV and environment from `environ'.
// doc: http://man7.org/linux/man-pages/man3/execvp.3.html
pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

// doc: http://man7.org/linux/man-pages/man3/exec.3.html
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

// run the current process in the background
// doc: http://man7.org/linux/man-pages/man3/daemon.3.html
pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

// sets the hostname to the value given
// doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

// gets the hostname
// doc: http://man7.org/linux/man-pages/man2/sethostname.2.html
pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

// change root directory
// doc: http://man7.org/linux/man-pages/man2/chroot.2.html
pub fn chroot(path: *const c_char) -> c_int;

// synchronize a file's in-core state with storage device
// doc: http://man7.org/linux/man-pages/man2/fsync.2.html
pub fn fsync(fd: c_int) -> c_int;
pub fn fdatasync(fd: c_int) -> c_int;
}
}

#[derive(Clone, Copy)]
pub enum Fork {
Parent(pid_t),
Expand All @@ -90,7 +34,7 @@ impl Fork {
}

pub fn fork() -> Result<Fork> {
let res = unsafe { ffi::fork() };
let res = unsafe { libc::fork() };

Errno::result(res).map(|res| match res {
0 => Fork::Child,
Expand All @@ -100,28 +44,28 @@ pub fn fork() -> Result<Fork> {

#[inline]
pub fn getpid() -> pid_t {
unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
unsafe { libc::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
unsafe { libc::getppid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> {
let res = unsafe { ffi::setpgid(pid, pgid) };
let res = unsafe { libc::setpgid(pid, pgid) };
Errno::result(res).map(drop)
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
let res = unsafe { ffi::dup(oldfd) };
let res = unsafe { libc::dup(oldfd) };

Errno::result(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
let res = unsafe { ffi::dup2(oldfd, newfd) };
let res = unsafe { libc::dup2(oldfd, newfd) };

Errno::result(res)
}
Expand Down Expand Up @@ -151,7 +95,7 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
unsafe { ffi::chdir(cstr.as_ptr()) }
unsafe { libc::chdir(cstr.as_ptr()) }
}));

Errno::result(res).map(drop)
Expand All @@ -161,7 +105,7 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
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| {
// We use `0 - 1` to get `-1 : {u,g}id_t` which is specified as the no-op value for chown(3).
unsafe { ffi::chown(cstr.as_ptr(), owner.unwrap_or(0 - 1), group.unwrap_or(0 - 1)) }
unsafe { libc::chown(cstr.as_ptr(), owner.unwrap_or(0 - 1), group.unwrap_or(0 - 1)) }
}));

Errno::result(res).map(drop)
Expand All @@ -181,7 +125,7 @@ pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
let args_p = to_exec_array(argv);

unsafe {
ffi::execv(path.as_ptr(), args_p.as_ptr())
libc::execv(path.as_ptr(), args_p.as_ptr())
};

Err(Error::Sys(Errno::last()))
Expand All @@ -193,7 +137,7 @@ pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
let env_p = to_exec_array(env);

unsafe {
ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
};

Err(Error::Sys(Errno::last()))
Expand All @@ -204,46 +148,54 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
let args_p = to_exec_array(args);

unsafe {
ffi::execvp(filename.as_ptr(), args_p.as_ptr())
libc::execvp(filename.as_ptr(), args_p.as_ptr())
};

Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
Errno::result(res).map(drop)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
// Handle some differences in type of the len arg across platforms.
cfg_if! {
if #[cfg(any(target_os = "macos", target_os = "ios"))] {
type sethostname_len_t = c_int;
} else {
type sethostname_len_t = size_t;
}
}
let ptr = name.as_ptr() as *const c_char;
let len = name.len() as size_t;
let len = name.len() as sethostname_len_t;

let res = unsafe { ffi::sethostname(ptr, len) };
let res = unsafe { libc::sethostname(ptr, len) };
Errno::result(res).map(drop)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
let ptr = name.as_mut_ptr() as *mut c_char;
let len = name.len() as size_t;

let res = unsafe { ffi::gethostname(ptr, len) };
let res = unsafe { libc::gethostname(ptr, len) };
Errno::result(res).map(drop)
}

pub fn close(fd: RawFd) -> Result<()> {
let res = unsafe { ffi::close(fd) };
let res = unsafe { libc::close(fd) };
Errno::result(res).map(drop)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

Errno::result(res).map(|r| r as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

Errno::result(res).map(|r| r as usize)
}
Expand All @@ -252,7 +204,7 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
unsafe {
let mut fds: [c_int; 2] = mem::uninitialized();

let res = ffi::pipe(fds.as_mut_ptr());
let res = libc::pipe(fds.as_mut_ptr());

try!(Errno::result(res));

Expand All @@ -264,7 +216,7 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
unsafe {
let mut fds: [c_int; 2] = mem::uninitialized();

let res = ffi::pipe(fds.as_mut_ptr());
let res = libc::pipe(fds.as_mut_ptr());

try!(Errno::result(res));

Expand Down Expand Up @@ -300,7 +252,7 @@ fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
Errno::result(unsafe { ffi::ftruncate(fd, len) }).map(drop)
Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
}

pub fn isatty(fd: RawFd) -> Result<bool> {
Expand All @@ -323,7 +275,7 @@ pub fn isatty(fd: RawFd) -> Result<bool> {
pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
unsafe {
ffi::unlink(cstr.as_ptr())
libc::unlink(cstr.as_ptr())
}
}));

Expand All @@ -333,22 +285,27 @@ pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
unsafe { ffi::chroot(cstr.as_ptr()) }
unsafe { libc::chroot(cstr.as_ptr()) }
}));

Errno::result(res).map(drop)
}

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
let res = unsafe { ffi::fsync(fd) };
let res = unsafe { libc::fsync(fd) };

Errno::result(res).map(drop)
}

// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
#[cfg(any(target_os = "linux",
target_os = "android",
target_os = "emscripten"))]
#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
let res = unsafe { ffi::fdatasync(fd) };
let res = unsafe { libc::fdatasync(fd) };

Errno::result(res).map(drop)
}
Expand All @@ -361,34 +318,34 @@ pub fn fdatasync(fd: RawFd) -> Result<()> {
// - http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
#[inline]
pub fn getuid() -> uid_t {
unsafe { ffi::getuid() }
unsafe { libc::getuid() }
}

#[inline]
pub fn geteuid() -> uid_t {
unsafe { ffi::geteuid() }
unsafe { libc::geteuid() }
}

#[inline]
pub fn getgid() -> gid_t {
unsafe { ffi::getgid() }
unsafe { libc::getgid() }
}

#[inline]
pub fn getegid() -> gid_t {
unsafe { ffi::getegid() }
unsafe { libc::getegid() }
}

#[inline]
pub fn setuid(uid: uid_t) -> Result<()> {
let res = unsafe { ffi::setuid(uid) };
let res = unsafe { libc::setuid(uid) };

Errno::result(res).map(drop)
}

#[inline]
pub fn setgid(gid: gid_t) -> Result<()> {
let res = unsafe { ffi::setgid(gid) };
let res = unsafe { libc::setgid(gid) };

Errno::result(res).map(drop)
}
Expand Down