mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-16 13:05:18 +03:00
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
This commit is contained in:
+2
-2
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
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 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn listen(self) -> IoResult<UnixAcceptor> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn clone(&self) -> UnixAcceptor {
|
||||
}
|
||||
}
|
||||
|
||||
impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor {
|
||||
fn as_inner(&self) -> &UnixAcceptorImp {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(experimental)]
|
||||
mod tests {
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
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 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn listen(self) -> IoResult<TcpAcceptor> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn clone(&self) -> TcpAcceptor {
|
||||
}
|
||||
}
|
||||
|
||||
impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor {
|
||||
fn as_inner(&self) -> &TcpAcceptorImp {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(experimental)]
|
||||
mod test {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
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 @@ fn clone(&self) -> 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.
|
||||
///
|
||||
|
||||
@@ -86,8 +86,8 @@ pub fn pair() -> IoResult<PipePair> {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,11 @@
|
||||
#[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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -133,7 +133,7 @@ fn new(inner: Arc<Inner>) -> 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 @@ pub fn bind(addr: &CString) -> IoResult<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)};
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
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 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
|
||||
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 @@ fn fail(output: &mut FileDesc) -> ! {
|
||||
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
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -329,7 +329,7 @@ pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<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 @@ pub fn listen(self) -> IoResult<UnixAcceptor> {
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> libc::HANDLE {
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for UnixListener {
|
||||
@@ -729,6 +733,10 @@ pub fn close_accept(&mut self) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> libc::HANDLE {
|
||||
self.listener.handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for UnixAcceptor {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
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 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
|
||||
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 @@ pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
||||
}
|
||||
}
|
||||
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())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user