diff options
author | Carl Lerche <me@carllerche.com> | 2015-02-21 22:42:10 -0800 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2015-02-21 22:42:10 -0800 |
commit | 6af51aa23225504022acdbcecc9f2e5d559522c4 (patch) | |
tree | 9db2cc0d7fe43a91db596429d0aea19f0ef6476d | |
parent | 60ccee778b2adca488706c586bd61c5affa90de3 (diff) | |
download | nix-6af51aa23225504022acdbcecc9f2e5d559522c4.zip |
Fix uio and add SockAddr conversions
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/sys/mod.rs | 2 | ||||
-rw-r--r-- | src/sys/socket.rs | 105 | ||||
-rw-r--r-- | src/sys/uio.rs | 22 | ||||
-rw-r--r-- | test/sys/mod.rs | 2 | ||||
-rw-r--r-- | test/sys/test_socket.rs | 29 | ||||
-rw-r--r-- | test/sys/test_uio.rs | 11 | ||||
-rw-r--r-- | test/test.rs | 2 |
8 files changed, 154 insertions, 21 deletions
@@ -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; |