Skip to content

Commit 61af402

Browse files
committed
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
2 parents 8d7b319 + 1e66164 commit 61af402

File tree

15 files changed

+287
-19
lines changed

15 files changed

+287
-19
lines changed

src/libstd/io/fs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ pub struct File {
8888
last_nread: int,
8989
}
9090

91-
impl sys_common::AsFileDesc for File {
92-
fn as_fd(&self) -> &fs_imp::FileDesc {
91+
impl sys_common::AsInner<fs_imp::FileDesc> for File {
92+
fn as_inner(&self) -> &fs_imp::FileDesc {
9393
&self.fd
9494
}
9595
}

src/libstd/io/net/pipe.rs

+20
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ use sys::pipe::UnixStream as UnixStreamImp;
3333
use sys::pipe::UnixListener as UnixListenerImp;
3434
use sys::pipe::UnixAcceptor as UnixAcceptorImp;
3535

36+
use sys_common;
37+
3638
/// A stream which communicates over a named pipe.
3739
pub struct UnixStream {
3840
inner: UnixStreamImp,
@@ -145,6 +147,12 @@ impl Writer for UnixStream {
145147
}
146148
}
147149

150+
impl sys_common::AsInner<UnixStreamImp> for UnixStream {
151+
fn as_inner(&self) -> &UnixStreamImp {
152+
&self.inner
153+
}
154+
}
155+
148156
/// A value that can listen for incoming named pipe connection requests.
149157
pub struct UnixListener {
150158
/// The internal, opaque runtime Unix listener.
@@ -186,6 +194,12 @@ impl Listener<UnixStream, UnixAcceptor> for UnixListener {
186194
}
187195
}
188196

197+
impl sys_common::AsInner<UnixListenerImp> for UnixListener {
198+
fn as_inner(&self) -> &UnixListenerImp {
199+
&self.inner
200+
}
201+
}
202+
189203
/// A value that can accept named pipe connections, returned from `listen()`.
190204
pub struct UnixAcceptor {
191205
/// The internal, opaque runtime Unix acceptor.
@@ -247,6 +261,12 @@ impl Clone for UnixAcceptor {
247261
}
248262
}
249263

264+
impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor {
265+
fn as_inner(&self) -> &UnixAcceptorImp {
266+
&self.inner
267+
}
268+
}
269+
250270
#[cfg(test)]
251271
#[allow(experimental)]
252272
mod tests {

src/libstd/io/net/tcp.rs

+20
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ use sys::tcp::TcpStream as TcpStreamImp;
3131
use sys::tcp::TcpListener as TcpListenerImp;
3232
use sys::tcp::TcpAcceptor as TcpAcceptorImp;
3333

34+
use sys_common;
35+
3436
/// A structure which represents a TCP stream between a local socket and a
3537
/// remote socket.
3638
///
@@ -260,6 +262,12 @@ impl Writer for TcpStream {
260262
}
261263
}
262264

265+
impl sys_common::AsInner<TcpStreamImp> for TcpStream {
266+
fn as_inner(&self) -> &TcpStreamImp {
267+
&self.inner
268+
}
269+
}
270+
263271
/// A structure representing a socket server. This listener is used to create a
264272
/// `TcpAcceptor` which can be used to accept sockets on a local port.
265273
///
@@ -329,6 +337,12 @@ impl Listener<TcpStream, TcpAcceptor> for TcpListener {
329337
}
330338
}
331339

340+
impl sys_common::AsInner<TcpListenerImp> for TcpListener {
341+
fn as_inner(&self) -> &TcpListenerImp {
342+
&self.inner
343+
}
344+
}
345+
332346
/// The accepting half of a TCP socket server. This structure is created through
333347
/// a `TcpListener`'s `listen` method, and this object can be used to accept new
334348
/// `TcpStream` instances.
@@ -456,6 +470,12 @@ impl Clone for TcpAcceptor {
456470
}
457471
}
458472

