summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sys/epoll.rs35
-rw-r--r--src/sys/eventfd.rs6
-rw-r--r--src/sys/socket/mod.rs18
-rw-r--r--src/unistd.rs61
4 files changed, 91 insertions, 29 deletions
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index 9774318f..eb28ffb9 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -1,6 +1,9 @@
use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
+use std::ptr;
+use std::mem;
+use ::Error;
bitflags!(
#[repr(C)]
@@ -23,7 +26,7 @@ bitflags!(
}
);
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
EpollCtlAdd = 1,
@@ -44,10 +47,14 @@ pub struct EpollEvent {
}
impl EpollEvent {
- pub fn new(events: EpollFlags, data: u64) -> EpollEvent {
+ pub fn new(events: EpollFlags, data: u64) -> Self {
EpollEvent { event: libc::epoll_event { events: events.bits(), u64: data } }
}
+ pub fn empty() -> Self {
+ unsafe { mem::zeroed::<EpollEvent>() }
+ }
+
pub fn events(&self) -> EpollFlags {
EpollFlags::from_bits(self.event.events).unwrap()
}
@@ -57,6 +64,16 @@ impl EpollEvent {
}
}
+impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
+ #[inline]
+ fn into(self) -> &'a mut EpollEvent {
+ match self {
+ Some(epoll_event) => epoll_event,
+ None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
+ }
+ }
+}
+
#[inline]
pub fn epoll_create() -> Result<RawFd> {
let res = unsafe { libc::epoll_create(1024) };
@@ -72,10 +89,16 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
}
#[inline]
-pub fn epoll_ctl(epfd: RawFd, op: EpollOp, fd: RawFd, event: &mut EpollEvent) -> Result<()> {
- let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
-
- Errno::result(res).map(drop)
+pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
+ where T: Into<&'a mut EpollEvent>
+{
+ let event: &mut EpollEvent = event.into();
+ if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
+ Err(Error::Sys(Errno::EINVAL))
+ } else {
+ let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
+ Errno::result(res).map(drop)
+ }
}
#[inline]
diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs
index e6e410ec..8058e207 100644
--- a/src/sys/eventfd.rs
+++ b/src/sys/eventfd.rs
@@ -4,9 +4,9 @@ use {Errno, Result};
libc_bitflags! {
flags EfdFlags: libc::c_int {
- const EFD_CLOEXEC, // Since Linux 2.6.27
- const EFD_NONBLOCK, // Since Linux 2.6.27
- const EFD_SEMAPHORE, // Since Linux 2.6.30
+ EFD_CLOEXEC, // Since Linux 2.6.27
+ EFD_NONBLOCK, // Since Linux 2.6.27
+ EFD_SEMAPHORE, // Since Linux 2.6.30
}
}
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index e041e6b6..645dfe41 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -50,17 +50,8 @@ pub use self::multicast::{
};
pub use self::consts::*;
-#[cfg(any(not(target_os = "linux"), not(target_arch = "x86")))]
pub use libc::sockaddr_storage;
-// Working around rust-lang/rust#23425
-#[cfg(all(target_os = "linux", target_arch = "x86"))]
-pub struct sockaddr_storage {
- pub ss_family: sa_family_t,
- pub __ss_align: u32,
- pub __ss_pad2: [u8; 120],
-}
-
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(i32)]
pub enum SockType {
@@ -238,8 +229,13 @@ impl<'a> ControlMessage<'a> {
let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
mem::size_of_val(&cmsg);
- let buf2 = &mut &mut buf[padlen..];
- copy_bytes(fds, buf2);
+
+ let mut tmpbuf = &mut [][..];
+ mem::swap(&mut tmpbuf, buf);
+ let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
+ mem::swap(buf, &mut remainder);
+
+ copy_bytes(fds, buf);
},
ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
copy_bytes(orig_cmsg, buf);
diff --git a/src/unistd.rs b/src/unistd.rs
index f7efbdee..187154bd 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -5,8 +5,8 @@ use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::F_SETFD;
use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
use std::mem;
-use std::ffi::{CString, CStr, OsString};
-use std::os::unix::ffi::{OsStringExt};
+use std::ffi::{CString, CStr, OsString, OsStr};
+use std::os::unix::ffi::{OsStringExt, OsStrExt};
use std::os::unix::io::RawFd;
use std::path::{PathBuf};
use void::Void;
@@ -249,6 +249,19 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
Errno::result(res).map(drop)
}
+/// Change the current working directory of the process to the one
+/// given as an open file descriptor (see
+/// [fchdir(2)](http://man7.org/linux/man-pages/man2/fchdir.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 fchdir(dirfd: RawFd) -> Result<()> {
+ let res = unsafe { libc::fchdir(dirfd) };
+
+ Errno::result(res).map(drop)
+}
+
/// Creates new directory `path` with access rights `mode`.
///
/// # Errors
@@ -480,7 +493,14 @@ pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
Errno::result(res).map(drop)
}
-pub fn sethostname(name: &[u8]) -> Result<()> {
+/// Set the system host name (see
+/// [gethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
+///
+/// Given a name, attempt to update the system host name to the given string.
+/// On some systems, the host name is limited to as few as 64 bytes. An error
+/// will be return if the name is not valid or the current process does not have
+/// permissions to update the host name.
+pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
// Handle some differences in type of the len arg across platforms.
cfg_if! {
if #[cfg(any(target_os = "dragonfly",
@@ -492,19 +512,42 @@ pub fn sethostname(name: &[u8]) -> Result<()> {
type sethostname_len_t = size_t;
}
}
- let ptr = name.as_ptr() as *const c_char;
- let len = name.len() as sethostname_len_t;
+ let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
+ let len = name.as_ref().len() as sethostname_len_t;
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;
+/// Get the host name and store it in the provided buffer, returning a pointer
+/// the CStr in that buffer on success (see
+/// [gethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
+///
+/// This function call attempts to get the host name for the running system and
+/// store it in a provided buffer. The buffer will be populated with bytes up
+/// to the length of the provided slice including a NUL terminating byte. If
+/// the hostname is longer than the length provided, no error will be provided.
+/// The posix specification does not specify whether implementations will
+/// null-terminate in this case, but the nix implementation will ensure that the
+/// buffer is null terminated in this case.
+///
+/// ```no_run
+/// use nix::unistd;
+///
+/// let mut buf = [0u8; 64];
+/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
+/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
+/// println!("Hostname: {}", hostname);
+/// ```
+pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr> {
+ let ptr = buffer.as_mut_ptr() as *mut c_char;
+ let len = buffer.len() as size_t;
let res = unsafe { libc::gethostname(ptr, len) };
- Errno::result(res).map(drop)
+ Errno::result(res).map(|_| {
+ buffer[len - 1] = 0; // ensure always null-terminated
+ unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
+ })
}
pub fn close(fd: RawFd) -> Result<()> {