summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2017-12-19 15:23:50 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2017-12-19 15:23:50 +0000
commitb68db41543d16d862e07ddbd143f43b92533d60b (patch)
treeab1f601bc9e67bc31ef833dcebc973b9ee899b67
parent291d618322a360e2b3ac99ca7c1fde19ba6b4b2c (diff)
parent709cbdf12cacb6ecf42cca9000d1d46380b6ba62 (diff)
downloadnix-b68db41543d16d862e07ddbd143f43b92533d60b.zip
Merge #799
799: Fix nix on Dragonfly r=Susurrus a=mneumann This commit replaces pull request https://github.com/nix-rust/nix/pull/684. It fixes building `nix` on DragonFly. All tests pass. This requires most recent libc to build: https://github.com/rust-lang/libc/pull/851.
-rw-r--r--Cargo.toml3
-rw-r--r--build.rs12
-rw-r--r--src/errno.rs26
-rw-r--r--src/errno_dragonfly.c3
-rw-r--r--src/fcntl.rs1
-rw-r--r--src/sys/socket/ffi.rs48
-rw-r--r--src/unistd.rs7
-rw-r--r--test/sys/mod.rs16
-rw-r--r--test/test_unistd.rs13
9 files changed, 87 insertions, 42 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 58161be0..7dbb9008 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/build.rs b/build.rs
new file mode 100644
index 00000000..d6a9a503
--- /dev/null
+++ b/build.rs
@@ -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() {}
diff --git a/src/errno.rs b/src/errno.rs
index aa152170..1f88ec78 100644
--- a/src/errno.rs
+++ b/src/errno.rs
@@ -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};
@@ -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",
diff --git a/src/errno_dragonfly.c b/src/errno_dragonfly.c
new file mode 100644
index 00000000..32fb4dab
--- /dev/null
+++ b/src/errno_dragonfly.c
@@ -0,0 +1,3 @@
+#include <errno.h>
+
+int *errno_location() { return &errno; }
diff --git a/src/fcntl.rs b/src/fcntl.rs
index 86375e4a..5abf65ac 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -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",
diff --git a/src/sys/socket/ffi.rs b/src/sys/socket/ffi.rs
index 265a97c9..d91b130e 100644
--- a/src/sys/socket/ffi.rs
+++ b/src/sys/socket/ffi.rs
@@ -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.
diff --git a/src/unistd.rs b/src/unistd.rs
index f35eab9d..7a1c56c7 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -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);
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index 3aab9fc5..31cf73b1 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -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;
@@ -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;
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 3fe123f0..93b54143 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -242,16 +242,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.
}
}