]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/mod.rs
Merge pull request #20510 from tshepang/patch-6
[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 prelude::v1::*;
22
23 use num;
24 use mem;
25 use io::{self, IoResult, IoError};
26 use sync::{Once, ONCE_INIT};
27
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 },
36     };
37 ) }
38
39 pub mod backtrace;
40 pub mod c;
41 pub mod ext;
42 pub mod condvar;
43 pub mod fs;
44 pub mod helper_signal;
45 pub mod mutex;
46 pub mod os;
47 pub mod pipe;
48 pub mod process;
49 pub mod rwlock;
50 pub mod sync;
51 pub mod stack_overflow;
52 pub mod tcp;
53 pub mod thread;
54 pub mod thread_local;
55 pub mod timer;
56 pub mod tty;
57 pub mod udp;
58
59 pub mod addrinfo {
60     pub use sys_common::net::get_host_addresses;
61     pub use sys_common::net::get_address_name;
62 }
63
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); }
69
70 // windows has zero values as errors
71 fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
72     if ret == 0 {
73         Err(last_error())
74     } else {
75         Ok(())
76     }
77 }
78
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));
83     err
84 }
85
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));
90     err
91 }
92
93 pub fn last_gai_error(_errno: i32) -> IoError {
94     last_net_error()
95 }
96
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")
110         }
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"),
128
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
132         // Windows calls.
133         libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
134                                          "illegal operation on a directory"),
135
136         _ => (io::OtherIoError, "unknown error")
137     };
138     IoError { kind: kind, desc: desc, detail: None }
139 }
140
141 pub fn decode_error_detailed(errno: i32) -> IoError {
142     let mut err = decode_error(errno);
143     err.detail = Some(os::error_string(errno));
144     err
145 }
146
147 #[inline]
148 pub fn retry<I, F>(f: F) -> I where F: FnOnce() -> I { f() } // PR rust-lang/rust/#17020
149
150 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
151     libc::timeval {
152         tv_sec: (ms / 1000) as libc::c_long,
153         tv_usec: ((ms % 1000) * 1000) as libc::c_long,
154     }
155 }
156
157 pub fn wouldblock() -> bool {
158     let err = os::errno();
159     err == libc::WSAEWOULDBLOCK as uint
160 }
161
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 } {
165         Err(last_error())
166     } else {
167         Ok(())
168     }
169 }
170
171 pub fn init_net() {
172     unsafe {
173         static START: Once = ONCE_INIT;
174
175         START.call_once(|| {
176             let mut data: c::WSADATA = mem::zeroed();
177             let ret = c::WSAStartup(0x202, // version 2.2
178                                     &mut data);
179             assert_eq!(ret, 0);
180         });
181     }
182 }
183
184 pub fn unimpl() -> IoError {
185     IoError {
186         kind: io::IoUnavailable,
187         desc: "operation is not implemented",
188         detail: None,
189     }
190 }
191
192 pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
193     match s {
194         Some(s) => Ok({
195             let mut s = s.utf16_units().collect::<Vec<u16>>();
196             s.push(0);
197             s
198         }),
199         None => Err(IoError {
200             kind: io::InvalidInput,
201             desc: "valid unicode input required",
202             detail: None
203         })
204     }
205 }