Skip to content

Commit 6af51aa

Browse files
committed
Fix uio and add SockAddr conversions
1 parent 60ccee7 commit 6af51aa

File tree

8 files changed

+154
-21
lines changed

8 files changed

+154
-21
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![crate_name = "nix"]
22

3-
#![feature(collections, core, linkage, libc, os, std_misc)]
3+
#![feature(collections, core, net, linkage, libc, os, path, std_misc)]
44
#![allow(non_camel_case_types)]
55

66
#[macro_use]

src/sys/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ pub mod utsname;
2626
pub mod wait;
2727

2828
pub mod mman;
29+
30+
pub mod uio;

src/sys/socket.rs

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
1-
use std::{mem, ptr, fmt};
2-
use libc::{c_void, c_int, socklen_t, size_t, ssize_t};
1+
use {NixError, NixResult, from_ffi};
32
use errno::Errno;
4-
use fcntl::{Fd, fcntl, FD_CLOEXEC, O_NONBLOCK};
5-
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
63
use features;
7-
use {NixError, NixResult, from_ffi};
8-
9-
pub use libc::{in_addr, sockaddr, sockaddr_storage, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
10-
4+
use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK};
5+
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
6+
use libc::{c_void, c_int, socklen_t, size_t, ssize_t};
7+
use std::{fmt, mem, net, ptr, path};
8+
use std::ffi::AsOsStr;
9+
use std::os::unix::prelude::*;
10+
11+
/*
12+
*
13+
* ===== Re-exports =====
14+
*
15+
*/
16+
17+
pub use libc::{
18+
in_addr,
19+
sockaddr,
20+
sockaddr_storage,
21+
sockaddr_in,
22+
sockaddr_in6,
23+
sockaddr_un,
24+
sa_family_t,
25+
ip_mreq
26+
};
1127
pub use self::consts::*;
1228

1329
mod ffi {
@@ -32,13 +48,86 @@ bitflags!(
3248
}
3349
);
3450

51+
/*
52+
*
53+
* ===== SockAddr =====
54+
*
55+
*/
56+
57+
/// Represents a socket address
3558
#[derive(Copy)]
3659
pub enum SockAddr {
60+
// TODO: Rename these variants IpV4, IpV6, Unix
3761
SockIpV4(sockaddr_in),
3862
SockIpV6(sockaddr_in6),
3963
SockUnix(sockaddr_un)
4064
}
4165