473+
impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor {
474+
fn as_inner(&self) -> &TcpAcceptorImp {
475+
&self.inner
476+
}
477+
}
478+
459479
#[cfg(test)]
460480
#[allow(experimental)]
461481
mod test {

src/libstd/io/net/udp.rs

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use io::{Reader, Writer, IoResult};
2121
use option::Option;
2222
use result::{Ok, Err};
2323
use sys::udp::UdpSocket as UdpSocketImp;
24+
use sys_common;
2425

2526
/// A User Datagram Protocol socket.
2627
///
@@ -184,6 +185,12 @@ impl Clone for UdpSocket {
184185
}
185186
}
186187

188+
impl sys_common::AsInner<UdpSocketImp> for UdpSocket {
189+
fn as_inner(&self) -> &UdpSocketImp {
190+
&self.inner
191+
}
192+
}
193+
187194
/// A type that allows convenient usage of a UDP stream connected to one
188195
/// address via the `Reader` and `Writer` traits.
189196
///

src/libstd/io/pipe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ impl PipeStream {
8686
}
8787
}
8888

89-
impl sys_common::AsFileDesc for PipeStream {
90-
fn as_fd(&self) -> &sys::fs::FileDesc {
89+
impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
90+
fn as_inner(&self) -> &sys::fs::FileDesc {
9191
&*self.inner
9292
}
9393
}

src/libstd/os.rs

+5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ use vec::Vec;
6262
#[cfg(unix)] use c_str::ToCStr;
6363
#[cfg(unix)] use libc::c_char;
6464

65+
#[cfg(unix)]
66+
pub use sys::ext as unix;
67+
#[cfg(windows)]
68+
pub use sys::ext as windows;
69+
6570
/// Get the number of cores available
6671
pub fn num_cpus() -> uint {
6772
unsafe {

src/libstd/sys/common/mod.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use io::{mod, IoError, IoResult};
1515
use prelude::*;
16-
use sys::{last_error, retry, fs};
16+
use sys::{last_error, retry};
1717
use c_str::CString;
1818
use num::Int;
1919
use path::BytesContainer;
@@ -84,10 +84,9 @@ pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
8484
return (origamt - amt) as i64;
8585
}
8686

87-
// traits for extracting representations from
88-
89-
pub trait AsFileDesc {
90-
fn as_fd(&self) -> &fs::FileDesc;
87+
// A trait for extracting representations from std::io types
88+
pub trait AsInner<Inner> {
89+
fn as_inner(&self) -> &Inner;
9190
}
9291

9392
pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {

src/libstd/sys/unix/ext.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Experimental extensions to `std` for Unix platforms.
12+
//!
13+
//! For now, this module is limited to extracting file descriptors,
14+
//! but its functionality will grow over time.
15+
//!
16+
//! # Example
17+
//!
18+
//! ```rust,ignore
19+
//! #![feature(globs)]
20+
//!
21+
//! use std::io::fs::File;
22+
//! use std::os::unix::prelude::*;
23+
//!
24+
//! fn main() {
25+
//! let f = File::create(&Path::new("foo.txt")).unwrap();
26+
//! let fd = f.as_raw_fd();
27+
//!
28+
//! // use fd with native unix bindings
29+
//! }
30+
//! ```
31+
32+
#![experimental]
33+
34+
use sys_common::AsInner;
35+
use libc;
36+
37+
use io;
38+
39+
/// Raw file descriptors.
40+
pub type Fd = libc::c_int;
41+
42+
/// Extract raw file descriptor
43+
pub trait AsRawFd {
44+
/// Extract the raw file descriptor, without taking any ownership.
45+
fn as_raw_fd(&self) -> Fd;
46+
}
47+
48+
impl AsRawFd for io::fs::File {
49+
fn as_raw_fd(&self) -> Fd {
50+
self.as_inner().fd()
51+
}
52+
}
53+
54+
impl AsRawFd for io::pipe::PipeStream {
55+
fn as_raw_fd(&self) -> Fd {
56+
self.as_inner().fd()
57+
}
58+
}
59+
60+
impl AsRawFd for io::net::pipe::UnixStream {
61+
fn as_raw_fd(&self) -> Fd {
62+
self.as_inner().fd()
63+
}
64+
}
65+
66+
impl AsRawFd for io::net::pipe::UnixListener {
67+
fn as_raw_fd(&self) -> Fd {
68+
self.as_inner().fd()
69+
}
70+
}
71+
72+
impl AsRawFd for io::net::pipe::UnixAcceptor {
73+
fn as_raw_fd(&self) -> Fd {
74+
self.as_inner().fd()
75+
}
76+
}
77+
78+
impl AsRawFd for io::net::tcp::TcpStream {
79+
fn as_raw_fd(&self) -> Fd {
80+
self.as_inner().fd()
81+
}
82+
}
83+
84+
impl AsRawFd for io::net::tcp::TcpListener {
85+
fn as_raw_fd(&self) -> Fd {
86+
self.as_inner().fd()
87+
}
88+
}
89+
90+
impl AsRawFd for io::net::tcp::TcpAcceptor {
91+
fn as_raw_fd(&self) -> Fd {
92+
self.as_inner().fd()
93+
}
94+
}
95+
96+
impl AsRawFd for io::net::udp::UdpSocket {
97+
fn as_raw_fd(&self) -> Fd {
98+
self.as_inner().fd()
99+
}
100+
}
101+
102+
/// A prelude for conveniently writing platform-specific code.
103+
///
104+
/// Includes all extension traits, and some important type definitions.
105+
pub mod prelude {
106+
pub use super::{Fd, AsRawFd};
107+
}

src/libstd/sys/unix/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
3333
) )
3434

3535
pub mod c;
36+
pub mod ext;
3637
pub mod fs;
3738
pub mod helper_signal;
3839
pub mod os;

src/libstd/sys/unix/pipe.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl UnixStream {
133133
}
134134
}
135135

136-
fn fd(&self) -> fd_t { self.inner.fd }
136+
pub fn fd(&self) -> fd_t { self.inner.fd }
137137

138138
#[cfg(target_os = "linux")]
139139
fn lock_nonblocking(&self) {}
@@ -222,7 +222,7 @@ impl UnixListener {
222222
})
223223
}
224224

