Skip to content

Commit

Permalink
Merge #688
Browse files Browse the repository at this point in the history
688: Support for OpenBSD r=Susurrus

Fixes #685 

These changes get nix building on OpenBSD 6.1. There is one failing test that I want a little guidance on:

```
error[E0308]: mismatched types
   --> src/sys/event.rs:333:30
    |
333 |     assert!(expected.data == actual.data());
    |                              ^^^^^^^^^^^^^ expected i64, found isize
```

`KEvent::data` is:

```
    pub fn data(&self) -> intptr_t {
        self.kevent.data as intptr_t
    }
```

I assume the test should be updated to cast to the expected type but wanted to confirm that before making the change.
  • Loading branch information
bors[bot] committed Aug 9, 2017
2 parents 6334f55 + 0fbd223 commit 087aece
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 121 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD
([#721](https://github.com/nix-rust/nix/pull/721))

# Fixed
- Fix compilation and tests for OpenBSD targets
([#688](https://github.com/nix-rust/nix/pull/688))

## [0.9.0] 2017-07-23

### Added
Expand Down
25 changes: 25 additions & 0 deletions nix-test/src/const.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,31 @@ get_int_const(const char* err) {
GET_CONST(ECANCELED);
#endif

#if defined(__OpenBSD__)
GET_CONST(EAUTH);
GET_CONST(EBADRPC);
GET_CONST(ECANCELED);
GET_CONST(EDQUOT);
GET_CONST(EFTYPE);
GET_CONST(EILSEQ);
GET_CONST(EIPSEC);
GET_CONST(EMEDIUMTYPE);
GET_CONST(ENEEDAUTH);
GET_CONST(ENOATTR);
GET_CONST(ENOMEDIUM);
GET_CONST(ENOTSUP);
GET_CONST(EOPNOTSUPP);
GET_CONST(EOVERFLOW);
GET_CONST(EPROCLIM);
GET_CONST(EPROCUNAVAIL);
GET_CONST(EPROGMISMATCH);
GET_CONST(EPROGUNAVAIL);
GET_CONST(EREMOTE);
GET_CONST(ERPCMISMATCH);
GET_CONST(ESTALE);
GET_CONST(EUSERS);
#endif

#ifdef DARWIN
GET_CONST(EPWROFF);
GET_CONST(EDEVERR);
Expand Down
38 changes: 24 additions & 14 deletions src/sys/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@ pub struct KEvent {
kevent: libc::kevent,
}

#[cfg(any(target_os = "openbsd", target_os = "freebsd",
target_os = "dragonfly", target_os = "macos",
target_os = "ios"))]
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd"))]
type type_of_udata = *mut libc::c_void;
#[cfg(any(target_os = "openbsd", target_os = "freebsd",
target_os = "dragonfly", target_os = "macos",
target_os = "ios"))]
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos"))]
type type_of_data = libc::intptr_t;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;
#[cfg(any(target_os = "netbsd"))]
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
type type_of_data = libc::int64_t;

#[cfg(not(target_os = "netbsd"))]
Expand Down Expand Up @@ -78,17 +77,26 @@ pub enum EventFilter {
EVFILT_TIMER = libc::EVFILT_TIMER,
}

