diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index c1253706832..b01cb53388f 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -56,7 +56,7 @@ mod tempdir; #[stable(feature = "rust1", since = "1.0.0")] pub struct File { inner: fs_imp::File, - path: PathBuf, + path: Option, } /// Metadata information about a file. @@ -171,7 +171,7 @@ impl File { reason = "this abstraction is imposed by this library instead \ of the underlying OS and may be removed")] pub fn path(&self) -> Option<&Path> { - Some(&self.path) + self.path.as_ref().map(|p| &**p) } /// Attempt to sync all OS-internal metadata to disk. @@ -273,6 +273,12 @@ impl File { impl AsInner for File { fn as_inner(&self) -> &fs_imp::File { &self.inner } } +impl FromInner for File { + fn from_inner(f: fs_imp::File) -> File { + File { inner: f, path: None } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -381,7 +387,7 @@ impl OpenOptions { pub fn open>(&self, path: P) -> io::Result { let path = path.as_ref(); let inner = try!(fs_imp::File::open(path, &self.0)); - Ok(File { path: path.to_path_buf(), inner: inner }) + Ok(File { path: Some(path.to_path_buf()), inner: inner }) } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 869faa795f9..9ed08d05e8b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -17,7 +17,7 @@ use io::prelude::*; use io; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A structure which represents a TCP stream between a local socket and a /// remote socket. @@ -172,6 +172,10 @@ impl AsInner for TcpStream { fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } } +impl FromInner for TcpStream { + fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } +} + impl TcpListener { /// Creates a new `TcpListener` which will be bound to the specified /// address. @@ -245,6 +249,12 @@ impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } } +impl FromInner for TcpListener { + fn from_inner(inner: net_imp::TcpListener) -> TcpListener { + TcpListener(inner) + } +} + #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..4aeb3d7c7c8 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A User Datagram Protocol socket. /// @@ -140,6 +140,10 @@ impl AsInner for UdpSocket { fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } } +impl FromInner for UdpSocket { + fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) } +} + #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index e213a86644f..8b54b7e6fb4 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -222,6 +222,12 @@ impl TcpStream { } } +impl FromInner for TcpStream { + fn from_inner(socket: Socket) -> TcpStream { + TcpStream { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -275,6 +281,12 @@ impl TcpListener { } } +impl FromInner for TcpListener { + fn from_inner(socket: Socket) -> TcpListener { + TcpListener { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -387,3 +399,9 @@ impl UdpSocket { self.inner.duplicate().map(|s| UdpSocket { inner: s }) } } + +impl FromInner for UdpSocket { + fn from_inner(socket: Socket) -> UdpSocket { + UdpSocket { inner: socket } + } +} diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 0805949d560..080cf5620fc 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -32,102 +32,171 @@ #![stable(feature = "rust1", since = "1.0.0")] /// Unix-specific extensions to general I/O primitives -#[unstable(feature = "io_ext", - reason = "may want a slightly different organization or a more \ - general file descriptor primitive")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { #[allow(deprecated)] use old_io; use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; /// Raw file descriptors. - pub type Fd = libc::c_int; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawFd = libc::c_int; - /// Extract raw file descriptor + /// A trait to extract the raw unix file descriptor from an underlying + /// object. + /// + /// This is only available on unix platforms and must be imported in order + /// to call the method. Windows platforms have a corresponding `AsRawHandle` + /// and `AsRawSocket` set of traits. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawFd { - /// Extract the raw file descriptor, without taking any ownership. - fn as_raw_fd(&self) -> Fd; + /// Extract the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guarantee to be valid while + /// the original object has not yet been destroyed. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; + } + + /// A trait to express the ability to construct an object from a raw file + /// descriptor. + #[unstable(feature = "from_raw_os", + reason = "recent addition to std::os::unix::io")] + pub trait FromRawFd { + /// Constructs a new instances of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// Callers should normally only pass in a valid file descriptor to this + /// method or otherwise methods will return errors. + fn from_raw_fd(fd: RawFd) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for fs::File { + fn from_raw_fd(fd: RawFd) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(fd)) + } + } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::pipe::PipeStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::udp::UdpSocket { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpStream { + fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(net2::TcpStream::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpListener { + fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(net2::TcpListener::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::UdpSocket { + fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket)) + } } } @@ -302,7 +371,7 @@ pub mod process { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Fd, AsRawFd}; + pub use super::io::{RawFd, AsRawFd}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 202e5ddaec4..80fc1235a31 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -280,6 +280,12 @@ fn cstr(path: &Path) -> io::Result { Ok(cstring) } +impl FromInner for File { + fn from_inner(fd: c_int) -> File { + File(FileDesc::new(fd)) + } +} + pub fn mkdir(p: &Path) -> io::Result<()> { let p = try!(cstr(p)); try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) })); diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b22fa33e562..00b907ce10c 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -17,7 +17,7 @@ use str; use sys::c; use net::SocketAddr; use sys::fd::FileDesc; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub use sys::{cvt, cvt_r}; @@ -72,3 +72,7 @@ impl Socket { impl AsInner for Socket { fn as_inner(&self) -> &c_int { self.0.as_inner() } } + +impl FromInner for Socket { + fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) } +} diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 7955397892b..2dd61861bd6 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -16,112 +16,188 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "io_ext", - reason = "organization may change slightly and the primitives \ - provided may be tweaked")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; #[allow(deprecated)] use old_io; /// Raw HANDLEs. - pub type Handle = libc::HANDLE; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawHandle = libc::HANDLE; /// Raw SOCKETs. - pub type Socket = libc::SOCKET; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawSocket = libc::SOCKET; /// Extract raw handles. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawHandle { /// Extract the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> Handle; + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_handle(&self) -> RawHandle; + } + + /// Construct I/O objects from raw handles. + #[unstable(feature = "from_raw_os", + reason = "recent addition to the std::os::windows::io module")] + pub trait FromRawHandle { + /// Construct a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + fn from_raw_handle(handle: RawHandle) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawHandle for fs::File { + fn from_raw_handle(handle: RawHandle) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(handle)) + } + } + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::pipe::PipeStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixListener { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixAcceptor { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } /// Extract raw sockets. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawSocket { - fn as_raw_socket(&self) -> Socket; + /// Extract the underlying raw socket from this object. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_socket(&self) -> RawSocket; + } + + /// Create I/O objects from raw sockets. + #[unstable(feature = "from_raw_os", reason = "recent addition to module")] + pub trait FromRawSocket { + /// Creates a new I/O object from the given raw socket. + /// + /// This function will **consume ownership** of the socket provided and + /// it will be closed when the returned object goes out of scope. + fn from_raw_socket(sock: RawSocket) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpStream { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpListener { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpAcceptor { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::udp::UdpSocket { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpStream { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpListener { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::UdpSocket { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpStream { + fn from_raw_socket(sock: RawSocket) -> net::TcpStream { + let sock = sys::net::Socket::from_inner(sock); + net::TcpStream::from_inner(net2::TcpStream::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpListener { + fn from_raw_socket(sock: RawSocket) -> net::TcpListener { + let sock = sys::net::Socket::from_inner(sock); + net::TcpListener::from_inner(net2::TcpListener::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::UdpSocket { + fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { + let sock = sys::net::Socket::from_inner(sock); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock)) + } } } @@ -230,7 +306,7 @@ pub mod fs { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Socket, Handle, AsRawSocket, AsRawHandle}; + pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 99835265111..d03e45649ed 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -20,11 +20,12 @@ use mem; use path::{Path, PathBuf}; use ptr; use sync::Arc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use sys::{c, cvt}; +use sys_common::FromInner; use vec::Vec; -pub struct File { handle: RawHandle } +pub struct File { handle: Handle } pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA } pub struct ReadDir { @@ -192,7 +193,7 @@ impl File { if handle == libc::INVALID_HANDLE_VALUE { Err(Error::last_os_error()) } else { - Ok(File { handle: RawHandle::new(handle) }) + Ok(File { handle: Handle::new(handle) }) } } @@ -260,7 +261,13 @@ impl File { Ok(newpos as u64) } - pub fn handle(&self) -> &RawHandle { &self.handle } + pub fn handle(&self) -> &Handle { &self.handle } +} + +impl FromInner for File { + fn from_inner(handle: libc::HANDLE) -> File { + File { handle: Handle::new(handle) } + } } pub fn to_utf16(s: &Path) -> Vec { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 734268c70ac..b07b3d8651e 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -19,7 +19,7 @@ use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; use sys::c; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub type wrlen_t = i32; @@ -123,10 +123,14 @@ impl Socket { impl Drop for Socket { fn drop(&mut self) { - unsafe { cvt(libc::closesocket(self.0)).unwrap(); } + let _ = unsafe { libc::closesocket(self.0) }; } } impl AsInner for Socket { fn as_inner(&self) -> &libc::SOCKET { &self.0 } } + +impl FromInner for Socket { + fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) } +} diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 167db1e8ac2..5cd90b0902b 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -31,7 +31,7 @@ use ptr; use slice; use sys::c; use sys::fs::FileDesc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use libc::funcs::extra::kernel32::{ GetEnvironmentStringsW, @@ -369,7 +369,7 @@ pub fn home_dir() -> Option { if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { return None } - let _handle = RawHandle::new(token); + let _handle = Handle::new(token); super::fill_utf16_buf_new(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if libc::GetLastError() != 0 => 0,