225-
fn fd(&self) -> fd_t { self.inner.fd }
225+
pub fn fd(&self) -> fd_t { self.inner.fd }
226226

227227
pub fn listen(self) -> IoResult<UnixAcceptor> {
228228
match unsafe { libc::listen(self.fd(), 128) } {
@@ -260,7 +260,7 @@ struct AcceptorInner {
260260
}
261261

262262
impl UnixAcceptor {
263-
fn fd(&self) -> fd_t { self.inner.listener.fd() }
263+
pub fn fd(&self) -> fd_t { self.inner.listener.fd() }
264264

265265
pub fn accept(&mut self) -> IoResult<UnixStream> {
266266
let deadline = if self.deadline == 0 {None} else {Some(self.deadline)};

src/libstd/sys/unix/process.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use hash::Hash;
2424
use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval};
2525
use sys::fs::FileDesc;
2626
use sys_common::helper_thread::Helper;
27-
use sys_common::{AsFileDesc, mkerr_libc, timeout};
27+
use sys_common::{AsInner, mkerr_libc, timeout};
2828

2929
pub use sys_common::ProcessConfig;
3030

@@ -56,7 +56,7 @@ impl Process {
5656
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
5757
out_fd: Option<P>, err_fd: Option<P>)
5858
-> IoResult<Process>
59-
where C: ProcessConfig<K, V>, P: AsFileDesc,
59+
where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
6060
K: BytesContainer + Eq + Hash, V: BytesContainer
6161
{
6262
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
@@ -183,7 +183,7 @@ impl Process {
183183
libc::open(devnull.as_ptr(), flags, 0)
184184
}
185185
Some(obj) => {
186-
let fd = obj.as_fd().fd();
186+
let fd = obj.as_inner().fd();
187187
// Leak the memory and the file descriptor. We're in the
188188
// child now an all our resources are going to be
189189
// cleaned up very soon

0 commit comments

Comments
 (0)