about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-11-26 08:42:09 +0000
committerbors <bors@rust-lang.org>2014-11-26 08:42:09 +0000
commit61af40278909eb899f1bdfbb8c45d4e4fb3dad5d (patch)
tree87d901e82bb5e19ed4e49216f2114c9ca060aee6 /src/libstd
parent8d7b3199d9a285b66b4f9a49d97234c956cb5e6c (diff)
parent1e661642105a1033f1c155ceb1b2335dd11cb40a (diff)
downloadrust-61af40278909eb899f1bdfbb8c45d4e4fb3dad5d.tar.gz
rust-61af40278909eb899f1bdfbb8c45d4e4fb3dad5d.zip
auto merge of #19169 : aturon/rust/fds, r=alexcrichton
This PR adds some internal infrastructure to allow the private `std::sys` module to access internal representation details of `std::io`.

It then exposes those details in two new, platform-specific API surfaces: `std::os::unix` and `std::os::windows`.

To start with, these will provide the ability to extract file descriptors, HANDLEs, SOCKETs, and so on from `std::io` types.

More functionality, and more specific platforms (e.g. `std::os::linux`) will be added over time.

Closes #18897
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/fs.rs4
-rw-r--r--src/libstd/io/net/pipe.rs20
-rw-r--r--src/libstd/io/net/tcp.rs20
-rw-r--r--src/libstd/io/net/udp.rs7
-rw-r--r--src/libstd/io/pipe.rs4
-rw-r--r--src/libstd/os.rs5
-rw-r--r--src/libstd/sys/common/mod.rs9
-rw-r--r--src/libstd/sys/unix/ext.rs107
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/pipe.rs6
-rw-r--r--src/libstd/sys/unix/process.rs6
-rw-r--r--src/libstd/sys/windows/ext.rs100
-rw-r--r--src/libstd/sys/windows/mod.rs1
-rw-r--r--src/libstd/sys/windows/pipe.rs10
-rw-r--r--src/libstd/sys/windows/process.rs6
15 files changed, 287 insertions, 19 deletions
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index cd4141e045c..6d29f3d2538 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -88,8 +88,8 @@ pub struct File {
     last_nread: int,
 }
 
-impl sys_common::AsFileDesc for File {
-    fn as_fd(&self) -> &fs_imp::FileDesc {
+impl sys_common::AsInner<fs_imp::FileDesc> for File {
+    fn as_inner(&self) -> &fs_imp::FileDesc {
         &self.fd
     }
 }
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 8e934d221d2..2984fa59631 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -33,6 +33,8 @@ use sys::pipe::UnixStream as UnixStreamImp;
 use sys::pipe::UnixListener as UnixListenerImp;
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 
+use sys_common;
+
 /// A stream which communicates over a named pipe.
 pub struct UnixStream {
     inner: UnixStreamImp,
@@ -145,6 +147,12 @@ impl Writer for UnixStream {
     }
 }
 
+impl sys_common::AsInner<UnixStreamImp> for UnixStream {
+    fn as_inner(&self) -> &UnixStreamImp {
+        &self.inner
+    }
+}
+
 /// A value that can listen for incoming named pipe connection requests.
 pub struct UnixListener {
     /// The internal, opaque runtime Unix listener.
@@ -186,6 +194,12 @@ impl Listener<UnixStream, UnixAcceptor> for UnixListener {
     }
 }
 
+impl sys_common::AsInner<UnixListenerImp> for UnixListener {
+    fn as_inner(&self) -> &UnixListenerImp {
+        &self.inner
+    }
+}
+
 /// A value that can accept named pipe connections, returned from `listen()`.
 pub struct UnixAcceptor {
     /// The internal, opaque runtime Unix acceptor.
@@ -247,6 +261,12 @@ impl Clone for UnixAcceptor {
     }
 }
 
+impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor {
+    fn as_inner(&self) -> &UnixAcceptorImp {
+        &self.inner
+    }
+}
+
 #[cfg(test)]
 #[allow(experimental)]
 mod tests {
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index cbac6b48b83..a989be758c3 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -31,6 +31,8 @@ use sys::tcp::TcpStream as TcpStreamImp;
 use sys::tcp::TcpListener as TcpListenerImp;
 use sys::tcp::TcpAcceptor as TcpAcceptorImp;
 
+use sys_common;
+
 /// A structure which represents a TCP stream between a local socket and a
 /// remote socket.
 ///
@@ -260,6 +262,12 @@ impl Writer for TcpStream {
     }
 }
 
+impl sys_common::AsInner<TcpStreamImp> for TcpStream {
+    fn as_inner(&self) -> &TcpStreamImp {
+        &self.inner
+    }
+}
+
 /// A structure representing a socket server. This listener is used to create a
 /// `TcpAcceptor` which can be used to accept sockets on a local port.
 ///
@@ -329,6 +337,12 @@ impl Listener<TcpStream, TcpAcceptor> for TcpListener {
     }
 }
 
+impl sys_common::AsInner<TcpListenerImp> for TcpListener {
+    fn as_inner(&self) -> &TcpListenerImp {
+        &self.inner
+    }
+}
+
 /// The accepting half of a TCP socket server. This structure is created through
 /// a `TcpListener`'s `listen` method, and this object can be used to accept new
 /// `TcpStream` instances.
@@ -456,6 +470,12 @@ impl Clone for TcpAcceptor {
     }
 }
 
+impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor {
+    fn as_inner(&self) -> &TcpAcceptorImp {
+        &self.inner
+    }
+}
+
 #[cfg(test)]
 #[allow(experimental)]
 mod test {
diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs
index 567e7da0c00..a7239ca0f2f 100644
--- a/src/libstd/io/net/udp.rs
+++ b/src/libstd/io/net/udp.rs
@@ -21,6 +21,7 @@ use io::{Reader, Writer, IoResult};
 use option::Option;
 use result::{Ok, Err};
 use sys::udp::UdpSocket as UdpSocketImp;
+use sys_common;
 
 /// A User Datagram Protocol socket.
 ///
@@ -184,6 +185,12 @@ impl Clone for UdpSocket {
     }
 }
 
+impl sys_common::AsInner<UdpSocketImp> for UdpSocket {
+    fn as_inner(&self) -> &UdpSocketImp {
+        &self.inner
+    }
+}
+
 /// A type that allows convenient usage of a UDP stream connected to one
 /// address via the `Reader` and `Writer` traits.
 ///
diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs
index 8c20ea08863..41676cdf6e9 100644
--- a/src/libstd/io/pipe.rs
+++ b/src/libstd/io/pipe.rs
@@ -86,8 +86,8 @@ impl PipeStream {
     }
 }
 
-impl sys_common::AsFileDesc for PipeStream {
-    fn as_fd(&self) -> &sys::fs::FileDesc {
+impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
+    fn as_inner(&self) -> &sys::fs::FileDesc {
         &*self.inner
     }
 }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 9b50361ec1f..33c9f38da9b 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -62,6 +62,11 @@ use vec::Vec;
 #[cfg(unix)] use c_str::ToCStr;
 #[cfg(unix)] use libc::c_char;
 
+#[cfg(unix)]
+pub use sys::ext as unix;
+#[cfg(windows)]
+pub use sys::ext as windows;
+
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
     unsafe {
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index 77edd7c5c4e..e382ec261a0 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -13,7 +13,7 @@
 
 use io::{mod, IoError, IoResult};
 use prelude::*;
-use sys::{last_error, retry, fs};
+use sys::{last_error, retry};
 use c_str::CString;
 use num::Int;
 use path::BytesContainer;
@@ -84,10 +84,9 @@ pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
     return (origamt - amt) as i64;
 }
 
-// traits for extracting representations from
-
-pub trait AsFileDesc {
-    fn as_fd(&self) -> &fs::FileDesc;
+// A trait for extracting representations from std::io types
+pub trait AsInner<Inner> {
+    fn as_inner(&self) -> &Inner;
 }
 
 pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
new file mode 100644
index 00000000000..ae3c939bf78
--- /dev/null
+++ b/src/libstd/sys/unix/ext.rs
@@ -0,0 +1,107 @@
+// 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.
+
+//! Experimental extensions to `std` for Unix platforms.
+//!
+//! For now, this module is limited to extracting file descriptors,
+//! but its functionality will grow over time.
+//!
+//! # Example
+//!
+//! ```rust,ignore
+//! #![feature(globs)]
+//!
+//! use std::io::fs::File;
+//! use std::os::unix::prelude::*;
+//!
+//! fn main() {
+//!     let f = File::create(&Path::new("foo.txt")).unwrap();
+//!     let fd = f.as_raw_fd();
+//!
+//!     // use fd with native unix bindings
+//! }
+//! ```
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw file descriptors.
+pub type Fd = libc::c_int;
+
+/// Extract raw file descriptor
+pub trait AsRawFd {
+    /// Extract the raw file descriptor, without taking any ownership.
+    fn as_raw_fd(&self) -> Fd;
+}
+
+impl AsRawFd for io::fs::File {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::pipe::PipeStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::udp::UdpSocket {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Fd, AsRawFd};
+}
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 7a5317b578d..af238905119 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -33,6 +33,7 @@ macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
 ) )
 
 pub mod c;
