diff options
| author | bors <bors@rust-lang.org> | 2015-04-22 03:38:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-04-22 03:38:20 +0000 |
| commit | c0eb9384af9f623563df59a9ae454ffedea1f4f8 (patch) | |
| tree | aaa36f5462dfe299902c6829795a8a8988f3061e /src/libstd/sys | |
| parent | 2baf3482537f5a245a9c17ca730398f1a8b001d7 (diff) | |
| parent | 58150640254e939519e57bf643af841cc60c1ac3 (diff) | |
| download | rust-c0eb9384af9f623563df59a9ae454ffedea1f4f8.tar.gz rust-c0eb9384af9f623563df59a9ae454ffedea1f4f8.zip | |
Auto merge of #24674 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/common/net.rs | 971 | ||||
| -rw-r--r-- | src/libstd/sys/common/wtf8.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/unix/condvar.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sys/unix/ext.rs | 34 | ||||
| -rw-r--r-- | src/libstd/sys/unix/helper_signal.rs | 31 | ||||
| -rw-r--r-- | src/libstd/sys/unix/mod.rs | 24 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process2.rs | 16 | ||||
| -rw-r--r-- | src/libstd/sys/windows/c.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext.rs | 48 | ||||
| -rw-r--r-- | src/libstd/sys/windows/fs2.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sys/windows/mod.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys/windows/net.rs | 15 | ||||
| -rw-r--r-- | src/libstd/sys/windows/process2.rs | 4 |
13 files changed, 120 insertions, 1054 deletions
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs deleted file mode 100644 index fc21effb45a..00000000000 --- a/src/libstd/sys/common/net.rs +++ /dev/null @@ -1,971 +0,0 @@ -// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(deprecated)] - -use prelude::v1::*; -use self::SocketStatus::*; -use self::InAddr::*; - -use ffi::{CString, CStr}; -use old_io::net::addrinfo; -use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; -use old_io::{IoResult, IoError}; -use libc::{self, c_char, c_int}; -use mem; -use num::Int; -use ptr::{self, null, null_mut}; -use str; -use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock, - wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval, - decode_error_detailed}; -use sync::{Arc, Mutex}; -#[cfg(not(target_os = "linux"))] -use sync::MutexGuard; -use sys_common::{self, keep_going, short_write, timeout}; -use cmp; -use old_io; - -// FIXME: move uses of Arc and deadline tracking to std::io - -#[derive(Debug)] -pub enum SocketStatus { - Readable, - Writable, -} - -//////////////////////////////////////////////////////////////////////////////// -// sockaddr and misc bindings -//////////////////////////////////////////////////////////////////////////////// - -pub fn htons(u: u16) -> u16 { - u.to_be() -} -pub fn ntohs(u: u16) -> u16 { - Int::from_be(u) -} - -pub enum InAddr { - In4Addr(libc::in_addr), - In6Addr(libc::in6_addr), -} - -pub fn ip_to_inaddr(ip: IpAddr) -> InAddr { - match ip { - Ipv4Addr(a, b, c, d) => { - let ip = ((a as u32) << 24) | - ((b as u32) << 16) | - ((c as u32) << 8) | - ((d as u32) << 0); - In4Addr(libc::in_addr { - s_addr: Int::from_be(ip) - }) - } - Ipv6Addr(a, b, c, d, e, f, g, h) => { - In6Addr(libc::in6_addr { - s6_addr: [ - htons(a), - htons(b), - htons(c), - htons(d), - htons(e), - htons(f), - htons(g), - htons(h), - ] - }) - } - } -} - -pub fn addr_to_sockaddr(addr: SocketAddr, - storage: &mut libc::sockaddr_storage) - -> libc::socklen_t { - unsafe { - let len = match ip_to_inaddr(addr.ip) { - In4Addr(inaddr) => { - let storage = storage as *mut _ as *mut libc::sockaddr_in; - (*storage).sin_family = libc::AF_INET as libc::sa_family_t; - (*storage).sin_port = htons(addr.port); - (*storage).sin_addr = inaddr; - mem::size_of::<libc::sockaddr_in>() - } - In6Addr(inaddr) => { - let storage = storage as *mut _ as *mut libc::sockaddr_in6; - (*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t; - (*storage).sin6_port = htons(addr.port); - (*storage).sin6_addr = inaddr; - mem::size_of::<libc::sockaddr_in6>() - } - }; - return len as libc::socklen_t; - } -} - -pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult<sock_t> { - unsafe { - let fam = match addr.ip { - Ipv4Addr(..) => libc::AF_INET, - Ipv6Addr(..) => libc::AF_INET6, - }; - match libc::socket(fam, ty, 0) as i32 { - -1 => Err(last_net_error()), - fd => Ok(fd as sock_t), - } - } -} - -pub fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int, - payload: T) -> IoResult<()> { - unsafe { - let payload = &payload as *const T as *const libc::c_void; - let ret = libc::setsockopt(fd, opt, val, - payload, - mem::size_of::<T>() as libc::socklen_t); - if ret != 0 { - Err(last_net_error()) - } else { - Ok(()) - } - } -} - -pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int, - val: libc::c_int) -> IoResult<T> { - unsafe { - let mut slot: T = mem::zeroed(); - let mut len = mem::size_of::<T>() as libc::socklen_t; - let ret = c::getsockopt(fd, opt, val, - &mut slot as *mut _ as *mut _, - &mut len); - if ret != 0 { - Err(last_net_error()) - } else { - assert!(len as usize == mem::size_of::<T>()); - Ok(slot) - } - } -} - -pub fn sockname(fd: sock_t, - f: unsafe extern "system" fn(sock_t, *mut libc::sockaddr, - *mut libc::socklen_t) -> libc::c_int) - -> IoResult<SocketAddr> -{ - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t; - unsafe { - let storage = &mut storage as *mut libc::sockaddr_storage; - let ret = f(fd, - storage as *mut libc::sockaddr, - &mut len as *mut libc::socklen_t); - if ret != 0 { - return Err(last_net_error()) - } - } - return sockaddr_to_addr(&storage, len as usize); -} - -pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, - len: usize) -> IoResult<SocketAddr> { - match storage.ss_family as libc::c_int { - libc::AF_INET => { - assert!(len as usize >= mem::size_of::<libc::sockaddr_in>()); - let storage: &libc::sockaddr_in = unsafe { - mem::transmute(storage) - }; - let ip = (storage.sin_addr.s_addr as u32).to_be(); - let a = (ip >> 24) as u8; - let b = (ip >> 16) as u8; - let c = (ip >> 8) as u8; - let d = (ip >> 0) as u8; - Ok(SocketAddr { - ip: Ipv4Addr(a, b, c, d), - port: ntohs(storage.sin_port), - }) - } - libc::AF_INET6 => { - assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>()); - let storage: &libc::sockaddr_in6 = unsafe { - mem::transmute(storage) - }; - let a = ntohs(storage.sin6_addr.s6_addr[0]); - let b = ntohs(storage.sin6_addr.s6_addr[1]); - let c = ntohs(storage.sin6_addr.s6_addr[2]); - let d = ntohs(storage.sin6_addr.s6_addr[3]); - let e = ntohs(storage.sin6_addr.s6_addr[4]); - let f = ntohs(storage.sin6_addr.s6_addr[5]); - let g = ntohs(storage.sin6_addr.s6_addr[6]); - let h = ntohs(storage.sin6_addr.s6_addr[7]); - Ok(SocketAddr { - ip: Ipv6Addr(a, b, c, d, e, f, g, h), - port: ntohs(storage.sin6_port), - }) - } - _ => { - Err(IoError { - kind: old_io::InvalidInput, - desc: "invalid argument", - detail: None, - }) - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// get_host_addresses -//////////////////////////////////////////////////////////////////////////////// - -extern "system" { - fn getaddrinfo(node: *const c_char, service: *const c_char, - hints: *const libc::addrinfo, - res: *mut *mut libc::addrinfo) -> c_int; - fn freeaddrinfo(res: *mut libc::addrinfo); -} - -pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, - hint: Option<addrinfo::Hint>) - -> Result<Vec<addrinfo::Info>, IoError> -{ - sys::init_net(); - - assert!(host.is_some() || servname.is_some()); - - let c_host = match host { - Some(x) => Some(try!(CString::new(x))), - None => None, - }; - let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); - let c_serv = match servname { - Some(x) => Some(try!(CString::new(x))), - None => None, - }; - let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); - - let hint = hint.map(|hint| { - libc::addrinfo { - ai_flags: hint.flags as c_int, - ai_family: hint.family as c_int, - ai_socktype: 0, - ai_protocol: 0, - ai_addrlen: 0, - ai_canonname: null_mut(), - ai_addr: null_mut(), - ai_next: null_mut() - } - }); - - let hint_ptr = hint.as_ref().map_or(null(), |x| { - x as *const libc::addrinfo - }); - let mut res = null_mut(); - - // Make the call - let s = unsafe { - getaddrinfo(c_host, c_serv, hint_ptr, &mut res) - }; - - // Error? - if s != 0 { - return Err(last_gai_error(s)); - } - - // Collect all the results we found - let mut addrs = Vec::new(); - let mut rp = res; - while !rp.is_null() { - unsafe { - let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr), - (*rp).ai_addrlen as usize)); - addrs.push(addrinfo::Info { - address: addr, - family: (*rp).ai_family as usize, - socktype: None, - protocol: None, - flags: (*rp).ai_flags as usize - }); - - rp = (*rp).ai_next as *mut libc::addrinfo; - } - } - - unsafe { freeaddrinfo(res); } - - Ok(addrs) -} - -//////////////////////////////////////////////////////////////////////////////// -// get_address_name -//////////////////////////////////////////////////////////////////////////////// - -extern "system" { - fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t, - host: *mut c_char, hostlen: libc::size_t, - serv: *mut c_char, servlen: libc::size_t, - flags: c_int) -> c_int; -} - -const NI_MAXHOST: usize = 1025; - -pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> { - let addr = SocketAddr{ip: addr, port: 0}; - - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - - let mut hostbuf = [0 as c_char; NI_MAXHOST]; - - let res = unsafe { - getnameinfo(&storage as *const _ as *const libc::sockaddr, len, - hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, - ptr::null_mut(), 0, - 0) - }; - - if res != 0 { - return Err(last_gai_error(res)); - } - - unsafe { - let data = CStr::from_ptr(hostbuf.as_ptr()); - Ok(str::from_utf8(data.to_bytes()).unwrap().to_string()) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Timeout helpers -// -// The read/write functions below are the helpers for reading/writing a socket -// with a possible deadline specified. This is generally viewed as a timed out -// I/O operation. -// -// From the application's perspective, timeouts apply to the I/O object, not to -// the underlying file descriptor (it's one timeout per object). This means that -// we can't use the SO_RCVTIMEO and corresponding send timeout option. -// -// The next idea to implement timeouts would be to use nonblocking I/O. An -// invocation of select() would wait (with a timeout) for a socket to be ready. -// Once its ready, we can perform the operation. Note that the operation *must* -// be nonblocking, even though select() says the socket is ready. This is -// because some other thread could have come and stolen our data (handles can be -// cloned). -// -// To implement nonblocking I/O, the first option we have is to use the -// O_NONBLOCK flag. Remember though that this is a global setting, affecting all -// I/O objects, so this was initially viewed as unwise. -// -// It turns out that there's this nifty MSG_DONTWAIT flag which can be passed to -// send/recv, but the niftiness wears off once you realize it only works well on -// Linux [1] [2]. This means that it's pretty easy to get a nonblocking -// operation on Linux (no flag fiddling, no affecting other objects), but not on -// other platforms. -// -// To work around this constraint on other platforms, we end up using the -// original strategy of flipping the O_NONBLOCK flag. As mentioned before, this -// could cause other objects' blocking operations to suddenly become -// nonblocking. To get around this, a "blocking operation" which returns EAGAIN -// falls back to using the same code path as nonblocking operations, but with an -// infinite timeout (select + send/recv). This helps emulate blocking -// reads/writes despite the underlying descriptor being nonblocking, as well as -// optimizing the fast path of just hitting one syscall in the good case. -// -// As a final caveat, this implementation uses a mutex so only one thread is -// doing a nonblocking operation at at time. This is the operation that comes -// after the select() (at which point we think the socket is ready). This is -// done for sanity to ensure that the state of the O_NONBLOCK flag is what we -// expect (wouldn't want someone turning it on when it should be off!). All -// operations performed in the lock are *nonblocking* to avoid holding the mutex -// forever. -// -// So, in summary, Linux uses MSG_DONTWAIT and doesn't need mutexes, everyone -// else uses O_NONBLOCK and mutexes with some trickery to make sure blocking -// reads/writes are still blocking. -// -// Fun, fun! -// -// [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html -// [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait - -pub fn read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult<usize> where - L: FnMut() -> T, - R: FnMut(bool) -> libc::c_int, -{ - let mut ret = -1; - if deadline == 0 { - ret = retry(|| read(false)); - } - - if deadline != 0 || (ret == -1 && wouldblock()) { - let deadline = match deadline { - 0 => None, - n => Some(n), - }; - loop { - // With a timeout, first we wait for the socket to become - // readable using select(), specifying the relevant timeout for - // our previously set deadline. - try!(await(&[fd], deadline, Readable)); - - // At this point, we're still within the timeout, and we've - // determined that the socket is readable (as returned by - // select). We must still read the socket in *nonblocking* mode - // because some other thread could come steal our data. If we - // fail to read some data, we retry (hence the outer loop) and - // wait for the socket to become readable again. - let _guard = lock(); - match retry(|| read(deadline.is_some())) { - -1 if wouldblock() => {} - -1 => return Err(last_net_error()), - n => { ret = n; break } - } - } - } - - match ret { - 0 => Err(sys_common::eof()), - n if n < 0 => Err(last_net_error()), - n => Ok(n as usize) - } -} - -pub fn write<T, L, W>(fd: sock_t, - deadline: u64, - buf: &[u8], - write_everything: bool, - mut lock: L, - mut write: W) -> IoResult<usize> where - L: FnMut() -> T, - W: FnMut(bool, *const u8, usize) -> i64, -{ - let mut ret = -1; - let mut written = 0; - if deadline == 0 { - if write_everything { - ret = keep_going(buf, |inner, len| { - written = buf.len() - len; - write(false, inner, len) - }); - } else { - ret = retry(|| { write(false, buf.as_ptr(), buf.len()) }); - if ret > 0 { written = ret as usize; } - } - } - - if deadline != 0 || (ret == -1 && wouldblock()) { - let deadline = match deadline { - 0 => None, - n => Some(n), - }; - while written < buf.len() && (write_everything || written == 0) { - // As with read(), first wait for the socket to be ready for - // the I/O operation. - match await(&[fd], deadline, Writable) { - Err(ref e) if e.kind == old_io::EndOfFile && written > 0 => { - assert!(deadline.is_some()); - return Err(short_write(written, "short write")) - } - Err(e) => return Err(e), - Ok(()) => {} - } - - // Also as with read(), we use MSG_DONTWAIT to guard ourselves - // against unforeseen circumstances. - let _guard = lock(); - let ptr = buf[written..].as_ptr(); - let len = buf.len() - written; - match retry(|| write(deadline.is_some(), ptr, len)) { - -1 if wouldblock() => {} - -1 => return Err(last_net_error()), - n => { written += n as usize; } - } - } - ret = 0; - } - if ret < 0 { - Err(last_net_error()) - } else { - Ok(written) - } -} - -// See http://developerweb.net/viewtopic.php?id=3196 for where this is -// derived from. -pub fn connect_timeout(fd: sock_t, - addrp: *const libc::sockaddr, - len: libc::socklen_t, - timeout_ms: u64) -> IoResult<()> { - #[cfg(unix)] use libc::EINPROGRESS as INPROGRESS; - #[cfg(windows)] use libc::WSAEINPROGRESS as INPROGRESS; - #[cfg(unix)] use libc::EWOULDBLOCK as WOULDBLOCK; - #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK; - - // Make sure the call to connect() doesn't block - set_nonblocking(fd, true); - - let ret = match unsafe { libc::connect(fd, addrp, len) } { - // If the connection is in progress, then we need to wait for it to - // finish (with a timeout). The current strategy for doing this is - // to use select() with a timeout. - -1 if os::errno() as isize == INPROGRESS as isize || - os::errno() as isize == WOULDBLOCK as isize => { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - c::fd_set(&mut set, fd); - match await(fd, &mut set, timeout_ms) { - 0 => Err(timeout("connection timed out")), - -1 => Err(last_net_error()), - _ => { - let err: libc::c_int = try!( - getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR)); - if err == 0 { - Ok(()) - } else { - Err(decode_error_detailed(err)) - } - } - } - } - - -1 => Err(last_net_error()), - _ => Ok(()), - }; - - // be sure to turn blocking I/O back on - set_nonblocking(fd, false); - return ret; - - #[cfg(unix)] - fn await(fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int { - let start = timer::now(); - retry(|| unsafe { - // Recalculate the timeout each iteration (it is generally - // undefined what the value of the 'tv' is after select - // returns EINTR). - let mut tv = ms_to_timeval(timeout - (timer::now() - start)); - c::select(fd + 1, ptr::null_mut(), set as *mut _, - ptr::null_mut(), &mut tv) - }) - } - #[cfg(windows)] - fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int { - let mut tv = ms_to_timeval(timeout); - unsafe { c::select(1, ptr::null_mut(), set, ptr::null_mut(), &mut tv) } - } -} - -pub fn await(fds: &[sock_t], deadline: Option<u64>, - status: SocketStatus) -> IoResult<()> { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - let mut max = 0; - for &fd in fds { - c::fd_set(&mut set, fd); - max = cmp::max(max, fd + 1); - } - if cfg!(windows) { - max = fds.len() as sock_t; - } - - let (read, write) = match status { - Readable => (&mut set as *mut _, ptr::null_mut()), - Writable => (ptr::null_mut(), &mut set as *mut _), - }; - let mut tv: libc::timeval = unsafe { mem::zeroed() }; - - match retry(|| { - let now = timer::now(); - let tvp = match deadline { - None => ptr::null_mut(), - Some(deadline) => { - // If we're past the deadline, then pass a 0 timeout to - // select() so we can poll the status - let ms = if deadline < now {0} else {deadline - now}; - tv = ms_to_timeval(ms); - &mut tv as *mut _ - } - }; - let r = unsafe { - c::select(max as libc::c_int, read, write, ptr::null_mut(), tvp) - }; - r - }) { - -1 => Err(last_net_error()), - 0 => Err(timeout("timed out")), - _ => Ok(()), - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Basic socket representation -//////////////////////////////////////////////////////////////////////////////// - -struct Inner { - fd: sock_t, - - // Unused on Linux, where this lock is not necessary. - #[allow(dead_code)] - lock: Mutex<()>, -} - -impl Inner { - fn new(fd: sock_t) -> Inner { - Inner { fd: fd, lock: Mutex::new(()) } - } -} - -impl Drop for Inner { - fn drop(&mut self) { unsafe { close_sock(self.fd); } } -} - -#[cfg(not(target_os = "linux"))] -pub struct Guard<'a> { - pub fd: sock_t, - pub guard: MutexGuard<'a, ()>, -} - -#[cfg(not(target_os = "linux"))] -#[unsafe_destructor] -impl<'a> Drop for Guard<'a> { - fn drop(&mut self) { - set_nonblocking(self.fd, false); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// TCP streams -//////////////////////////////////////////////////////////////////////////////// - -pub struct TcpStream { - inner: Arc<Inner>, - read_deadline: u64, - write_deadline: u64, -} - -impl TcpStream { - pub fn connect(addr: SocketAddr, timeout: Option<u64>) -> IoResult<TcpStream> { - sys::init_net(); - - let fd = try!(socket(addr, libc::SOCK_STREAM)); - let ret = TcpStream::new(fd); - - let mut storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - let addrp = &storage as *const _ as *const libc::sockaddr; - - match timeout { - Some(timeout) => { - try!(connect_timeout(fd, addrp, len, timeout)); - Ok(ret) - }, - None => { - match retry(|| unsafe { libc::connect(fd, addrp, len) }) { - -1 => Err(last_error()), - _ => Ok(ret), - } - } - } - } - - pub fn new(fd: sock_t) -> TcpStream { - TcpStream { - inner: Arc::new(Inner::new(fd)), - read_deadline: 0, - write_deadline: 0, - } - } - - pub fn fd(&self) -> sock_t { self.inner.fd } - - pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_NODELAY, - nodelay as libc::c_int) - } - - pub fn set_keepalive(&mut self, seconds: Option<usize>) -> IoResult<()> { - let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE, - seconds.is_some() as libc::c_int); - match seconds { - Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)), - None => ret, - } - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, - seconds as libc::c_int) - } - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly"))] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, - seconds as libc::c_int) - } - #[cfg(target_os = "openbsd")] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE, - seconds as libc::c_int) - } - #[cfg(not(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd")))] - fn set_tcp_keepalive(&mut self, _seconds: usize) -> IoResult<()> { - Ok(()) - } - - #[cfg(target_os = "linux")] - fn lock_nonblocking(&self) {} - - #[cfg(not(target_os = "linux"))] - fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { - let ret = Guard { - fd: self.fd(), - guard: self.inner.lock.lock().unwrap(), - }; - set_nonblocking(self.fd(), true); - ret - } - - pub fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let doread = |nb| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::recv(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as wrlen, - flags) as libc::c_int - }; - read(fd, self.read_deadline, dolock, doread) - } - - pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::send(fd, - buf as *const _, - len as wrlen, - flags) as i64 - }; - write(fd, self.write_deadline, buf, true, dolock, dowrite).map(|_| ()) - } - pub fn peer_name(&mut self) -> IoResult<SocketAddr> { - sockname(self.fd(), libc::getpeername) - } - - pub fn close_write(&mut self) -> IoResult<()> { - super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) }) - } - pub fn close_read(&mut self) -> IoResult<()> { - super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) }) - } - - pub fn set_timeout(&mut self, timeout: Option<u64>) { - let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - self.read_deadline = deadline; - self.write_deadline = deadline; - } - pub fn set_read_timeout(&mut self, timeout: Option<u64>) { - self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - pub fn set_write_timeout(&mut self, timeout: Option<u64>) { - self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - - pub fn socket_name(&mut self) -> IoResult<SocketAddr> { - sockname(self.fd(), libc::getsockname) - } -} - -impl Clone for TcpStream { - fn clone(&self) -> TcpStream { - TcpStream { - inner: self.inner.clone(), - read_deadline: 0, - write_deadline: 0, - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// UDP -//////////////////////////////////////////////////////////////////////////////// - -pub struct UdpSocket { - inner: Arc<Inner>, - read_deadline: u64, - write_deadline: u64, -} - -impl UdpSocket { - pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> { - sys::init_net(); - - let fd = try!(socket(addr, libc::SOCK_DGRAM)); - let ret = UdpSocket { - inner: Arc::new(Inner::new(fd)), - read_deadline: 0, - write_deadline: 0, - }; - - let mut storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - let addrp = &storage as *const _ as *const libc::sockaddr; - - match unsafe { libc::bind(fd, addrp, len) } { - -1 => Err(last_error()), - _ => Ok(ret), - } - } - - pub fn fd(&self) -> sock_t { self.inner.fd } - - pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_BROADCAST, - on as libc::c_int) - } - - pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, - on as libc::c_int) - } - - pub fn set_membership(&mut self, addr: IpAddr, opt: libc::c_int) -> IoResult<()> { - match ip_to_inaddr(addr) { - In4Addr(addr) => { - let mreq = libc::ip_mreq { - imr_multiaddr: addr, - // interface == INADDR_ANY - imr_interface: libc::in_addr { s_addr: 0x0 }, - }; - setsockopt(self.fd(), libc::IPPROTO_IP, opt, mreq) - } - In6Addr(addr) => { - let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: addr, - ipv6mr_interface: 0, - }; - setsockopt(self.fd(), libc::IPPROTO_IPV6, opt, mreq) - } - } - } - - #[cfg(target_os = "linux")] - fn lock_nonblocking(&self) {} - - #[cfg(not(target_os = "linux"))] - fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { - let ret = Guard { - fd: self.fd(), - guard: self.inner.lock.lock().unwrap(), - }; - set_nonblocking(self.fd(), true); - ret - } - - pub fn socket_name(&mut self) -> IoResult<SocketAddr> { - sockname(self.fd(), libc::getsockname) - } - - pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> { - let fd = self.fd(); - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let storagep = &mut storage as *mut _ as *mut libc::sockaddr; - let mut addrlen: libc::socklen_t = - mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t; - - let dolock = || self.lock_nonblocking(); - let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::recvfrom(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as msglen_t, - flags, - storagep, - &mut addrlen) as libc::c_int - })); - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize).unwrap())) - } - - pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { - let mut storage = unsafe { mem::zeroed() }; - let dstlen = addr_to_sockaddr(dst, &mut storage); - let dstp = &storage as *const _ as *const libc::sockaddr; - - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let dowrite = |nb, buf: *const u8, len: usize| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::sendto(fd, - buf as *const libc::c_void, - len as msglen_t, - flags, - dstp, - dstlen) as i64 - }; - - let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite)); - assert!(n == buf.len(), "UDP packet not completely written."); - Ok(()) - } - - pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> { - match multi { - Ipv4Addr(..) => { - self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) - } - Ipv6Addr(..) => { - self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) - } - } - } - pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> { - match multi { - Ipv4Addr(..) => { - self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) - } - Ipv6Addr(..) => { - self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) - } - } - } - - pub fn multicast_time_to_live(&mut self, ttl: isize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, - ttl as libc::c_int) - } - pub fn time_to_live(&mut self, ttl: isize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int) - } - - pub fn set_timeout(&mut self, timeout: Option<u64>) { - let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - self.read_deadline = deadline; - self.write_deadline = deadline; - } - pub fn set_read_timeout(&mut self, timeout: Option<u64>) { - self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - pub fn set_write_timeout(&mut self, timeout: Option<u64>) { - self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } -} - -impl Clone for UdpSocket { - fn clone(&self) -> UdpSocket { - UdpSocket { - inner: self.inner.clone(), - read_deadline: 0, - write_deadline: 0, - } - } -} diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index aa035a18437..56a952e6a7e 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -35,10 +35,8 @@ use borrow::Cow; use cmp; use fmt; use hash::{Hash, Hasher}; -use iter::{FromIterator, IntoIterator}; +use iter::FromIterator; use mem; -#[allow(deprecated)] // Int -use num::Int; use ops; use slice; use str; diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 90dfebc4c45..ed6382e000a 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -17,7 +17,6 @@ use sys::mutex::{self, Mutex}; use sys::time; use sys::sync as ffi; use time::Duration; -use num::{Int, NumCast}; pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> } @@ -70,8 +69,8 @@ impl Condvar { let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut()); debug_assert_eq!(r, 0); - let seconds = NumCast::from(dur.num_seconds()); - let timeout = match seconds.and_then(|s| sys_now.tv_sec.checked_add(s)) { + let seconds = dur.num_seconds() as libc::time_t; + let timeout = match sys_now.tv_sec.checked_add(seconds) { Some(sec) => { libc::timespec { tv_sec: sec, @@ -81,7 +80,7 @@ impl Condvar { } None => { libc::timespec { - tv_sec: Int::max_value(), + tv_sec: <libc::time_t>::max_value(), tv_nsec: 1_000_000_000 - 1, } } diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 032fd33b1d3..9504fe63697 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -189,8 +189,12 @@ pub mod ffi { #[unstable(feature = "fs_ext", reason = "may want a more useful mode abstraction")] pub mod fs { + use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use fs::{Permissions, OpenOptions}; + use path::Path; + use convert::AsRef; + use io; /// Unix-specific extensions to `Permissions` pub trait PermissionsExt { @@ -220,6 +224,36 @@ pub mod fs { self.as_inner_mut().mode(mode); self } } + + /// Creates a new symbolic link on the filesystem. + /// + /// The `dst` path will be a symbolic link pointing to the `src` path. + /// + /// # Note + /// + /// On Windows, you must specify whether a symbolic link points to a file + /// or directory. Use `os::windows::fs::symlink_file` to create a + /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a + /// symbolic link to a directory. Additionally, the process must have + /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a + /// symbolic link. + /// + /// # Examples + /// + /// ``` + /// #![feature(fs_ext)] + /// use std::os::unix::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink("a.txt", "b.txt")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> + { + sys::fs2::symlink(src.as_ref(), dst.as_ref()) + } + } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs deleted file mode 100644 index fe0ede80fc6..00000000000 --- a/src/libstd/sys/unix/helper_signal.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(deprecated)] - -use libc; -use sys::os; - -use sys::fs::FileDesc; - -pub type signal = libc::c_int; - -pub fn new() -> (signal, signal) { - let (a, b) = unsafe { os::pipe().unwrap() }; - (a.unwrap(), b.unwrap()) -} - -pub fn signal(fd: libc::c_int) { - FileDesc::new(fd, false).write(&[0]).unwrap(); -} - -pub fn close(fd: libc::c_int) { - let _fd = FileDesc::new(fd, true); -} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index a8a6219f398..d99753a6a4c 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -15,7 +15,8 @@ use prelude::v1::*; use io::{self, ErrorKind}; use libc; -use num::{Int, SignedInt}; +use num::One; +use ops::Neg; pub mod backtrace; pub mod c; @@ -63,23 +64,8 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } -#[inline] -#[allow(deprecated)] -pub fn retry<T, F> (mut f: F) -> T where - T: SignedInt, - F: FnMut() -> T, -{ - let one: T = Int::one(); - loop { - let n = f(); - if n == -one && os::errno() == libc::EINTR as i32 { } - else { return n } - } -} - -#[allow(deprecated)] -pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> { - let one: T = Int::one(); +pub fn cvt<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> { + let one: T = T::one(); if t == -one { Err(io::Error::last_os_error()) } else { @@ -89,7 +75,7 @@ pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> { #[allow(deprecated)] pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> - where T: SignedInt, F: FnMut() -> T + where T: One + PartialEq + Neg<Output=T>, F: FnMut() -> T { loop { match cvt(f()) { diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index caa7b4eb29c..4e7c4d241f5 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -19,7 +19,7 @@ use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_void, c_int, gid_t, uid_t}; use ptr; use sys::pipe2::AnonPipe; -use sys::{self, retry, c, cvt}; +use sys::{self, c, cvt, cvt_r}; use sys::fs2::{File, OpenOptions}; //////////////////////////////////////////////////////////////////////////////// @@ -273,7 +273,7 @@ impl Process { } } }; - retry(|| libc::dup2(fd.raw(), dst)) != -1 + cvt_r(|| libc::dup2(fd.raw(), dst)).is_ok() }; if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) } @@ -317,19 +317,19 @@ impl Process { pub fn wait(&self) -> io::Result<ExitStatus> { let mut status = 0 as c_int; - try!(cvt(retry(|| unsafe { c::waitpid(self.pid, &mut status, 0) }))); + try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) })); Ok(translate_status(status)) } pub fn try_wait(&self) -> Option<ExitStatus> { let mut status = 0 as c_int; - match retry(|| unsafe { + match cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, c::WNOHANG) }) { - n if n == self.pid => Some(translate_status(status)), - 0 => None, - n => panic!("unknown waitpid error `{}`: {}", n, - io::Error::last_os_error()), + Ok(0) => None, + Ok(n) if n == self.pid => Some(translate_status(status)), + Ok(n) => panic!("unkown pid: {}", n), + Err(e) => panic!("unknown waitpid error: {}", e), } } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 45f389f0aeb..331bfbfff36 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -54,6 +54,8 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8; pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c; +pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1; + // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD; pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 90548dcefb4..eac6496870e 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -191,7 +191,11 @@ pub mod ffi { #[unstable(feature = "fs_ext", reason = "may require more thought/methods")] pub mod fs { use fs::OpenOptions; + use sys; use sys_common::AsInnerMut; + use path::Path; + use convert::AsRef; + use io; /// Windows-specific extensions to `OpenOptions` pub trait OpenOptionsExt { @@ -235,6 +239,50 @@ pub mod fs { self.as_inner_mut().share_mode(access); self } } + + /// Creates a new file symbolic link on the filesystem. + /// + /// The `dst` path will be a file symbolic link pointing to the `src` + /// path. + /// + /// # Examples + /// + /// ```ignore + /// #![feature(fs_ext)] + /// use std::os::windows::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink_file("a.txt", "b.txt")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) + -> io::Result<()> + { + sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false) + } + + /// Creates a new directory symlink on the filesystem. + /// + /// The `dst` path will be a directory symbolic link pointing to the `src` + /// path. + /// + /// # Examples + /// + /// ```ignore + /// #![feature(fs_ext)] + /// use std::os::windows::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink_file("a", "b")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>> (src: P, dst: Q) + -> io::Result<()> + { + sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true) + } } /// A prelude for conveniently writing platform-specific code. diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index b0515a71229..5ac9a0ace58 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -12,8 +12,7 @@ use core::prelude::*; use io::prelude::*; use os::windows::prelude::*; -use default::Default; -use ffi::{OsString, AsOsStr}; +use ffi::OsString; use fmt; use io::{self, Error, SeekFrom}; use libc::{self, HANDLE}; @@ -412,11 +411,16 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { + symlink_inner(src, dst, false) +} + +pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { use sys::c::compat::kernel32::CreateSymbolicLinkW; let src = to_utf16(src); let dst = to_utf16(dst); + let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; try!(cvt(unsafe { - CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL + CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL })); Ok(()) } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 1171c6c068b..5ae5f6f201b 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -17,8 +17,7 @@ use prelude::v1::*; use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; use libc; -#[allow(deprecated)] -use num::Int; +use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; @@ -144,9 +143,8 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { } } -#[allow(deprecated)] -fn cvt<I: Int>(i: I) -> io::Result<I> { - if i == Int::zero() { +fn cvt<I: PartialEq + Zero>(i: I) -> io::Result<I> { + if i == I::zero() { Err(io::Error::last_os_error()) } else { Ok(i) diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index cbc3876dbb1..6bbcd968157 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -15,8 +15,8 @@ use libc::consts::os::extra::INVALID_SOCKET; use libc::{self, c_int, c_void}; use mem; use net::SocketAddr; -#[allow(deprecated)] -use num::{SignedInt, Int}; +use num::One; +use ops::Neg; use rt; use sync::{Once, ONCE_INIT}; use sys::c; @@ -49,11 +49,8 @@ fn last_error() -> io::Error { /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) /// and if so, returns the last error from the Windows socket interface. . This /// function must be called before another call to the socket API is made. -/// -/// FIXME: generics needed? -#[allow(deprecated)] -pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> { - let one: T = Int::one(); +pub fn cvt<T: One + Neg<Output=T> + PartialEq>(t: T) -> io::Result<T> { + let one: T = T::one(); if t == -one { Err(last_error()) } else { @@ -70,7 +67,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { /// Provides the functionality of `cvt` for a closure. #[allow(deprecated)] -pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T { +pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> + where F: FnMut() -> T, T: One + Neg<Output=T> + PartialEq +{ cvt(f()) } diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 16c2a9125ea..5ddcf3d1ea2 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -140,7 +140,7 @@ impl Process { // read the *child's* PATH if one is provided. See #15149 for more details. let program = cfg.env.as_ref().and_then(|env| { for (key, v) in env { - if OsStr::from_str("PATH") != &**key { continue } + if OsStr::new("PATH") != &**key { continue } // Split the value and test each path to see if the // program exists. @@ -463,7 +463,7 @@ mod tests { fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { String::from_utf16( - &make_command_line(OsStr::from_str(prog), + &make_command_line(OsStr::new(prog), &args.iter() .map(|a| OsString::from(a)) .collect::<Vec<OsString>>())).unwrap() |
