summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUtkarsh Kukreti <utkarshkukreti@gmail.com>2015-09-14 21:00:35 +0530
committerCarl Lerche <me@carllerche.com>2015-09-28 10:58:05 -0700
commitee9affe12fa216c84eb11cc3169673b55af1bb56 (patch)
treecebc05fad8069bcf60c5a160603e760af2c2aba5
parent6e27e16d633a8dbb632bf3cbd6c7d542cd547033 (diff)
downloadnix-ee9affe12fa216c84eb11cc3169673b55af1bb56.zip
Add sys::select::FdSet and sys::select::select.
-rw-r--r--src/sys/mod.rs2
-rw-r--r--src/sys/select.rs84
-rw-r--r--test/sys/mod.rs1
-rw-r--r--test/sys/test_select.rs42
4 files changed, 129 insertions, 0 deletions
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index eda95972..3e4a0836 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -47,3 +47,5 @@ pub mod time;
target_arch = "arm")),
)]
pub mod ptrace;
+
+pub mod select;
diff --git a/src/sys/select.rs b/src/sys/select.rs
new file mode 100644
index 00000000..1060d618
--- /dev/null
+++ b/src/sys/select.rs
@@ -0,0 +1,84 @@
+use std::ptr::null_mut;
+use std::os::unix::io::RawFd;
+use libc::c_int;
+use {Result, Error};
+use errno::Errno;
+use sys::time::TimeVal;
+
+pub const FD_SETSIZE: RawFd = 1024;
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[repr(C)]
+pub struct FdSet {
+ bits: [i32; FD_SETSIZE as usize / 32]
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+const BITS: usize = 32;
+
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[repr(C)]
+pub struct FdSet {
+ bits: [u64; FD_SETSIZE as usize / 64]
+}
+
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+const BITS: usize = 64;
+
+impl FdSet {
+ pub fn new() -> FdSet {
+ FdSet {
+ bits: [0; FD_SETSIZE as usize / BITS]
+ }
+ }
+
+ pub fn insert(&mut self, fd: RawFd) {
+ let fd = fd as usize;
+ self.bits[fd / BITS] |= 1 << (fd % BITS);
+ }
+
+ pub fn remove(&mut self, fd: RawFd) {
+ let fd = fd as usize;
+ self.bits[fd / BITS] &= !(1 << (fd % BITS));
+ }
+
+ pub fn contains(&mut self, fd: RawFd) -> bool {
+ let fd = fd as usize;
+ self.bits[fd / BITS] & (1 << (fd % BITS)) > 0
+ }
+}
+
+mod ffi {
+ use libc::c_int;
+ use sys::time::TimeVal;
+ use super::FdSet;
+
+ extern {
+ pub fn select(nfds: c_int,
+ readfds: *mut FdSet,
+ writefds: *mut FdSet,
+ errorfds: *mut FdSet,
+ timeout: *mut TimeVal) -> c_int;
+ }
+}
+
+pub fn select(nfds: c_int,
+ readfds: Option<&mut FdSet>,
+ writefds: Option<&mut FdSet>,
+ errorfds: Option<&mut FdSet>,
+ timeout: &mut TimeVal) -> Result<c_int> {
+ let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
+ let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
+ let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
+ let timeout = timeout as *mut TimeVal;
+
+ let res = unsafe {
+ ffi::select(nfds, readfds, writefds, errorfds, timeout)
+ };
+
+ if res == -1 {
+ Err(Error::Sys(Errno::last()))
+ } else {
+ Ok(res)
+ }
+}
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index 8a1f77fd..fbb4a6e0 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -3,3 +3,4 @@ mod test_termios;
mod test_uio;
mod test_ioctl;
mod test_wait;
+mod test_select;
diff --git a/test/sys/test_select.rs b/test/sys/test_select.rs
new file mode 100644
index 00000000..c9331886
--- /dev/null
+++ b/test/sys/test_select.rs
@@ -0,0 +1,42 @@
+use nix::sys::select::{FdSet, FD_SETSIZE, select};
+use nix::sys::time::TimeVal;
+use nix::unistd::{read, write, pipe};
+
+#[test]
+fn test_fdset() {
+ let mut fd_set = FdSet::new();
+
+ for i in 0..FD_SETSIZE {
+ assert!(!fd_set.contains(i));
+ }
+
+ fd_set.insert(7);
+
+ assert!(fd_set.contains(7));
+
+ fd_set.remove(7);
+
+ for i in 0..FD_SETSIZE {
+ assert!(!fd_set.contains(i));
+ }
+}
+
+#[test]
+fn test_select() {
+ let (r1, w1) = pipe().unwrap();
+ write(w1, b"hi!").unwrap();
+ let (r2, w2) = pipe().unwrap();
+
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1);
+ fd_set.insert(r2);
+
+ let mut timeout = TimeVal::seconds(1);
+ assert_eq!(1, select(r2 + 1,
+ Some(&mut fd_set),
+ None,
+ None,
+ &mut timeout).unwrap());
+ assert!(fd_set.contains(r1));
+ assert!(!fd_set.contains(r2));
+}