Skip to content

libs: add platform-specific APIs to extract file descriptors, SOCKETs, HANDLEs, etc from std::io #19169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 26, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libstd/io/fs.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
20 changes: 20 additions & 0 deletions src/libstd/io/net/pipe.rs
Original file line number Diff line number Diff line change
@@ -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 {
20 changes: 20 additions & 0 deletions src/libstd/io/net/tcp.rs
Original file line number Diff line number Diff line change
@@ -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.
///
@@ -256,6 +258,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.
///
@@ -325,6 +333,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.
@@ -452,6 +466,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 {
7 changes: 7 additions & 0 deletions src/libstd/io/net/udp.rs
Original file line number Diff line number Diff line change
@@ -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.
///
4 changes: 2 additions & 2 deletions src/libstd/io/pipe.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
5 changes: 5 additions & 0 deletions src/libstd/os.rs
Original file line number Diff line number Diff line change
@@ -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 {
9 changes: 4 additions & 5 deletions src/libstd/sys/common/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -83,10 +83,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> {
107 changes: 107 additions & 0 deletions src/libstd/sys/unix/ext.rs
Original file line number Diff line number Diff line change
@@ -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};
}
1 change: 1 addition & 0 deletions src/libstd/sys/unix/mod.rs
Original file line number Diff line number Diff line change
@@ -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 os;
pub mod tcp;
6 changes: 3 additions & 3 deletions src/libstd/sys/unix/pipe.rs
Original file line number Diff line number Diff line change
@@ -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)};
6 changes: 3 additions & 3 deletions src/libstd/sys/unix/process.rs
Original file line number Diff line number Diff line change
@@ -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
100 changes: 100 additions & 0 deletions src/libstd/sys/windows/ext.rs
Original file line number Diff line number Diff line change
@@ -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};
}
1 change: 1 addition & 0 deletions src/libstd/sys/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -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 os;
pub mod tcp;
10 changes: 9 additions & 1 deletion src/libstd/sys/windows/pipe.rs
Original file line number Diff line number Diff line change
@@ -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 {
6 changes: 3 additions & 3 deletions src/libstd/sys/windows/process.rs
Original file line number Diff line number Diff line change
@@ -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())
}