]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/unix/mod.rs
rollup merge of #20518: nagisa/weighted-bool
[rust.git] / src / libstd / sys / unix / 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(unused_imports)]
14 #![allow(dead_code)]
15 #![allow(unused_unsafe)]
16 #![allow(unused_mut)]
17
18 use prelude::v1::*;
19
20 use ffi;
21 use io::{self, IoResult, IoError};
22 use libc;
23 use num::{Int, SignedInt};
24 use num;
25 use str;
26 use sys_common::mkerr_libc;
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 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 stack_overflow;
51 pub mod sync;
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 = self::fs::fd_t;
66 pub type wrlen = libc::size_t;
67 pub type msglen_t = libc::size_t;
68 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); }
69
70 pub fn last_error() -> IoError {
71     decode_error_detailed(os::errno() as i32)
72 }
73
74 pub fn last_net_error() -> IoError {
75     last_error()
76 }
77
78 extern "system" {
79     fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
80 }
81
82 pub fn last_gai_error(s: libc::c_int) -> IoError {
83
84     let mut err = decode_error(s);
85     err.detail = Some(unsafe {
86         str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
87     });
88     err
89 }
90
91 /// Convert an `errno` value into a high-level error variant and description.
92 pub fn decode_error(errno: i32) -> IoError {
93     // FIXME: this should probably be a bit more descriptive...
94     let (kind, desc) = match errno {
95         libc::EOF => (io::EndOfFile, "end of file"),
96         libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"),
97         libc::ECONNRESET => (io::ConnectionReset, "connection reset"),
98         libc::EPERM | libc::EACCES =>
99             (io::PermissionDenied, "permission denied"),
100         libc::EPIPE => (io::BrokenPipe, "broken pipe"),
101         libc::ENOTCONN => (io::NotConnected, "not connected"),
102         libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"),
103         libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
104         libc::EADDRINUSE => (io::ConnectionRefused, "address in use"),
105         libc::ENOENT => (io::FileNotFound, "no such file or directory"),
106         libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"),
107         libc::ENOSYS => (io::IoUnavailable, "function not implemented"),
108         libc::EINVAL => (io::InvalidInput, "invalid argument"),
109         libc::ENOTTY =>
110             (io::MismatchedFileTypeForOperation,
111              "file descriptor is not a TTY"),
112         libc::ETIMEDOUT => (io::TimedOut, "operation timed out"),
113         libc::ECANCELED => (io::TimedOut, "operation aborted"),
114         libc::consts::os::posix88::EEXIST =>
115             (io::PathAlreadyExists, "path already exists"),
116
117         // These two constants can have the same value on some systems,
118         // but different values on others, so we can't use a match
119         // clause
120         x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
121             (io::ResourceUnavailable, "resource temporarily unavailable"),
122
123         _ => (io::OtherIoError, "unknown error")
124     };
125     IoError { kind: kind, desc: desc, detail: None }
126 }
127
128 pub fn decode_error_detailed(errno: i32) -> IoError {
129     let mut err = decode_error(errno);
130     err.detail = Some(os::error_string(errno));
131     err
132 }
133
134 #[inline]
135 pub fn retry<T, F> (mut f: F) -> T where
136     T: SignedInt,
137     F: FnMut() -> T,
138 {
139     let one: T = Int::one();
140     loop {
141         let n = f();
142         if n == -one && os::errno() == libc::EINTR as int { }
143         else { return n }
144     }
145 }
146
147 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
148     libc::timeval {
149         tv_sec: (ms / 1000) as libc::time_t,
150         tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
151     }
152 }
153
154 pub fn wouldblock() -> bool {
155     let err = os::errno();
156     err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
157 }
158
159 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
160     let set = nb as libc::c_int;
161     mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
162 }
163
164 // nothing needed on unix platforms
165 pub fn init_net() {}