diff options
| author | Aaron Turon <aturon@mozilla.com> | 2014-09-30 17:03:56 -0700 |
|---|---|---|
| committer | Aaron Turon <aturon@mozilla.com> | 2014-11-08 20:40:38 -0800 |
| commit | 3a527f2b3311d5b1c6dd7c72db71c45596e6db49 (patch) | |
| tree | 1a550dd4b679b0ccf13acef6cc7879e486a3d3de /src/libnative | |
| parent | 93c85eb8bdcc910a27caf6abd20207a626ae98e5 (diff) | |
| download | rust-3a527f2b3311d5b1c6dd7c72db71c45596e6db49.tar.gz rust-3a527f2b3311d5b1c6dd7c72db71c45596e6db49.zip | |
Runtime removal: add private sys, sys_common modules
These modules will house the code that used to be part of the runtime system in libnative. The `sys_common` module contains a few low-level but cross-platform details. The `sys` module is set up using `#[cfg()]` to include either a unix or windows implementation of a common API surface. This API surface is *not* exported directly in `libstd`, but is instead used to bulid `std::os` and `std::io`. Ultimately, the low-level details in `sys` will be exposed in a controlled way through a separate platform-specific surface, but that setup is not part of this patch.
Diffstat (limited to 'src/libnative')
| -rw-r--r-- | src/libnative/io/c_unix.rs | 261 | ||||
| -rw-r--r-- | src/libnative/io/c_windows.rs | 246 | ||||
| -rw-r--r-- | src/libnative/io/mod.rs | 3 | ||||
| -rw-r--r-- | src/libnative/io/util.rs | 209 |
4 files changed, 0 insertions, 719 deletions
diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs deleted file mode 100644 index f1757d367c3..00000000000 --- a/src/libnative/io/c_unix.rs +++ /dev/null @@ -1,261 +0,0 @@ -// 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. - -//! C definitions used by libnative that don't belong in liblibc - -#![allow(dead_code)] - -pub use self::select::fd_set; -pub use self::signal::{sigaction, siginfo, sigset_t}; -pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP}; -pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD}; - -use libc; - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] -pub const FIONBIO: libc::c_ulong = 0x8004667e; -#[cfg(any(all(target_os = "linux", - any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm")), - target_os = "android"))] -pub const FIONBIO: libc::c_ulong = 0x5421; -#[cfg(all(target_os = "linux", - any(target_arch = "mips", target_arch = "mipsel")))] -pub const FIONBIO: libc::c_ulong = 0x667e; - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] -pub const FIOCLEX: libc::c_ulong = 0x20006601; -#[cfg(any(all(target_os = "linux", - any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm")), - target_os = "android"))] -pub const FIOCLEX: libc::c_ulong = 0x5451; -#[cfg(all(target_os = "linux", - any(target_arch = "mips", target_arch = "mipsel")))] -pub const FIOCLEX: libc::c_ulong = 0x6601; - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] -pub const MSG_DONTWAIT: libc::c_int = 0x80; -#[cfg(any(target_os = "linux", target_os = "android"))] -pub const MSG_DONTWAIT: libc::c_int = 0x40; - -pub const WNOHANG: libc::c_int = 1; - -extern { - pub fn gettimeofday(timeval: *mut libc::timeval, - tzp: *mut libc::c_void) -> libc::c_int; - pub fn select(nfds: libc::c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - errorfds: *mut fd_set, - timeout: *mut libc::timeval) -> libc::c_int; - pub fn getsockopt(sockfd: libc::c_int, - level: libc::c_int, - optname: libc::c_int, - optval: *mut libc::c_void, - optlen: *mut libc::socklen_t) -> libc::c_int; - pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int; - - - pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int, - options: libc::c_int) -> libc::pid_t; - - pub fn sigaction(signum: libc::c_int, - act: *const sigaction, - oldact: *mut sigaction) -> libc::c_int; - - pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int; - pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int; - pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int; -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -mod select { - pub const FD_SETSIZE: uint = 1024; - - #[repr(C)] - pub struct fd_set { - fds_bits: [i32, ..(FD_SETSIZE / 32)] - } - - pub fn fd_set(set: &mut fd_set, fd: i32) { - set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint); - } -} - -#[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux"))] -mod select { - use std::uint; - use libc; - - pub const FD_SETSIZE: uint = 1024; - - #[repr(C)] - pub struct fd_set { - // FIXME: shouldn't this be a c_ulong? - fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)] - } - - pub fn fd_set(set: &mut fd_set, fd: i32) { - let fd = fd as uint; - set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS); - } -} - -#[cfg(any(all(target_os = "linux", - any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm")), - target_os = "android"))] -mod signal { - use libc; - - pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001; - pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002; - pub const SA_NODEFER: libc::c_ulong = 0x40000000; - pub const SA_ONSTACK: libc::c_ulong = 0x08000000; - pub const SA_RESETHAND: libc::c_ulong = 0x80000000; - pub const SA_RESTART: libc::c_ulong = 0x10000000; - pub const SA_SIGINFO: libc::c_ulong = 0x00000004; - pub const SIGCHLD: libc::c_int = 17; - - // This definition is not as accurate as it could be, {pid, uid, status} is - // actually a giant union. Currently we're only interested in these fields, - // however. - #[repr(C)] - pub struct siginfo { - si_signo: libc::c_int, - si_errno: libc::c_int, - si_code: libc::c_int, - pub pid: libc::pid_t, - pub uid: libc::uid_t, - pub status: libc::c_int, - } - - #[repr(C)] - pub struct sigaction { - pub sa_handler: extern fn(libc::c_int), - pub sa_mask: sigset_t, - pub sa_flags: libc::c_ulong, - sa_restorer: *mut libc::c_void, - } - - #[repr(C)] - #[cfg(target_word_size = "32")] - pub struct sigset_t { - __val: [libc::c_ulong, ..32], - } - - #[repr(C)] - #[cfg(target_word_size = "64")] - pub struct sigset_t { - __val: [libc::c_ulong, ..16], - } -} - -#[cfg(all(target_os = "linux", - any(target_arch = "mips", target_arch = "mipsel")))] -mod signal { - use libc; - - pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001; - pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000; - pub const SA_NODEFER: libc::c_ulong = 0x40000000; - pub const SA_ONSTACK: libc::c_ulong = 0x08000000; - pub const SA_RESETHAND: libc::c_ulong = 0x80000000; - pub const SA_RESTART: libc::c_ulong = 0x10000000; - pub const SA_SIGINFO: libc::c_ulong = 0x00000008; - pub const SIGCHLD: libc::c_int = 18; - - // This definition is not as accurate as it could be, {pid, uid, status} is - // actually a giant union. Currently we're only interested in these fields, - // however. - #[repr(C)] - pub struct siginfo { - si_signo: libc::c_int, - si_code: libc::c_int, - si_errno: libc::c_int, - pub pid: libc::pid_t, - pub uid: libc::uid_t, - pub status: libc::c_int, - } - - #[repr(C)] - pub struct sigaction { - pub sa_flags: libc::c_uint, - pub sa_handler: extern fn(libc::c_int), - pub sa_mask: sigset_t, - sa_restorer: *mut libc::c_void, - sa_resv: [libc::c_int, ..1], - } - - #[repr(C)] - pub struct sigset_t { - __val: [libc::c_ulong, ..32], - } -} - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] -mod signal { - use libc; - - pub const SA_ONSTACK: libc::c_int = 0x0001; - pub const SA_RESTART: libc::c_int = 0x0002; - pub const SA_RESETHAND: libc::c_int = 0x0004; - pub const SA_NOCLDSTOP: libc::c_int = 0x0008; - pub const SA_NODEFER: libc::c_int = 0x0010; - pub const SA_NOCLDWAIT: libc::c_int = 0x0020; - pub const SA_SIGINFO: libc::c_int = 0x0040; - pub const SIGCHLD: libc::c_int = 20; - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub type sigset_t = u32; - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - #[repr(C)] - pub struct sigset_t { - bits: [u32, ..4], - } - - // This structure has more fields, but we're not all that interested in - // them. - #[repr(C)] - pub struct siginfo { - pub si_signo: libc::c_int, - pub si_errno: libc::c_int, - pub si_code: libc::c_int, - pub pid: libc::pid_t, - pub uid: libc::uid_t, - pub status: libc::c_int, - } - - #[repr(C)] - pub struct sigaction { - pub sa_handler: extern fn(libc::c_int), - pub sa_flags: libc::c_int, - pub sa_mask: sigset_t, - } -} diff --git a/src/libnative/io/c_windows.rs b/src/libnative/io/c_windows.rs deleted file mode 100644 index ee6aa26ede2..00000000000 --- a/src/libnative/io/c_windows.rs +++ /dev/null @@ -1,246 +0,0 @@ -// 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. - -//! C definitions used by libnative that don't belong in liblibc - -#![allow(overflowing_literals)] - -use libc; - -pub const WSADESCRIPTION_LEN: uint = 256; -pub const WSASYS_STATUS_LEN: uint = 128; -pub const FIONBIO: libc::c_long = 0x8004667e; -pub const FD_SETSIZE: uint = 64; -pub const MSG_DONTWAIT: libc::c_int = 0; -pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582; -pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4; -pub const ENABLE_EXTENDED_FLAGS: libc::DWORD = 0x80; -pub const ENABLE_INSERT_MODE: libc::DWORD = 0x20; -pub const ENABLE_LINE_INPUT: libc::DWORD = 0x2; -pub const ENABLE_PROCESSED_INPUT: libc::DWORD = 0x1; -pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40; -pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT; - -pub const FD_ACCEPT: libc::c_long = 0x08; -pub const FD_MAX_EVENTS: uint = 10; -pub const WSA_INFINITE: libc::DWORD = libc::INFINITE; -pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT; -pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0; -pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED; - -#[repr(C)] -#[cfg(target_arch = "x86")] -pub struct WSADATA { - pub wVersion: libc::WORD, - pub wHighVersion: libc::WORD, - pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1], - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: *mut u8, -} -#[repr(C)] -#[cfg(target_arch = "x86_64")] -pub struct WSADATA { - pub wVersion: libc::WORD, - pub wHighVersion: libc::WORD, - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: *mut u8, - pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1], -} - -pub type LPWSADATA = *mut WSADATA; - -#[repr(C)] -pub struct WSANETWORKEVENTS { - pub lNetworkEvents: libc::c_long, - pub iErrorCode: [libc::c_int, ..FD_MAX_EVENTS], -} - -pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS; - -pub type WSAEVENT = libc::HANDLE; - -#[repr(C)] -pub struct fd_set { - fd_count: libc::c_uint, - fd_array: [libc::SOCKET, ..FD_SETSIZE], -} - -pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { - set.fd_array[set.fd_count as uint] = s; - set.fd_count += 1; -} - -#[link(name = "ws2_32")] -extern "system" { - pub fn WSAStartup(wVersionRequested: libc::WORD, - lpWSAData: LPWSADATA) -> libc::c_int; - pub fn WSAGetLastError() -> libc::c_int; - pub fn WSACloseEvent(hEvent: WSAEVENT) -> libc::BOOL; - pub fn WSACreateEvent() -> WSAEVENT; - pub fn WSAEventSelect(s: libc::SOCKET, - hEventObject: WSAEVENT, - lNetworkEvents: libc::c_long) -> libc::c_int; - pub fn WSASetEvent(hEvent: WSAEVENT) -> libc::BOOL; - pub fn WSAWaitForMultipleEvents(cEvents: libc::DWORD, - lphEvents: *const WSAEVENT, - fWaitAll: libc::BOOL, - dwTimeout: libc::DWORD, - fAltertable: libc::BOOL) -> libc::DWORD; - pub fn WSAEnumNetworkEvents(s: libc::SOCKET, - hEventObject: WSAEVENT, - lpNetworkEvents: LPWSANETWORKEVENTS) - -> libc::c_int; - - pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long, - argp: *mut libc::c_ulong) -> libc::c_int; - pub fn select(nfds: libc::c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *mut libc::timeval) -> libc::c_int; - pub fn getsockopt(sockfd: libc::SOCKET, - level: libc::c_int, - optname: libc::c_int, - optval: *mut libc::c_char, - optlen: *mut libc::c_int) -> libc::c_int; - - pub fn SetEvent(hEvent: libc::HANDLE) -> libc::BOOL; - pub fn WaitForMultipleObjects(nCount: libc::DWORD, - lpHandles: *const libc::HANDLE, - bWaitAll: libc::BOOL, - dwMilliseconds: libc::DWORD) -> libc::DWORD; - - pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL; - pub fn CancelIoEx(hFile: libc::HANDLE, - lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL; -} - -pub mod compat { - use std::intrinsics::{atomic_store_relaxed, transmute}; - use std::iter::Iterator; - use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; - - extern "system" { - fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; - fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID; - } - - // store_func() is idempotent, so using relaxed ordering for the atomics - // should be enough. This way, calling a function in this compatibility - // layer (after it's loaded) shouldn't be any slower than a regular DLL - // call. - unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) { - let mut module: Vec<u16> = module.utf16_units().collect(); - module.push(0); - symbol.with_c_str(|symbol| { - let handle = GetModuleHandleW(module.as_ptr()); - let func: uint = transmute(GetProcAddress(handle, symbol)); - atomic_store_relaxed(ptr, if func == 0 { - fallback - } else { - func - }) - }) - } - - /// Macro for creating a compatibility fallback for a Windows function - /// - /// # Example - /// ``` - /// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) { - /// // Fallback implementation - /// }) - /// ``` - /// - /// Note that arguments unused by the fallback implementation should not be called `_` as - /// they are used to be passed to the real function if available. - macro_rules! compat_fn( - ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) - -> $rettype:ty $fallback:block) => ( - #[inline(always)] - pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype { - static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk; - - extern "system" fn thunk($($argname: $argtype),*) -> $rettype { - unsafe { - ::io::c::compat::store_func(&mut ptr as *mut _ as *mut uint, - stringify!($module), - stringify!($symbol), - fallback as uint); - ::std::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) - } - } - - extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback - - ::std::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) - } - ); - - ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => ( - compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback) - ) - ) - - /// Compatibility layer for functions in `kernel32.dll` - /// - /// Latest versions of Windows this is needed for: - /// - /// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003 - /// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003 - pub mod kernel32 { - use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE}; - use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - - extern "system" { - fn SetLastError(dwErrCode: DWORD); - } - - compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, - _lpTargetFileName: LPCWSTR, - _dwFlags: DWORD) -> BOOLEAN { - unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } - 0 - }) - - compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE, - _lpszFilePath: LPCWSTR, - _cchFilePath: DWORD, - _dwFlags: DWORD) -> DWORD { - unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } - 0 - }) - } -} - -extern "system" { - // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL - pub fn ReadConsoleW(hConsoleInput: libc::HANDLE, - lpBuffer: libc::LPVOID, - nNumberOfCharsToRead: libc::DWORD, - lpNumberOfCharsRead: libc::LPDWORD, - pInputControl: libc::LPVOID) -> libc::BOOL; - - pub fn WriteConsoleW(hConsoleOutput: libc::HANDLE, - lpBuffer: libc::types::os::arch::extra::LPCVOID, - nNumberOfCharsToWrite: libc::DWORD, - lpNumberOfCharsWritten: libc::LPDWORD, - lpReserved: libc::LPVOID) -> libc::BOOL; - - pub fn GetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::LPDWORD) -> libc::BOOL; - - pub fn SetConsoleMode(hConsoleHandle: libc::HANDLE, - lpMode: libc::DWORD) -> libc::BOOL; -} diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 954f7bbc59a..90f8f6c214e 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -73,9 +73,6 @@ pub mod pipe; #[path = "tty_windows.rs"] mod tty; -#[cfg(unix)] #[path = "c_unix.rs"] mod c; -#[cfg(windows)] #[path = "c_windows.rs"] mod c; - fn unimpl() -> IoError { #[cfg(unix)] use libc::ENOSYS as ERROR; #[cfg(windows)] use libc::ERROR_CALL_NOT_IMPLEMENTED as ERROR; diff --git a/src/libnative/io/util.rs b/src/libnative/io/util.rs deleted file mode 100644 index 5f69ec00cdd..00000000000 --- a/src/libnative/io/util.rs +++ /dev/null @@ -1,209 +0,0 @@ -// 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. - -use libc; -use std::cmp; -use std::mem; -use std::os; -use std::ptr; -use std::rt::rtio::{IoResult, IoError}; - -use super::c; -use super::net; -use super::{retry, last_error}; - -#[deriving(Show)] -pub enum SocketStatus { - Readable, - Writable, -} - -pub fn timeout(desc: &'static str) -> IoError { - #[cfg(unix)] use libc::ETIMEDOUT as ERROR; - #[cfg(windows)] use libc::ERROR_OPERATION_ABORTED as ERROR; - IoError { - code: ERROR as uint, - extra: 0, - detail: Some(desc.to_string()), - } -} - -pub fn short_write(n: uint, desc: &'static str) -> IoError { - #[cfg(unix)] use libc::EAGAIN as ERROR; - #[cfg(windows)] use libc::ERROR_OPERATION_ABORTED as ERROR; - IoError { - code: ERROR as uint, - extra: n, - detail: Some(desc.to_string()), - } -} - -pub fn eof() -> IoError { - IoError { - code: libc::EOF as uint, - extra: 0, - detail: None, - } -} - -#[cfg(windows)] -pub fn ms_to_timeval(ms: u64) -> libc::timeval { - libc::timeval { - tv_sec: (ms / 1000) as libc::c_long, - tv_usec: ((ms % 1000) * 1000) as libc::c_long, - } -} -#[cfg(not(windows))] -pub fn ms_to_timeval(ms: u64) -> libc::timeval { - libc::timeval { - tv_sec: (ms / 1000) as libc::time_t, - tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t, - } -} - -#[cfg(unix)] -pub fn wouldblock() -> bool { - let err = os::errno(); - err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int -} - -#[cfg(windows)] -pub fn wouldblock() -> bool { - let err = os::errno(); - err == libc::WSAEWOULDBLOCK as uint -} - -#[cfg(unix)] -pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> { - let set = nb as libc::c_int; - super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })) -} - -#[cfg(windows)] -pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> { - let mut set = nb as libc::c_ulong; - if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } { - Err(last_error()) - } else { - Ok(()) - } -} - -// See http://developerweb.net/viewtopic.php?id=3196 for where this is -// derived from. -pub fn connect_timeout(fd: net::sock_t, - addrp: *const libc::sockaddr, - len: libc::socklen_t, - timeout_ms: u64) -> IoResult<()> { - use std::os; - #[cfg(unix)] use libc::EINPROGRESS as INPROGRESS; - #[cfg(windows)] use libc::WSAEINPROGRESS as INPROGRESS; - #[cfg(unix)] use libc::EWOULDBLOCK as WOULDBLOCK; - #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK; - - // Make sure the call to connect() doesn't block - try!(set_nonblocking(fd, true)); - - let ret = match unsafe { libc::connect(fd, addrp, len) } { - // If the connection is in progress, then we need to wait for it to - // finish (with a timeout). The current strategy for doing this is - // to use select() with a timeout. - -1 if os::errno() as int == INPROGRESS as int || - os::errno() as int == WOULDBLOCK as int => { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - c::fd_set(&mut set, fd); - match await(fd, &mut set, timeout_ms) { - 0 => Err(timeout("connection timed out")), - -1 => Err(last_error()), - _ => { - let err: libc::c_int = try!( - net::getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR)); - if err == 0 { - Ok(()) - } else { - Err(IoError { - code: err as uint, - extra: 0, - detail: Some(os::error_string(err as uint)), - }) - } - } - } - } - - -1 => Err(last_error()), - _ => Ok(()), - }; - - // be sure to turn blocking I/O back on - try!(set_nonblocking(fd, false)); - return ret; - - #[cfg(unix)] - fn await(fd: net::sock_t, set: &mut c::fd_set, - timeout: u64) -> libc::c_int { - let start = ::io::timer::now(); - retry(|| unsafe { - // Recalculate the timeout each iteration (it is generally - // undefined what the value of the 'tv' is after select - // returns EINTR). - let mut tv = ms_to_timeval(timeout - (::io::timer::now() - start)); - c::select(fd + 1, ptr::null_mut(), set as *mut _, - ptr::null_mut(), &mut tv) - }) - } - #[cfg(windows)] - fn await(_fd: net::sock_t, set: &mut c::fd_set, - timeout: u64) -> libc::c_int { - let mut tv = ms_to_timeval(timeout); - unsafe { c::select(1, ptr::null_mut(), set, ptr::null_mut(), &mut tv) } - } -} - -pub fn await(fds: &[net::sock_t], deadline: Option<u64>, - status: SocketStatus) -> IoResult<()> { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - let mut max = 0; - for &fd in fds.iter() { - c::fd_set(&mut set, fd); - max = cmp::max(max, fd + 1); - } - if cfg!(windows) { - max = fds.len() as net::sock_t; - } - - let (read, write) = match status { - Readable => (&mut set as *mut _, ptr::null_mut()), - Writable => (ptr::null_mut(), &mut set as *mut _), - }; - let mut tv: libc::timeval = unsafe { mem::zeroed() }; - - match retry(|| { - let now = ::io::timer::now(); - let tvp = match deadline { - None => ptr::null_mut(), - Some(deadline) => { - // If we're past the deadline, then pass a 0 timeout to - // select() so we can poll the status - let ms = if deadline < now {0} else {deadline - now}; - tv = ms_to_timeval(ms); - &mut tv as *mut _ - } - }; - let r = unsafe { - c::select(max as libc::c_int, read, write, ptr::null_mut(), tvp) - }; - r - }) { - -1 => Err(last_error()), - 0 => Err(timeout("timed out")), - _ => Ok(()), - } -} |
