summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZachary Tong <zacharyjtong@gmail.com>2015-11-22 08:04:41 -0500
committerCarl Lerche <me@carllerche.com>2015-12-03 13:15:20 -0800
commit1b97d964ece80f9fff9adad721dbaffe92d90a07 (patch)
treeef2153ca553e9ffb49606cf340fcbeb84ed03fb6 /src
parent04d315dee956ed8223cbac2be0839d0dae9497a5 (diff)
downloadnix-1b97d964ece80f9fff9adad721dbaffe92d90a07.zip
NetBSD tweaks for kqueue support
Diffstat (limited to 'src')
-rw-r--r--src/sys/event.rs135
-rw-r--r--src/sys/mod.rs3
-rw-r--r--src/sys/socket/consts.rs8
-rw-r--r--src/sys/socket/sockopt.rs4
4 files changed, 142 insertions, 8 deletions
diff --git a/src/sys/event.rs b/src/sys/event.rs
index d95b2107..6498cb97 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -3,16 +3,20 @@
use {Error, Result};
use errno::Errno;
+#[cfg(not(target_os = "netbsd"))]
use libc::{timespec, time_t, c_int, c_long, uintptr_t};
+#[cfg(target_os = "netbsd")]
+use libc::{timespec, time_t, c_long, uintptr_t, size_t};
use std::os::unix::io::RawFd;
use std::ptr;
pub use self::ffi::kevent as KEvent;
mod ffi {
- pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec};
+ pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec, size_t, int64_t};
use super::{EventFilter, EventFlag, FilterFlag};
+ #[cfg(not(target_os = "netbsd"))]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct kevent {
@@ -24,11 +28,24 @@ mod ffi {
pub udata: usize // 8
}
+ #[cfg(target_os = "netbsd")]
+ #[derive(Clone, Copy)]
+ #[repr(C)]
+ pub struct kevent {
+ pub ident: uintptr_t,
+ pub filter: EventFilter,
+ pub flags: EventFlag,
+ pub fflags: FilterFlag,
+ pub data: int64_t,
+ pub udata: intptr_t
+ }
+
// Bug in rustc, cannot determine that kevent is #[repr(C)]
#[allow(improper_ctypes)]
extern {
pub fn kqueue() -> c_int;
+ #[cfg(not(target_os = "netbsd"))]
pub fn kevent(
kq: c_int,
changelist: *const kevent,
@@ -36,10 +53,19 @@ mod ffi {
eventlist: *mut kevent,
nevents: c_int,
timeout: *const timespec) -> c_int;
+
+ #[cfg(target_os = "netbsd")]
+ pub fn kevent(
+ kq: c_int,
+ changelist: *const kevent,
+ nchanges: size_t,
+ eventlist: *mut kevent,
+ nevents: size_t,
+ timeout: *const timespec) -> c_int;
}
}
-#[cfg(not(target_os = "dragonfly"))]
+#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
@@ -73,7 +99,21 @@ pub enum EventFilter {
EVFILT_USER = -9,
}
-#[cfg(not(target_os = "dragonfly"))]
+#[cfg(target_os = "netbsd")]
+#[repr(u32)]
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum EventFilter {
+ EVFILT_READ = 0,
+ EVFILT_WRITE = 1,
+ EVFILT_AIO = 2,
+ EVFILT_VNODE = 3,
+ EVFILT_PROC = 4,
+ EVFILT_SIGNAL = 5,
+ EVFILT_TIMER = 6,
+ EVFILT_SYSCOUNT = 7
+}
+
+#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
bitflags!(
flags EventFlag: u16 {
const EV_ADD = 0x0001,
@@ -110,7 +150,24 @@ bitflags!(
}
);
-#[cfg(not(target_os = "dragonfly"))]
+#[cfg(target_os = "netbsd")]
+bitflags!(
+ flags EventFlag: u32 {
+ const EV_ADD = 0x0001,
+ const EV_DELETE = 0x0002,
+ const EV_ENABLE = 0x0004,
+ const EV_DISABLE = 0x0008,
+ const EV_ONESHOT = 0x0010,
+ const EV_CLEAR = 0x0020,
+ const EV_SYSFLAGS = 0xF000,
+ const EV_NODATA = 0x1000,
+ const EV_FLAG1 = 0x2000,
+ const EV_EOF = 0x8000,
+ const EV_ERROR = 0x4000
+ }
+);
+
+#[cfg(not(any(target_os = "dragonfly", target_os="netbsd")))]
bitflags!(
flags FilterFlag: u32 {
const NOTE_TRIGGER = 0x01000000,
@@ -188,10 +245,33 @@ bitflags!(
}
);
-#[cfg(not(target_os = "dragonfly"))]
+#[cfg(target_os = "netbsd")]
+bitflags!(
+ flags FilterFlag: u32 {
+ const NOTE_LOWAT = 0x00000001,
+ const NOTE_DELETE = 0x00000001,
+ const NOTE_WRITE = 0x00000002,
+ const NOTE_EXTEND = 0x00000004,
+ const NOTE_ATTRIB = 0x00000008,
+ const NOTE_LINK = 0x00000010,
+ const NOTE_RENAME = 0x00000020,
+ const NOTE_REVOKE = 0x00000040,
+ const NOTE_EXIT = 0x80000000,
+ const NOTE_FORK = 0x40000000,
+ const NOTE_EXEC = 0x20000000,
+ const NOTE_SIGNAL = 0x08000000,
+ const NOTE_PDATAMASK = 0x000fffff,
+ const NOTE_PCTRLMASK = 0xf0000000, // NOTE: FreeBSD uses 0xfff00000,
+ const NOTE_TRACK = 0x00000001,
+ const NOTE_TRACKERR = 0x00000002,
+ const NOTE_CHILD = 0x00000004
+ }
+);
+
+#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
pub const EV_POLL: EventFlag = EV_FLAG0;
-#[cfg(not(target_os = "dragonfly"))]
+#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
pub const EV_OOBAND: EventFlag = EV_FLAG1;
pub fn kqueue() -> Result<RawFd> {
@@ -218,10 +298,12 @@ pub fn kevent(kq: RawFd,
kevent_ts(kq, changelist, eventlist, Some(timeout))
}
+#[cfg(not(target_os = "netbsd"))]
pub fn kevent_ts(kq: RawFd,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_opt: Option<timespec>) -> Result<usize> {
+
let res = unsafe {
ffi::kevent(
kq,
@@ -239,6 +321,30 @@ pub fn kevent_ts(kq: RawFd,
return Ok(res as usize)
}
+#[cfg(target_os = "netbsd")]
+pub fn kevent_ts(kq: RawFd,
+ changelist: &[KEvent],
+ eventlist: &mut [KEvent],
+ timeout_opt: Option<timespec>) -> Result<usize> {
+
+ let res = unsafe {
+ ffi::kevent(
+ kq,
+ changelist.as_ptr(),
+ changelist.len() as size_t,
+ eventlist.as_mut_ptr(),
+ eventlist.len() as size_t,
+ if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
+ };
+
+ if res < 0 {
+ return Err(Error::Sys(Errno::last()));
+ }
+
+ return Ok(res as usize)
+}
+
+#[cfg(not(target_os = "netbsd"))]
#[inline]
pub fn ev_set(ev: &mut KEvent,
ident: usize,
@@ -254,3 +360,20 @@ pub fn ev_set(ev: &mut KEvent,
ev.data = 0;
ev.udata = udata;
}
+
+#[cfg(target_os = "netbsd")]
+#[inline]
+pub fn ev_set(ev: &mut KEvent,
+ ident: usize,
+ filter: EventFilter,
+ flags: EventFlag,
+ fflags: FilterFlag,
+ udata: i64) {
+
+ ev.ident = ident as uintptr_t;
+ ev.filter = filter;
+ ev.flags = flags;
+ ev.fflags = fflags;
+ ev.data = 0;
+ ev.udata = udata;
+}
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 6e40c57f..c7fdc4dc 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -2,7 +2,8 @@
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod epoll;
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
+ target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))]
pub mod event;
// TODO: switch from feature flags to conditional builds
diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs
index 22bd02a2..ef8c23f6 100644
--- a/src/sys/socket/consts.rs
+++ b/src/sys/socket/consts.rs
@@ -208,7 +208,13 @@ mod os {
pub const IPV6_ADD_MEMBERSHIP: c_int = libc::IPV6_ADD_MEMBERSHIP;
#[cfg(not(target_os = "netbsd"))]
pub const IPV6_DROP_MEMBERSHIP: c_int = libc::IPV6_DROP_MEMBERSHIP;
-
+
+ #[cfg(target_os = "netbsd")]
+ pub const IPV6_JOIN_GROUP: c_int = 12;
+
+ #[cfg(target_os = "netbsd")]
+ pub const IPV6_LEAVE_GROUP: c_int = 13;
+
pub type InAddrT = u32;
// Declarations of special addresses
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index ede9d408..2f01b91d 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -125,6 +125,10 @@ sockopt_impl!(SetOnly, IpDropMembership, consts::IPPROTO_IP, consts::IP_DROP_MEM
sockopt_impl!(SetOnly, Ipv6AddMembership, consts::IPPROTO_IPV6, consts::IPV6_ADD_MEMBERSHIP, super::ipv6_mreq);
#[cfg(not(target_os = "netbsd"))]
sockopt_impl!(SetOnly, Ipv6DropMembership, consts::IPPROTO_IPV6, consts::IPV6_DROP_MEMBERSHIP, super::ipv6_mreq);
+#[cfg(target_os = "netbsd")]
+sockopt_impl!(SetOnly, Ipv6AddMembership, consts::IPPROTO_IPV6, consts::IPV6_JOIN_GROUP, super::ipv6_mreq);
+#[cfg(target_os = "netbsd")]
+sockopt_impl!(SetOnly, Ipv6DropMembership, consts::IPPROTO_IPV6, consts::IPV6_LEAVE_GROUP, super::ipv6_mreq);
sockopt_impl!(Both, IpMulticastTtl, consts::IPPROTO_IP, consts::IP_MULTICAST_TTL, u8);
sockopt_impl!(Both, IpMulticastLoop, consts::IPPROTO_IP, consts::IP_MULTICAST_LOOP, bool);
sockopt_impl!(Both, ReceiveTimeout, consts::SOL_SOCKET, consts::SO_RCVTIMEO, TimeVal);