66+
/// Convert a value into a socket address
67+
pub trait AsSockAddr {
68+
fn as_sock_addr(&self) -> NixResult<SockAddr>;
69+
}
70+
71+
/// Convert a path into a unix domain socket address
72+
impl AsSockAddr for path::Path {
73+
fn as_sock_addr(&self) -> NixResult<SockAddr> {
74+
let bytes = self.as_os_str().as_bytes();
75+
76+
Ok(SockAddr::SockUnix(unsafe {
77+
let mut ret = sockaddr_un {
78+
sun_family: AF_UNIX as sa_family_t,
79+
.. mem::zeroed()
80+
};
81+
82+
// Make sure the destination has enough capacity
83+
if bytes.len() >= ret.sun_path.len() {
84+
return Err(NixError::Sys(Errno::ENAMETOOLONG));
85+
}
86+
87+
// Copy the path
88+
ptr::copy_memory(
89+
ret.sun_path.as_mut_ptr(),
90+
bytes.as_ptr() as *const i8,
91+
bytes.len());
92+
93+
ret
94+
}))
95+
}
96+
}
97+
98+
/// Convert an inet address into a socket address
99+
impl AsSockAddr for net::SocketAddr {
100+
fn as_sock_addr(&self) -> NixResult<SockAddr> {
101+
use std::net::IpAddr;
102+
use std::num::Int;
103+
104+
match self.ip() {
105+
IpAddr::V4(ip) => {
106+
let addr = ip.octets();
107+
Ok(SockAddr::SockIpV4(sockaddr_in {
108+
sin_family: AF_INET as sa_family_t,
109+
sin_port: self.port(),
110+
sin_addr: in_addr {
111+
s_addr: Int::from_be(
112+
((addr[0] as u32) << 24) |
113+
((addr[1] as u32) << 16) |
114+
((addr[2] as u32) << 8) |
115+
((addr[3] as u32) << 0))
116+
},
117+
.. unsafe { mem::zeroed() }
118+
}))
119+
}
120+
_ => unimplemented!()
121+
}
122+
}
123+
}
124+
125+
/*
126+
*
127+
* ===== Consts =====
128+
*
129+
*/
130+
42131
#[cfg(target_os = "linux")]
43132
mod consts {
44133
use libc::{c_int, uint8_t};

src/sys/uio.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1+
use {NixResult, NixError};
2+
use errno::Errno;
3+
use fcntl::Fd;
4+
use libc::{c_int, c_void, size_t};
5+
use std::marker::PhantomData;
16

27
mod ffi {
38
use super::IoVec;
4-
use libc::{ssize_t];
9+
use libc::{ssize_t, c_int};
10+
use fcntl::Fd;
511

6-
// vectorized version of write
7-
// doc: http://man7.org/linux/man-pages/man2/writev.2.html
8-
pub fn writev(fd: Fd, iov: *const IoVec<&[u8]>, iovcnt: c_int) -> ssize_t;
12+
extern {
13+
// vectorized version of write
14+
// doc: http://man7.org/linux/man-pages/man2/writev.2.html
15+
pub fn writev(fd: Fd, iov: *const IoVec<&[u8]>, iovcnt: c_int) -> ssize_t;
916

10-
// vectorized version of read
11-
// doc: http://man7.org/linux/man-pages/man2/readv.2.html
12-
pub fn readv(fd: Fd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t;
17+
// vectorized version of read
18+
// doc: http://man7.org/linux/man-pages/man2/readv.2.html
19+
pub fn readv(fd: Fd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t;
20+
}
1321
}
1422

1523
pub fn writev(fd: Fd, iov: &[IoVec<&[u8]>]) -> NixResult<usize> {

test/sys/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
mod test_socket;
12
mod test_termios;
3+
mod test_uio;

test/sys/test_socket.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use nix::sys::socket::{AsSockAddr, SockAddr};
2+
use std::{mem, net};
3+
use std::num::Int;
4+
use std::path::Path;
5+
use std::str::FromStr;
6+
7+
#[test]
8+
pub fn test_inetv4_addr_to_sock_addr() {
9+
let std: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
10+
11+
match std.as_sock_addr().unwrap() {
12+
SockAddr::SockIpV4(addr) => {
13+
assert_eq!(addr.sin_addr.s_addr, Int::from_be(2130706433));
14+
assert_eq!(addr.sin_port, 3000);
15+
}
16+
_ => panic!("nope"),
17+
}
18+
}
19+
20+
#[test]
21+
pub fn test_path_to_sock_addr() {
22+
match Path::new("/foo/bar").as_sock_addr().unwrap() {
23+
SockAddr::SockUnix(addr) => {
24+
let expect: &'static [i8] = unsafe { mem::transmute(b"/foo/bar") };
25+
assert_eq!(&addr.sun_path[..8], expect);
26+
}
27+
_ => panic!("nope"),
28+
}
29+
}

test/sys/test_uio.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
use nix::sys::uio::*;
2+
use nix::unistd::*;
3+
use rand::{thread_rng, Rng};
4+
use std::{cmp, iter};
25

36
#[test]
47
fn test_writev() {
@@ -13,7 +16,7 @@ fn test_writev() {
1316
let mut consumed = 0;
1417
while consumed < to_write.len() {
1518
let left = to_write.len() - consumed;
16-
let slice_len = if left < 64 { left } else { thread_rng().gen_range(64, min(256, left)) };
19+
let slice_len = if left < 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
1720
let b = &to_write[consumed..consumed+slice_len];
1821
iovecs.push(IoVec::from_slice(b));
1922
consumed += slice_len;
@@ -22,7 +25,7 @@ fn test_writev() {
2225
assert!(pipe_res.is_ok());
2326
let (reader, writer) = pipe_res.ok().unwrap();
2427
// FileDesc will close its filedesc (reader).
25-
let mut read_buf: Vec<u8> = repeat(0u8).take(128 * 16).collect();
28+
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
2629
// Blocking io, should write all data.
2730
let write_res = writev(writer, iovecs.as_slice());
2831
// Successful write
@@ -52,8 +55,8 @@ fn test_readv() {
5255
let mut allocated = 0;
5356
while allocated < to_write.len() {
5457
let left = to_write.len() - allocated;
55-
let vec_len = if left < 64 { left } else { thread_rng().gen_range(64, min(256, left)) };
56-
let v: Vec<u8> = repeat(0u8).take(vec_len).collect();
58+
let vec_len = if left < 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
59+
let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
5760
storage.push(v);
5861
allocated += vec_len;
5962
}

test/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(core, libc, std_misc)]
1+
#![feature(core, libc, net, path, std_misc)]
22

33
extern crate nix;
44
extern crate libc;

0 commit comments

Comments
 (0)