about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-22 03:38:20 +0000
committerbors <bors@rust-lang.org>2015-04-22 03:38:20 +0000
commitc0eb9384af9f623563df59a9ae454ffedea1f4f8 (patch)
treeaaa36f5462dfe299902c6829795a8a8988f3061e /src/libstd/sys
parent2baf3482537f5a245a9c17ca730398f1a8b001d7 (diff)
parent58150640254e939519e57bf643af841cc60c1ac3 (diff)
downloadrust-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.rs971
-rw-r--r--src/libstd/sys/common/wtf8.rs4
-rw-r--r--src/libstd/sys/unix/condvar.rs7
-rw-r--r--src/libstd/sys/unix/ext.rs34
-rw-r--r--src/libstd/sys/unix/helper_signal.rs31
-rw-r--r--src/libstd/sys/unix/mod.rs24
-rw-r--r--src/libstd/sys/unix/process2.rs16
-rw-r--r--src/libstd/sys/windows/c.rs2
-rw-r--r--src/libstd/sys/windows/ext.rs48
-rw-r--r--src/libstd/sys/windows/fs2.rs10
-rw-r--r--src/libstd/sys/windows/mod.rs8
-rw-r--r--src/libstd/sys/windows/net.rs15
-rw-r--r--src/libstd/sys/windows/process2.rs4
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()