#[cfg(any(target_os = "macos", target_os = "ios",
target_os = "freebsd", target_os = "dragonfly"))]
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "openbsd"))]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
#[cfg(any(target_os = "netbsd"))]
pub type type_of_event_flag = u32;
libc_bitflags!{
pub flags EventFlag: type_of_event_flag {
EV_ADD,
EV_CLEAR,
EV_DELETE,
EV_DISABLE,
// No released version of OpenBSD supports EV_DISPATCH or EV_RECEIPT.
// These have been commited to the -current branch though and are
// expected to be part of the OpenBSD 6.2 release in Nov 2017.
// See: https://marc.info/?l=openbsd-tech&m=149621427511219&w=2
// https://github.com/rust-lang/libc/pull/613
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "netbsd"))]
EV_DISPATCH,
#[cfg(target_os = "freebsd")]
EV_DROP,
Expand All @@ -105,7 +113,9 @@ libc_bitflags!{
EV_OOBAND,
#[cfg(any(target_os = "macos", target_os = "ios"))]
EV_POLL,
#[cfg(not(target_os = "openbsd"))]
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "netbsd"))]
EV_RECEIPT,
EV_SYSFLAGS,
}
Expand Down Expand Up @@ -315,21 +325,21 @@ fn test_struct_kevent() {

let expected = libc::kevent{ident: 0xdeadbeef,
filter: libc::EVFILT_READ,
flags: libc::EV_DISPATCH | libc::EV_ADD,
flags: libc::EV_ONESHOT | libc::EV_ADD,
fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
data: 0x1337,
udata: udata as type_of_udata};
let actual = KEvent::new(0xdeadbeef,
EventFilter::EVFILT_READ,
EV_DISPATCH | EV_ADD,
EV_ONESHOT | EV_ADD,
NOTE_CHILD | NOTE_EXIT,
0x1337,
udata);
assert!(expected.ident == actual.ident());
assert!(expected.filter == actual.filter() as type_of_event_filter);
assert!(expected.flags == actual.flags().bits());
assert!(expected.fflags == actual.fflags().bits());
assert!(expected.data == actual.data());
assert!(expected.data == actual.data() as type_of_data);
assert!(expected.udata == actual.udata() as type_of_udata);
assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
}
193 changes: 103 additions & 90 deletions src/sys/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

use libc;
use {Errno, Error, Result};
use std::fmt;
use std::fmt::Debug;
use std::mem;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
use std::os::unix::io::RawFd;
use std::ptr;

#[cfg(not(target_os = "openbsd"))]
pub use self::sigevent::*;

// Currently there is only one definition of c_int in libc, as well as only one
// type for signal constants.
// We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
Expand Down Expand Up @@ -488,102 +489,114 @@ pub enum SigevNotify {
si_value: libc::intptr_t },
}

/// Used to request asynchronous notification of the completion of certain
/// events, such as POSIX AIO and timers.
#[repr(C)]
pub struct SigEvent {
sigevent: libc::sigevent
}
#[cfg(not(target_os = "openbsd"))]
mod sigevent {
use libc;
use std::mem;
use std::ptr;
use std::fmt::{self, Debug};
use super::SigevNotify;
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
use super::type_of_thread_id;

/// Used to request asynchronous notification of the completion of certain
/// events, such as POSIX AIO and timers.
#[repr(C)]
pub struct SigEvent {
sigevent: libc::sigevent
}

impl SigEvent {
/// **Note:** this constructor does not allow the user to set the
/// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD
/// at least those flags don't do anything useful. That field is part of a
/// union that shares space with the more genuinely useful fields.
///
/// **Note:** This constructor also doesn't allow the caller to set the
/// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
/// required for `SIGEV_THREAD`. That's considered ok because on no operating
/// system is `SIGEV_THREAD` the most efficient way to deliver AIO
/// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
/// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
/// more genuinely useful `sigev_notify_thread_id`
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
sev.sigev_notify = match sigev_notify {
SigevNotify::SigevNone => libc::SIGEV_NONE,
SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
#[cfg(target_os = "freebsd")]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
};
sev.sigev_signo = match sigev_notify {
SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ kq, ..} => kq,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
_ => 0
};
sev.sigev_value.sival_ptr = match sigev_notify {
SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
};
SigEvent::set_tid(&mut sev, &sigev_notify);
SigEvent{sigevent: sev}
}