+pub mod ext;
 pub mod fs;
 pub mod helper_signal;
 pub mod os;
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 4d3469a9c24..3f70fb5c1a5 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -133,7 +133,7 @@ impl UnixStream {
         }
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     #[cfg(target_os = "linux")]
     fn lock_nonblocking(&self) {}
@@ -222,7 +222,7 @@ impl UnixListener {
         })
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     pub fn listen(self) -> IoResult<UnixAcceptor> {
         match unsafe { libc::listen(self.fd(), 128) } {
@@ -260,7 +260,7 @@ struct AcceptorInner {
 }
 
 impl UnixAcceptor {
-    fn fd(&self) -> fd_t { self.inner.listener.fd() }
+    pub fn fd(&self) -> fd_t { self.inner.listener.fd() }
 
     pub fn accept(&mut self) -> IoResult<UnixStream> {
         let deadline = if self.deadline == 0 {None} else {Some(self.deadline)};
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 81bc138ca91..76c316076f9 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -24,7 +24,7 @@ use hash::Hash;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 pub use sys_common::ProcessConfig;
 
@@ -56,7 +56,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
@@ -183,7 +183,7 @@ impl Process {
                             libc::open(devnull.as_ptr(), flags, 0)
                         }
                         Some(obj) => {
-                            let fd = obj.as_fd().fd();
+                            let fd = obj.as_inner().fd();
                             // Leak the memory and the file descriptor. We're in the
                             // child now an all our resources are going to be
                             // cleaned up very soon
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs
new file mode 100644
index 00000000000..2c58ee69e8b
--- /dev/null
+++ b/src/libstd/sys/windows/ext.rs
@@ -0,0 +1,100 @@
+// 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.
+
+//! Experimental extensions to `std` for Windows.
+//!
+//! For now, this module is limited to extracting handles, file
+//! descriptors, and sockets, but its functionality will grow over
+//! time.
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw HANDLEs.
+pub type Handle = libc::HANDLE;
+
+/// Raw SOCKETs.
+pub type Socket = libc::SOCKET;
+
+/// Extract raw handles.
+pub trait AsRawHandle {
+    /// Extract the raw handle, without taking any ownership.
+    fn as_raw_handle(&self) -> Handle;
+}
+
+impl AsRawHandle for io::fs::File {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::pipe::PipeStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixListener {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixAcceptor {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+/// Extract raw sockets.
+pub trait AsRawSocket {
+    fn as_raw_socket(&self) -> Socket;
+}
+
+impl AsRawSocket for io::net::tcp::TcpStream {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpListener {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpAcceptor {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawSocket for io::net::udp::UdpSocket {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Socket, Handle, AsRawSocket, AsRawHandle};
+}
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index a785ccfe804..6b9555c52ce 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -34,6 +34,7 @@ macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
 ) )
 
 pub mod c;
+pub mod ext;
 pub mod fs;
 pub mod helper_signal;
 pub mod os;
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index a623c2cd8e2..ca7985aa35b 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -329,7 +329,7 @@ impl UnixStream {
         }
     }
 
-    fn handle(&self) -> libc::HANDLE { self.inner.handle }
+    pub fn handle(&self) -> libc::HANDLE { self.inner.handle }
 
     fn read_closed(&self) -> bool {
         self.inner.read_closed.load(atomic::SeqCst)
@@ -585,6 +585,10 @@ impl UnixListener {
             }),
         })
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.handle
+    }
 }
 
 impl Drop for UnixListener {
@@ -729,6 +733,10 @@ impl UnixAcceptor {
             Ok(())
         }
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.listener.handle()
+    }
 }
 
 impl Clone for UnixAcceptor {
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 3fb5ee34356..eddb89c673d 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -26,7 +26,7 @@ use sys::fs;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 use io::fs::PathExtensions;
 use string::String;
@@ -105,7 +105,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
@@ -195,7 +195,7 @@ impl Process {
                         }
                     }
                     Some(ref fd) => {
-                        let orig = get_osfhandle(fd.as_fd().fd()) as HANDLE;
+                        let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE;
                         if orig == INVALID_HANDLE_VALUE {
                             return Err(super::last_error())
                         }