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(unused_imports)]
15 #![allow(unused_unsafe)]
21 use num::{Int, SignedInt};
23 use io::{mod, IoResult, IoError};
24 use sys_common::mkerr_libc;
26 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
27 static $name: Helper<$m> = Helper {
28 lock: ::sync::MUTEX_INIT,
29 cond: ::sync::CONDVAR_INIT,
30 chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
31 signal: ::cell::UnsafeCell { value: 0 },
32 initialized: ::cell::UnsafeCell { value: false },
33 shutdown: ::cell::UnsafeCell { value: false },
42 pub mod helper_signal;
48 pub mod stack_overflow;
58 pub use sys_common::net::get_host_addresses;
59 pub use sys_common::net::get_address_name;
62 // FIXME: move these to c module
63 pub type sock_t = self::fs::fd_t;
64 pub type wrlen = libc::size_t;
65 pub type msglen_t = libc::size_t;
66 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); }
68 pub fn last_error() -> IoError {
69 decode_error_detailed(os::errno() as i32)
72 pub fn last_net_error() -> IoError {
77 fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
80 pub fn last_gai_error(s: libc::c_int) -> IoError {
83 let mut err = decode_error(s);
84 err.detail = Some(unsafe {
85 CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
90 /// Convert an `errno` value into a high-level error variant and description.
91 pub fn decode_error(errno: i32) -> IoError {
92 // FIXME: this should probably be a bit more descriptive...
93 let (kind, desc) = match errno {
94 libc::EOF => (io::EndOfFile, "end of file"),
95 libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"),
96 libc::ECONNRESET => (io::ConnectionReset, "connection reset"),
97 libc::EPERM | libc::EACCES =>
98 (io::PermissionDenied, "permission denied"),
99 libc::EPIPE => (io::BrokenPipe, "broken pipe"),
100 libc::ENOTCONN => (io::NotConnected, "not connected"),
101 libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"),
102 libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
103 libc::EADDRINUSE => (io::ConnectionRefused, "address in use"),
104 libc::ENOENT => (io::FileNotFound, "no such file or directory"),
105 libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"),
106 libc::ENOSYS => (io::IoUnavailable, "function not implemented"),
107 libc::EINVAL => (io::InvalidInput, "invalid argument"),
109 (io::MismatchedFileTypeForOperation,
110 "file descriptor is not a TTY"),
111 libc::ETIMEDOUT => (io::TimedOut, "operation timed out"),
112 libc::ECANCELED => (io::TimedOut, "operation aborted"),
113 libc::consts::os::posix88::EEXIST =>
114 (io::PathAlreadyExists, "path already exists"),
116 // These two constants can have the same value on some systems,
117 // but different values on others, so we can't use a match
119 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
120 (io::ResourceUnavailable, "resource temporarily unavailable"),
122 _ => (io::OtherIoError, "unknown error")
124 IoError { kind: kind, desc: desc, detail: None }
127 pub fn decode_error_detailed(errno: i32) -> IoError {
128 let mut err = decode_error(errno);
129 err.detail = Some(os::error_string(errno));
134 pub fn retry<T, F> (mut f: F) -> T where
138 let one: T = Int::one();
141 if n == -one && os::errno() == libc::EINTR as int { }
146 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
148 tv_sec: (ms / 1000) as libc::time_t,
149 tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
153 pub fn wouldblock() -> bool {
154 let err = os::errno();
155 err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
158 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
159 let set = nb as libc::c_int;
160 mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
163 // nothing needed on unix platforms