summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2015-02-21 22:42:10 -0800
committerCarl Lerche <me@carllerche.com>2015-02-21 22:42:10 -0800
commit6af51aa23225504022acdbcecc9f2e5d559522c4 (patch)
tree9db2cc0d7fe43a91db596429d0aea19f0ef6476d
parent60ccee778b2adca488706c586bd61c5affa90de3 (diff)
downloadnix-6af51aa23225504022acdbcecc9f2e5d559522c4.zip
Fix uio and add SockAddr conversions
-rw-r--r--src/lib.rs2
-rw-r--r--src/sys/mod.rs2
-rw-r--r--src/sys/socket.rs105
-rw-r--r--src/sys/uio.rs22
-rw-r--r--test/sys/mod.rs2
-rw-r--r--test/sys/test_socket.rs29
-rw-r--r--test/sys/test_uio.rs11
-rw-r--r--test/test.rs2
8 files changed, 154 insertions, 21 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 517e80ec..5dbcfa2f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,6 @@
#![crate_name = "nix"]
-#![feature(collections, core, linkage, libc, os, std_misc)]
+#![feature(collections, core, net, linkage, libc, os, path, std_misc)]
#![allow(non_camel_case_types)]
#[macro_use]
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index fbcf9e27..5dacde21 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -26,3 +26,5 @@ pub mod utsname;
pub mod wait;
pub mod mman;
+
+pub mod uio;
diff --git a/src/sys/socket.rs b/src/sys/socket.rs
index b462570d..ff2d7ee7 100644
--- a/src/sys/socket.rs
+++ b/src/sys/socket.rs
@@ -1,13 +1,29 @@
-use std::{mem, ptr, fmt};
-use libc::{c_void, c_int, socklen_t, size_t, ssize_t};
+use {NixError, NixResult, from_ffi};
use errno::Errno;
-use fcntl::{Fd, fcntl, FD_CLOEXEC, O_NONBLOCK};
-use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use features;
-use {NixError, NixResult, from_ffi};
-
-pub use libc::{in_addr, sockaddr, sockaddr_storage, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
-
+use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK};
+use fcntl::FcntlArg::{F_SETFD, F_SETFL};
+use libc::{c_void, c_int, socklen_t, size_t, ssize_t};
+use std::{fmt, mem, net, ptr, path};
+use std::ffi::AsOsStr;
+use std::os::unix::prelude::*;
+
+/*
+ *
+ * ===== Re-exports =====
+ *
+ */
+
+pub use libc::{
+ in_addr,
+ sockaddr,
+ sockaddr_storage,
+ sockaddr_in,
+ sockaddr_in6,
+ sockaddr_un,
+ sa_family_t,
+ ip_mreq
+};
pub use self::consts::*;
mod ffi {
@@ -32,13 +48,86 @@ bitflags!(
}
);
+/*
+ *
+ * ===== SockAddr =====
+ *
+ */
+
+/// Represents a socket address
#[derive(Copy)]
pub enum SockAddr {
+ // TODO: Rename these variants IpV4, IpV6, Unix
SockIpV4(sockaddr_in),
SockIpV6(sockaddr_in6),
SockUnix(sockaddr_un)
}
+/// Convert a value into a socket address
+pub trait AsSockAddr {
+ fn as_sock_addr(&self) -> NixResult<SockAddr>;
+}
+
+/// Convert a path into a unix domain socket address
+impl AsSockAddr for path::Path {
+ fn as_sock_addr(&self) -> NixResult<SockAddr> {
+ let bytes = self.as_os_str().as_bytes();
+
+ Ok(SockAddr::SockUnix(unsafe {
+ let mut ret = sockaddr_un {
+ sun_family: AF_UNIX as sa_family_t,
+ .. mem::zeroed()
+ };
+
+ // Make sure the destination has enough capacity
+ if bytes.len() >= ret.sun_path.len() {
+ return Err(NixError::Sys(Errno::ENAMETOOLONG));
+ }
+
+ // Copy the path
+ ptr::copy_memory(
+ ret.sun_path.as_mut_ptr(),
+ bytes.as_ptr() as *const i8,
+ bytes.len());
+
+ ret
+ }))
+ }
+}
+
+/// Convert an inet address into a socket address
+impl AsSockAddr for net::SocketAddr {
+ fn as_sock_addr(&self) -> NixResult<SockAddr> {
+ use std::net::IpAddr;
+ use std::num::Int;
+
+ match self.ip() {
+ IpAddr::V4(ip) => {
+ let addr = ip.octets();
+ Ok(SockAddr::SockIpV4(sockaddr_in {
+ sin_family: AF_INET as sa_family_t,
+ sin_port: self.port(),
+ sin_addr: in_addr {
+ s_addr: Int::from_be(
+ ((addr[0] as u32) << 24) |
+ ((addr[1] as u32) << 16) |
+ ((addr[2] as u32) << 8) |
+ ((addr[3] as u32) << 0))
+ },
+ .. unsafe { mem::zeroed() }
+ }))
+ }
+ _ => unimplemented!()
+ }
+ }
+}
+
+/*
+ *
+ * ===== Consts =====
+ *
+ */
+
#[cfg(target_os = "linux")]
mod consts {
use libc::{c_int, uint8_t};
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 322182c5..35ae6da3 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -1,15 +1,23 @@
+use {NixResult, NixError};
+use errno::Errno;
+use fcntl::Fd;
+use libc::{c_int, c_void, size_t};
+use std::marker::PhantomData;
mod ffi {
use super::IoVec;
- use libc::{ssize_t];
+ use libc::{ssize_t, c_int};
+ use fcntl::Fd;
- // vectorized version of write
- // doc: http://man7.org/linux/man-pages/man2/writev.2.html
- pub fn writev(fd: Fd, iov: *const IoVec<&[u8]>, iovcnt: c_int) -> ssize_t;
+ extern {
+ // vectorized version of write
+ // doc: http://man7.org/linux/man-pages/man2/writev.2.html
+ pub fn writev(fd: Fd, iov: *const IoVec<&[u8]>, iovcnt: c_int) -> ssize_t;
- // vectorized version of read
- // doc: http://man7.org/linux/man-pages/man2/readv.2.html
- pub fn readv(fd: Fd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t;
+ // vectorized version of read
+ // doc: http://man7.org/linux/man-pages/man2/readv.2.html
+ pub fn readv(fd: Fd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t;
+ }
}
pub fn writev(fd: Fd, iov: &[IoVec<&[u8]>]) -> NixResult<usize> {
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index 5b368f36..21c5817c 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -1 +1,3 @@
+mod test_socket;
mod test_termios;
+mod test_uio;
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
new file mode 100644
index 00000000..8451853f
--- /dev/null
+++ b/test/sys/test_socket.rs
@@ -0,0 +1,29 @@
+use nix::sys::socket::{AsSockAddr, SockAddr};
+use std::{mem, net};
+use std::num::Int;
+use std::path::Path;
+use std::str::FromStr;
+
+#[test]
+pub fn test_inetv4_addr_to_sock_addr() {
+ let std: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
+
+ match std.as_sock_addr().unwrap() {
+ SockAddr::SockIpV4(addr) => {
+ assert_eq!(addr.sin_addr.s_addr, Int::from_be(2130706433));
+ assert_eq!(addr.sin_port, 3000);
+ }
+ _ => panic!("nope"),
+ }
+}
+
+#[test]
+pub fn test_path_to_sock_addr() {
+ match Path::new("/foo/bar").as_sock_addr().unwrap() {
+ SockAddr::SockUnix(addr) => {
+ let expect: &'static [i8] = unsafe { mem::transmute(b"/foo/bar") };
+ assert_eq!(&addr.sun_path[..8], expect);
+ }
+ _ => panic!("nope"),
+ }
+}
diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs
index 3f28c329..c90ce288 100644
--- a/test/sys/test_uio.rs
+++ b/test/sys/test_uio.rs
@@ -1,4 +1,7 @@
use nix::sys::uio::*;
+use nix::unistd::*;
+use rand::{thread_rng, Rng};
+use std::{cmp, iter};
#[test]
fn test_writev() {
@@ -13,7 +16,7 @@ fn test_writev() {
let mut consumed = 0;
while consumed < to_write.len() {
let left = to_write.len() - consumed;
- let slice_len = if left < 64 { left } else { thread_rng().gen_range(64, min(256, left)) };
+ let slice_len = if left < 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
let b = &to_write[consumed..consumed+slice_len];
iovecs.push(IoVec::from_slice(b));
consumed += slice_len;
@@ -22,7 +25,7 @@ fn test_writev() {
assert!(pipe_res.is_ok());
let (reader, writer) = pipe_res.ok().unwrap();
// FileDesc will close its filedesc (reader).
- let mut read_buf: Vec<u8> = repeat(0u8).take(128 * 16).collect();
+ let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
// Blocking io, should write all data.
let write_res = writev(writer, iovecs.as_slice());
// Successful write
@@ -52,8 +55,8 @@ fn test_readv() {
let mut allocated = 0;
while allocated < to_write.len() {
let left = to_write.len() - allocated;
- let vec_len = if left < 64 { left } else { thread_rng().gen_range(64, min(256, left)) };
- let v: Vec<u8> = repeat(0u8).take(vec_len).collect();
+ let vec_len = if left < 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
+ let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
storage.push(v);
allocated += vec_len;
}
diff --git a/test/test.rs b/test/test.rs
index 1148adcf..0fd45f0b 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -1,4 +1,4 @@
-#![feature(core, libc, std_misc)]
+#![feature(core, libc, net, path, std_misc)]
extern crate nix;
extern crate libc;