]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/unix/mod.rs
rollup merge of #20350: fhahn/issue-20340-rustdoc-version
[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
14 extern crate libc;
15
16 use num::{Int, SignedInt};
17 use prelude::*;
18 use io::{mod, IoResult, IoError};
19 use sys_common::mkerr_libc;
20
21 pub mod backtrace;
22 pub mod c;
23 pub mod ext;
24 pub mod condvar;
25 pub mod fs;
26 pub mod helper_signal;
27 pub mod mutex;
28 pub mod os;
29 pub mod pipe;
30 pub mod process;
31 pub mod rwlock;
32 pub mod stack_overflow;
33 pub mod sync;
34 pub mod tcp;
35 pub mod thread;
36 pub mod thread_local;
37 pub mod timer;
38 pub mod tty;
39 pub mod udp;
40
41 pub mod addrinfo {
42     pub use sys_common::net::get_host_addresses;
43     pub use sys_common::net::get_address_name;
44 }
45
46 // FIXME: move these to c module
47 pub type sock_t = self::fs::fd_t;
48 pub type wrlen = libc::size_t;
49 pub type msglen_t = libc::size_t;
50 pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); }
51
52 pub fn last_error() -> IoError {
53     decode_error_detailed(os::errno() as i32)
54 }
55
56 pub fn last_net_error() -> IoError {
57     last_error()
58 }
59
60 extern "system" {
61     fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
62 }
63
64 pub fn last_gai_error(s: libc::c_int) -> IoError {
65     use c_str::CString;
66
67     let mut err = decode_error(s);
68     err.detail = Some(unsafe {
69         CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
70     });
71     err
72 }
73
74 /// Convert an `errno` value into a high-level error variant and description.
75 pub fn decode_error(errno: i32) -> IoError {
76     // FIXME: this should probably be a bit more descriptive...
77     let (kind, desc) = match errno {
78         libc::EOF => (io::EndOfFile, "end of file"),
79         libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"),
80         libc::ECONNRESET => (io::ConnectionReset, "connection reset"),
81         libc::EPERM | libc::EACCES =>
82             (io::PermissionDenied, "permission denied"),
83         libc::EPIPE => (io::BrokenPipe, "broken pipe"),
84         libc::ENOTCONN => (io::NotConnected, "not connected"),
85         libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"),
86         libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
87         libc::EADDRINUSE => (io::ConnectionRefused, "address in use"),
88         libc::ENOENT => (io::FileNotFound, "no such file or directory"),
89         libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"),
90         libc::ENOSYS => (io::IoUnavailable, "function not implemented"),
91         libc::EINVAL => (io::InvalidInput, "invalid argument"),
92         libc::ENOTTY =>
93             (io::MismatchedFileTypeForOperation,
94              "file descriptor is not a TTY"),
95         libc::ETIMEDOUT => (io::TimedOut, "operation timed out"),
96         libc::ECANCELED => (io::TimedOut, "operation aborted"),
97         libc::consts::os::posix88::EEXIST =>
98             (io::PathAlreadyExists, "path already exists"),
99
100         // These two constants can have the same value on some systems,
101         // but different values on others, so we can't use a match
102         // clause
103         x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
104             (io::ResourceUnavailable, "resource temporarily unavailable"),
105
106         _ => (io::OtherIoError, "unknown error")
107     };
108     IoError { kind: kind, desc: desc, detail: None }
109 }
110
111 pub fn decode_error_detailed(errno: i32) -> IoError {
112     let mut err = decode_error(errno);
113     err.detail = Some(os::error_string(errno));
114     err
115 }
116
117 #[inline]
118 pub fn retry<T, F> (mut f: F) -> T where
119     T: SignedInt,
120     F: FnMut() -> T,
121 {
122     let one: T = Int::one();
123     loop {
124         let n = f();
125         if n == -one && os::errno() == libc::EINTR as int { }
126         else { return n }
127     }
128 }
129
130 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
131     libc::timeval {
132         tv_sec: (ms / 1000) as libc::time_t,
133         tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
134     }
135 }
136
137 pub fn wouldblock() -> bool {
138     let err = os::errno();
139     err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
140 }
141
142 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
143     let set = nb as libc::c_int;
144     mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
145 }
146
147 // nothing needed on unix platforms
148 pub fn init_net() {}