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 io::{self, ErrorKind};
23 use num::{Int, SignedInt};
25 use old_io::{self, IoResult, IoError};
27 use sys_common::mkerr_libc;
29 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
30 static $name: Helper<$m> = Helper {
31 lock: ::sync::MUTEX_INIT,
32 cond: ::sync::CONDVAR_INIT,
33 chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
34 signal: ::cell::UnsafeCell { value: 0 },
35 initialized: ::cell::UnsafeCell { value: false },
36 shutdown: ::cell::UnsafeCell { value: false },
45 pub mod fs; // support for std::old_io
46 pub mod fs2; // support for std::fs
47 pub mod helper_signal;
57 pub mod stack_overflow;
68 pub use sys_common::net::get_host_addresses;
69 pub use sys_common::net::get_address_name;
72 // FIXME: move these to c module
73 pub type sock_t = self::fs::fd_t;
74 pub type wrlen = libc::size_t;
75 pub type msglen_t = libc::size_t;
76 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); }
78 pub fn last_error() -> IoError {
79 decode_error_detailed(os::errno() as i32)
82 pub fn last_net_error() -> IoError {
87 fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
90 pub fn last_gai_error(s: libc::c_int) -> IoError {
92 let mut err = decode_error(s);
93 err.detail = Some(unsafe {
94 str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
99 /// Convert an `errno` value into a high-level error variant and description.
100 pub fn decode_error(errno: i32) -> IoError {
101 // FIXME: this should probably be a bit more descriptive...
102 let (kind, desc) = match errno {
103 libc::EOF => (old_io::EndOfFile, "end of file"),
104 libc::ECONNREFUSED => (old_io::ConnectionRefused, "connection refused"),
105 libc::ECONNRESET => (old_io::ConnectionReset, "connection reset"),
106 libc::EPERM | libc::EACCES =>
107 (old_io::PermissionDenied, "permission denied"),
108 libc::EPIPE => (old_io::BrokenPipe, "broken pipe"),
109 libc::ENOTCONN => (old_io::NotConnected, "not connected"),
110 libc::ECONNABORTED => (old_io::ConnectionAborted, "connection aborted"),
111 libc::EADDRNOTAVAIL => (old_io::ConnectionRefused, "address not available"),
112 libc::EADDRINUSE => (old_io::ConnectionRefused, "address in use"),
113 libc::ENOENT => (old_io::FileNotFound, "no such file or directory"),
114 libc::EISDIR => (old_io::InvalidInput, "illegal operation on a directory"),
115 libc::ENOSYS => (old_io::IoUnavailable, "function not implemented"),
116 libc::EINVAL => (old_io::InvalidInput, "invalid argument"),
118 (old_io::MismatchedFileTypeForOperation,
119 "file descriptor is not a TTY"),
120 libc::ETIMEDOUT => (old_io::TimedOut, "operation timed out"),
121 libc::ECANCELED => (old_io::TimedOut, "operation aborted"),
122 libc::consts::os::posix88::EEXIST =>
123 (old_io::PathAlreadyExists, "path already exists"),
125 // These two constants can have the same value on some systems,
126 // but different values on others, so we can't use a match
128 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
129 (old_io::ResourceUnavailable, "resource temporarily unavailable"),
131 _ => (old_io::OtherIoError, "unknown error")
133 IoError { kind: kind, desc: desc, detail: None }
136 pub fn decode_error_detailed(errno: i32) -> IoError {
137 let mut err = decode_error(errno);
138 err.detail = Some(os::error_string(errno));
142 pub fn decode_error_kind(errno: i32) -> ErrorKind {
143 match errno as libc::c_int {
144 libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
145 libc::ECONNRESET => ErrorKind::ConnectionReset,
146 libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
147 libc::EPIPE => ErrorKind::BrokenPipe,
148 libc::ENOTCONN => ErrorKind::NotConnected,
149 libc::ECONNABORTED => ErrorKind::ConnectionAborted,
150 libc::EADDRNOTAVAIL => ErrorKind::ConnectionRefused,
151 libc::EADDRINUSE => ErrorKind::ConnectionRefused,
152 libc::ENOENT => ErrorKind::FileNotFound,
153 libc::EISDIR => ErrorKind::InvalidInput,
154 libc::EINTR => ErrorKind::Interrupted,
155 libc::EINVAL => ErrorKind::InvalidInput,
156 libc::ENOTTY => ErrorKind::MismatchedFileTypeForOperation,
157 libc::ETIMEDOUT => ErrorKind::TimedOut,
158 libc::ECANCELED => ErrorKind::TimedOut,
159 libc::consts::os::posix88::EEXIST => ErrorKind::PathAlreadyExists,
161 // These two constants can have the same value on some systems,
162 // but different values on others, so we can't use a match
164 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
165 ErrorKind::ResourceUnavailable,
167 _ => ErrorKind::Other,
172 pub fn retry<T, F> (mut f: F) -> T where
176 let one: T = Int::one();
179 if n == -one && os::errno() == libc::EINTR as i32 { }
184 pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
185 let one: T = Int::one();
187 Err(io::Error::last_os_error())
193 pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
194 where T: SignedInt, F: FnMut() -> T
198 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
199 other => return other,
204 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
206 tv_sec: (ms / 1000) as libc::time_t,
207 tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
211 pub fn wouldblock() -> bool {
212 let err = os::errno();
213 err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
216 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
217 let set = nb as libc::c_int;
218 mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
221 // nothing needed on unix platforms