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.
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.
11 #![allow(missing_docs)]
12 #![allow(non_camel_case_types)]
13 #![allow(non_snake_case)]
14 #![allow(unused_imports)]
16 #![allow(unused_unsafe)]
25 use io::{mod, IoResult, IoError};
26 use sync::{Once, ONCE_INIT};
28 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
29 static $name: Helper<$m> = Helper {
30 lock: ::sync::MUTEX_INIT,
31 cond: ::sync::CONDVAR_INIT,
32 chan: ::cell::UnsafeCell { value: 0 as *mut ::sync::mpsc::Sender<$m> },
33 signal: ::cell::UnsafeCell { value: 0 },
34 initialized: ::cell::UnsafeCell { value: false },
35 shutdown: ::cell::UnsafeCell { value: false },
44 pub mod helper_signal;
51 pub mod stack_overflow;
60 pub use sys_common::net::get_host_addresses;
61 pub use sys_common::net::get_address_name;
64 // FIXME: move these to c module
65 pub type sock_t = libc::SOCKET;
66 pub type wrlen = libc::c_int;
67 pub type msglen_t = libc::c_int;
68 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::closesocket(sock); }
70 // windows has zero values as errors
71 fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
79 pub fn last_error() -> IoError {
80 let errno = os::errno() as i32;
81 let mut err = decode_error(errno);
82 err.detail = Some(os::error_string(errno));
86 pub fn last_net_error() -> IoError {
87 let errno = unsafe { c::WSAGetLastError() as i32 };
88 let mut err = decode_error(errno);
89 err.detail = Some(os::error_string(errno));
93 pub fn last_gai_error(_errno: i32) -> IoError {
97 /// Convert an `errno` value into a high-level error variant and description.
98 pub fn decode_error(errno: i32) -> IoError {
99 let (kind, desc) = match errno {
100 libc::EOF => (io::EndOfFile, "end of file"),
101 libc::ERROR_NO_DATA => (io::BrokenPipe, "the pipe is being closed"),
102 libc::ERROR_FILE_NOT_FOUND => (io::FileNotFound, "file not found"),
103 libc::ERROR_INVALID_NAME => (io::InvalidInput, "invalid file name"),
104 libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"),
105 libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"),
106 libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
107 (io::PermissionDenied, "permission denied"),
108 libc::WSAEWOULDBLOCK => {
109 (io::ResourceUnavailable, "resource temporarily unavailable")
111 libc::WSAENOTCONN => (io::NotConnected, "not connected"),
112 libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"),
113 libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
114 libc::WSAEADDRINUSE => (io::ConnectionRefused, "address in use"),
115 libc::ERROR_BROKEN_PIPE => (io::EndOfFile, "the pipe has ended"),
116 libc::ERROR_OPERATION_ABORTED =>
117 (io::TimedOut, "operation timed out"),
118 libc::WSAEINVAL => (io::InvalidInput, "invalid argument"),
119 libc::ERROR_CALL_NOT_IMPLEMENTED =>
120 (io::IoUnavailable, "function not implemented"),
121 libc::ERROR_INVALID_HANDLE =>
122 (io::MismatchedFileTypeForOperation,
123 "invalid handle provided to function"),
124 libc::ERROR_NOTHING_TO_TERMINATE =>
125 (io::InvalidInput, "no process to kill"),
126 libc::ERROR_ALREADY_EXISTS =>
127 (io::PathAlreadyExists, "path already exists"),
129 // libuv maps this error code to EISDIR. we do too. if it is found
130 // to be incorrect, we can add in some more machinery to only
131 // return this message when ERROR_INVALID_FUNCTION after certain
133 libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
134 "illegal operation on a directory"),
136 _ => (io::OtherIoError, "unknown error")
138 IoError { kind: kind, desc: desc, detail: None }
141 pub fn decode_error_detailed(errno: i32) -> IoError {
142 let mut err = decode_error(errno);
143 err.detail = Some(os::error_string(errno));
148 pub fn retry<I, F>(f: F) -> I where F: FnOnce() -> I { f() } // PR rust-lang/rust/#17020
150 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
152 tv_sec: (ms / 1000) as libc::c_long,
153 tv_usec: ((ms % 1000) * 1000) as libc::c_long,
157 pub fn wouldblock() -> bool {
158 let err = os::errno();
159 err == libc::WSAEWOULDBLOCK as uint
162 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
163 let mut set = nb as libc::c_ulong;
164 if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
173 static START: Once = ONCE_INIT;
176 let mut data: c::WSADATA = mem::zeroed();
177 let ret = c::WSAStartup(0x202, // version 2.2
184 pub fn unimpl() -> IoError {
186 kind: io::IoUnavailable,
187 desc: "operation is not implemented",
192 pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
195 let mut s = s.utf16_units().collect::<Vec<u16>>();
199 None => Err(IoError {
200 kind: io::InvalidInput,
201 desc: "valid unicode input required",