impl SigEvent {
// Note: this constructor does not allow the user to set the
// sigev_notify_kevent_flags field. That's considered ok because on FreeBSD
// at least those flags don't do anything useful. That field is part of a
// union that shares space with the more genuinely useful
// Note: This constructor also doesn't allow the caller to set the
// sigev_notify_function or sigev_notify_attributes fields, which are
// required for SIGEV_THREAD. That's considered ok because on no operating
// system is SIGEV_THREAD the most efficient way to deliver AIO
// notification. FreeBSD and Dragonfly programs should prefer SIGEV_KEVENT.
// Linux, Solaris, and portable programs should prefer SIGEV_THREAD_ID or
// SIGEV_SIGNAL. That field is part of a union that shares space with the
// more genuinely useful sigev_notify_thread_id
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
sev.sigev_notify = match sigev_notify {
SigevNotify::SigevNone => libc::SIGEV_NONE,
SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
#[cfg(target_os = "freebsd")]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
};
sev.sigev_signo = match sigev_notify {
SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ kq, ..} => kq,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
_ => 0
};
sev.sigev_value.sival_ptr = match sigev_notify {
SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
};
SigEvent::set_tid(&mut sev, &sigev_notify);
SigEvent{sigevent: sev}
}
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
sev.sigev_notify_thread_id = match sigev_notify {
&SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
_ => 0 as type_of_thread_id
};
}

#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
sev.sigev_notify_thread_id = match sigev_notify {
&SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
_ => 0 as type_of_thread_id
};
}
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
}

#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
pub fn sigevent(&self) -> libc::sigevent {
self.sigevent
}
}

pub fn sigevent(&self) -> libc::sigevent {
self.sigevent
}
}
impl Debug for SigEvent {
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SigEvent")
.field("sigev_notify", &self.sigevent.sigev_notify)
.field("sigev_signo", &self.sigevent.sigev_signo)
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
.field("sigev_notify_thread_id",
&self.sigevent.sigev_notify_thread_id)
.finish()
}

impl Debug for SigEvent {
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SigEvent")
.field("sigev_notify", &self.sigevent.sigev_notify)
.field("sigev_signo", &self.sigevent.sigev_signo)
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
.field("sigev_notify_thread_id",
&self.sigevent.sigev_notify_thread_id)
.finish()
}

#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SigEvent")
.field("sigev_notify", &self.sigevent.sigev_notify)
.field("sigev_signo", &self.sigevent.sigev_signo)
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
.finish()
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SigEvent")
.field("sigev_notify", &self.sigevent.sigev_notify)
.field("sigev_signo", &self.sigevent.sigev_signo)
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
.finish()
}
}
}

impl<'a> From<&'a libc::sigevent> for SigEvent {
fn from(sigevent: &libc::sigevent) -> Self {
SigEvent{ sigevent: sigevent.clone() }
impl<'a> From<&'a libc::sigevent> for SigEvent {
fn from(sigevent: &libc::sigevent) -> Self {
SigEvent{ sigevent: sigevent.clone() }
}
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/sys/socket/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

pub use libc::{socket, listen, bind, accept, connect, setsockopt, sendto, recvfrom, getsockname, getpeername, recv, send};

use libc::{c_int, c_void, socklen_t, size_t, ssize_t};
use libc::{c_int, c_void, socklen_t, ssize_t};

#[cfg(target_os = "macos")]
#[cfg(not(target_os = "macos"))]
use libc::size_t;

#[cfg(not(target_os = "linux"))]
use libc::c_uint;

use sys::uio::IoVec;
Expand All @@ -23,19 +26,27 @@ pub type type_of_cmsg_data = c_uint;
#[cfg(not(target_os = "macos"))]
pub type type_of_cmsg_data = size_t;

#[cfg(target_os = "linux")]
pub type type_of_msg_iovlen = size_t;

#[cfg(not(target_os = "linux"))]
pub type type_of_msg_iovlen = c_uint;

// Private because we don't expose any external functions that operate
// directly on this type; we just use it internally at FFI boundaries.
// Note that in some cases we store pointers in *const fields that the
// kernel will proceed to mutate, so users should be careful about the
// actual mutability of data pointed to by this structure.
//
// FIXME: Replace these structs with the ones defined in libc
#[repr(C)]
pub struct msghdr<'a> {
pub msg_name: *const c_void,
pub msg_namelen: socklen_t,
pub msg_iov: *const IoVec<&'a [u8]>,
pub msg_iovlen: size_t,
pub msg_iovlen: type_of_msg_iovlen,
pub msg_control: *const c_void,
pub msg_controllen: size_t,
pub msg_controllen: type_of_cmsg_len,
pub msg_flags: c_int,
}

Expand Down
Loading

0 comments on commit 087aece

Please sign in to comment.