]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/mod.rs
Fall out of the std::sync rewrite
[rust.git] / src / libstd / sys / windows / mod.rs
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 #![allow(missing_docs)]
12 #![allow(non_camel_case_types)]
13 #![allow(non_snake_case)]
14 #![allow(unused_imports)]
15 #![allow(dead_code)]
16 #![allow(unused_unsafe)]
17 #![allow(unused_mut)]
18
19 extern crate libc;
20
21 use num;
22 use mem;
23 use prelude::*;
24 use io::{mod, IoResult, IoError};
25 use sync::{Once, ONCE_INIT};
26
27 macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
28     static $name: Helper<$m> = Helper {
29         lock: ::sync::MUTEX_INIT,
30         cond: ::sync::CONDVAR_INIT,
31         chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
32         signal: ::cell::UnsafeCell { value: 0 },
33         initialized: ::cell::UnsafeCell { value: false },
34         shutdown: ::cell::UnsafeCell { value: false },
35     };
36 ) )
37
38 pub mod c;
39 pub mod ext;
40 pub mod condvar;
41 pub mod fs;
42 pub mod helper_signal;
43 pub mod mutex;
44 pub mod os;
45 pub mod pipe;
46 pub mod process;
47 pub mod rwlock;
48 pub mod sync;
49 pub mod tcp;
50 pub mod thread_local;
51 pub mod timer;
52 pub mod tty;
53 pub mod udp;
54
55 pub mod addrinfo {
56     pub use sys_common::net::get_host_addresses;
57 }
58
59 // FIXME: move these to c module
60 pub type sock_t = libc::SOCKET;
61 pub type wrlen = libc::c_int;
62 pub type msglen_t = libc::c_int;
63 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::closesocket(sock); }
64
65 // windows has zero values as errors
66 fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
67     if ret == 0 {
68         Err(last_error())
69     } else {
70         Ok(())
71     }
72 }
73
74 pub fn last_error() -> IoError {
75     let errno = os::errno() as i32;
76     let mut err = decode_error(errno);
77     err.detail = Some(os::error_string(errno));
78     err
79 }
80
81 pub fn last_net_error() -> IoError {
82     let errno = unsafe { c::WSAGetLastError() as i32 };
83     let mut err = decode_error(errno);
84     err.detail = Some(os::error_string(errno));
85     err
86 }
87
88 pub fn last_gai_error(_errno: i32) -> IoError {
89     last_net_error()
90 }
91
92 /// Convert an `errno` value into a high-level error variant and description.
93 pub fn decode_error(errno: i32) -> IoError {
94     let (kind, desc) = match errno {
95         libc::EOF => (io::EndOfFile, "end of file"),
96         libc::ERROR_NO_DATA => (io::BrokenPipe, "the pipe is being closed"),
97         libc::ERROR_FILE_NOT_FOUND => (io::FileNotFound, "file not found"),
98         libc::ERROR_INVALID_NAME => (io::InvalidInput, "invalid file name"),
99         libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"),
100         libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"),
101         libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
102             (io::PermissionDenied, "permission denied"),
103         libc::WSAEWOULDBLOCK => {
104             (io::ResourceUnavailable, "resource temporarily unavailable")
105         }
106         libc::WSAENOTCONN => (io::NotConnected, "not connected"),
107         libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"),
108         libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
109         libc::WSAEADDRINUSE => (io::ConnectionRefused, "address in use"),
110         libc::ERROR_BROKEN_PIPE => (io::EndOfFile, "the pipe has ended"),
111         libc::ERROR_OPERATION_ABORTED =>
112             (io::TimedOut, "operation timed out"),
113         libc::WSAEINVAL => (io::InvalidInput, "invalid argument"),
114         libc::ERROR_CALL_NOT_IMPLEMENTED =>
115             (io::IoUnavailable, "function not implemented"),
116         libc::ERROR_INVALID_HANDLE =>
117             (io::MismatchedFileTypeForOperation,
118              "invalid handle provided to function"),
119         libc::ERROR_NOTHING_TO_TERMINATE =>
120             (io::InvalidInput, "no process to kill"),
121
122         // libuv maps this error code to EISDIR. we do too. if it is found
123         // to be incorrect, we can add in some more machinery to only
124         // return this message when ERROR_INVALID_FUNCTION after certain
125         // Windows calls.
126         libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
127                                          "illegal operation on a directory"),
128
129         _ => (io::OtherIoError, "unknown error")
130     };
131     IoError { kind: kind, desc: desc, detail: None }
132 }
133
134 pub fn decode_error_detailed(errno: i32) -> IoError {
135     let mut err = decode_error(errno);
136     err.detail = Some(os::error_string(errno));
137     err
138 }
139
140 #[inline]
141 pub fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
142
143 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
144     libc::timeval {
145         tv_sec: (ms / 1000) as libc::c_long,
146         tv_usec: ((ms % 1000) * 1000) as libc::c_long,
147     }
148 }
149
150 pub fn wouldblock() -> bool {
151     let err = os::errno();
152     err == libc::WSAEWOULDBLOCK as uint
153 }
154
155 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
156     let mut set = nb as libc::c_ulong;
157     if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
158         Err(last_error())
159     } else {
160         Ok(())
161     }
162 }
163
164 pub fn init_net() {
165     unsafe {
166         static START: Once = ONCE_INIT;
167
168         START.doit(|| {
169             let mut data: c::WSADATA = mem::zeroed();
170             let ret = c::WSAStartup(0x202, // version 2.2
171                                     &mut data);
172             assert_eq!(ret, 0);
173         });
174     }
175 }
176
177 pub fn unimpl() -> IoError {
178     IoError {
179         kind: io::IoUnavailable,
180         desc: "operation is not implemented",
181         detail: None,
182     }
183 }
184
185 pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
186     match s {
187         Some(s) => Ok({
188             let mut s = s.utf16_units().collect::<Vec<u16>>();
189             s.push(0);
190             s
191         }),
192         None => Err(IoError {
193             kind: io::InvalidInput,
194             desc: "valid unicode input required",
195             detail: None
196         })
197     }
198 }