Skip to content

Commit

Permalink
Fix support for DragonFly
Browse files Browse the repository at this point in the history
* DragonFly does not have a O_DSYNC flag
* Fix type_of_cmsg_data on DragonFly
* No fexecve() on DragonFly
* Do not run aio test cases on DragonFly
* Keep target lists in alphabetical order
* Unscrable #[cfg] directives and use cfg_if! macro instead
* Fix errno on DragonFly

Below follows an explanation why we have to use a C extension
to get errno working on DragonFly:

DragonFly uses a thread-local errno variable, but #[thread_local] is
feature-gated and not available in stable Rust as of this writing (Rust
1.21.0). We have to use a C extension (src/errno_dragonfly.c) to access
it.

Tracking issue for `thread_local` stabilization:

    rust-lang/rust#29594

Once this becomes stable, we can remove build.rs, src/errno_dragonfly.c,
remove the build-dependency from Cargo.toml, and use:

    extern {
        #[thread_local]
        static errno: c_int;
    }

Now all targets will use the build.rs script, but only on DragonFly this
will do something. Also, there are no additional dependencies for
targets other than DragonFly (no gcc dep).
  • Loading branch information
mneumann committed Dec 19, 2017
1 parent f778523 commit 709cbdf
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 42 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ bitflags = "1.0"
cfg-if = "0.1.0"
void = "1.0.2"

[target.'cfg(target_os = "dragonfly")'.build-dependencies]
gcc = "0.3"

[dev-dependencies]
lazy_static = "1"
rand = "0.3.8"
Expand Down
12 changes: 12 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#[cfg(target_os = "dragonfly")]
extern crate gcc;

#[cfg(target_os = "dragonfly")]
fn main() {
gcc::Build::new()
.file("src/errno_dragonfly.c")
.compile("liberrno_dragonfly.a");
}

#[cfg(not(target_os = "dragonfly"))]
fn main() {}
26 changes: 20 additions & 6 deletions src/errno.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use libc::{self, c_int};
#[cfg(not(target_os = "dragonfly"))]
use libc;
use libc::c_int;
use std::{fmt, io, error};
use {Error, Result};

Expand All @@ -12,11 +14,23 @@ cfg_if! {
libc::__error()
}
} else if #[cfg(target_os = "dragonfly")] {
unsafe fn errno_location() -> *mut c_int {
// FIXME: Replace with errno-dragonfly crate as this is no longer the correct
// implementation.
extern { fn __dfly_error() -> *mut c_int; }
__dfly_error()
// DragonFly uses a thread-local errno variable, but #[thread_local] is
// feature-gated and not available in stable Rust as of this writing
// (Rust 1.21.0). We have to use a C extension to access it
// (src/errno_dragonfly.c).
//
// Tracking issue for `thread_local` stabilization:
//
// https://github.com/rust-lang/rust/issues/29594
//
// Once this becomes stable, we can remove build.rs,
// src/errno_dragonfly.c, and use:
//
// extern { #[thread_local] static errno: c_int; }
//
#[link(name="errno_dragonfly", kind="static")]
extern {
pub fn errno_location() -> *mut c_int;
}
} else if #[cfg(any(target_os = "android",
target_os = "netbsd",
Expand Down
3 changes: 3 additions & 0 deletions src/errno_dragonfly.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include <errno.h>

int *errno_location() { return &errno; }
1 change: 0 additions & 1 deletion src/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ libc_bitflags!(
O_DIRECTORY;
/// Implicitly follow each `write()` with an `fdatasync()`.
#[cfg(any(target_os = "android",
target_os = "dragonfly",
target_os = "ios",
target_os = "linux",
target_os = "macos",
Expand Down
48 changes: 24 additions & 24 deletions src/sys/socket/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,32 @@ pub use libc::{socket, listen, bind, accept, connect, setsockopt, sendto, recvfr

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

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

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

use sys::uio::IoVec;

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

#[cfg(not(target_os = "linux"))]
pub type type_of_cmsg_len = socklen_t;

// OSX always aligns struct cmsghdr as if it were a 32-bit OS
#[cfg(target_os = "macos")]
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;
cfg_if! {
if #[cfg(target_os = "dragonfly")] {
use libc::c_uint;
pub type type_of_cmsg_len = socklen_t;
pub type type_of_cmsg_data = c_int;
pub type type_of_msg_iovlen = c_uint;
} else if #[cfg(target_os = "linux")] {
use libc::size_t;
pub type type_of_cmsg_len = size_t;
pub type type_of_cmsg_data = size_t;
pub type type_of_msg_iovlen = size_t;
} else if #[cfg(target_os = "macos")] {
use libc::c_uint;
pub type type_of_cmsg_len = socklen_t;
// OSX always aligns struct cmsghdr as if it were a 32-bit OS
pub type type_of_cmsg_data = c_uint;
pub type type_of_msg_iovlen = c_uint;
} else {
use libc::{c_uint, size_t};
pub type type_of_cmsg_len = socklen_t;
pub type type_of_cmsg_data = size_t;
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.
Expand Down
7 changes: 5 additions & 2 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,11 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
///
/// This function is similar to `execve`, except that the program to be executed
/// is referenced as a file descriptor instead of a path.
#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
target_os = "netbsd", target_os = "openbsd", target_os = "linux"))]
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"))]
#[inline]
pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
let args_p = to_exec_array(args);
Expand Down
16 changes: 13 additions & 3 deletions test/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
mod test_signal;
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
target_os = "netbsd", target_os = "macos", target_os = "linux"))]

// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of
// this writing. There is an user-level implementation, but whether aio
// works or not heavily depends on which pthread implementation is chosen
// by the user at link time. For this reason we do not want to run aio test
// cases on DragonFly.
#[cfg(any(target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd"))]
mod test_aio;
#[cfg(target_os = "linux")]
mod test_signalfd;
Expand All @@ -14,5 +23,6 @@ mod test_uio;
#[cfg(target_os = "linux")]
mod test_epoll;
mod test_pthread;
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(any(target_os = "android",
target_os = "linux"))]
mod test_ptrace;
13 changes: 7 additions & 6 deletions test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,17 @@ cfg_if!{
if #[cfg(target_os = "android")] {
execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
} else if #[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
} else if #[cfg(any(target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "linux", ))] {
target_os = "openbsd"))] {
execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
} else if #[cfg(any(target_os = "ios", target_os = "macos", ))] {
} else if #[cfg(any(target_os = "dragonfly",
target_os = "ios",
target_os = "macos"))] {
execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
// No fexecve() on macos/ios.
// No fexecve() on macos/ios and DragonFly.
}
}

Expand Down

0 comments on commit 709cbdf

Please sign in to comment.