1 | //! Implementation of `errno` functionality for Unix systems. |
2 | //! |
3 | //! Adapted from `src/libstd/sys/unix/os.rs` in the Rust distribution. |
4 | |
5 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
6 | // file at the top-level directory of this distribution and at |
7 | // http://rust-lang.org/COPYRIGHT. |
8 | // |
9 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
10 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
11 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
12 | // option. This file may not be copied, modified, or distributed |
13 | // except according to those terms. |
14 | |
15 | use core::str; |
16 | use libc::{self, c_char, c_int, size_t, strlen}; |
17 | |
18 | use crate::Errno; |
19 | |
20 | fn from_utf8_lossy(input: &[u8]) -> &str { |
21 | match str::from_utf8(input) { |
22 | Ok(valid: &str) => valid, |
23 | Err(error: Utf8Error) => unsafe { str::from_utf8_unchecked(&input[..error.valid_up_to()]) }, |
24 | } |
25 | } |
26 | |
27 | pub fn with_description<F, T>(err: Errno, callback: F) -> T |
28 | where |
29 | F: FnOnce(Result<&str, Errno>) -> T, |
30 | { |
31 | let mut buf: [u8; 1024] = [0u8; 1024]; |
32 | let c_str: &[u8] = unsafe { |
33 | if strerror_r(errnum:err.0, buf:buf.as_mut_ptr() as *mut _, buflen:buf.len() as size_t) < 0 { |
34 | let fm_err: Errno = errno(); |
35 | if fm_err != Errno(libc::ERANGE) { |
36 | return callback(Err(fm_err)); |
37 | } |
38 | } |
39 | let c_str_len: usize = strlen(cs:buf.as_ptr() as *const _); |
40 | &buf[..c_str_len] |
41 | }; |
42 | callback(Ok(from_utf8_lossy(input:c_str))) |
43 | } |
44 | |
45 | pub const STRERROR_NAME: &str = "strerror_r" ; |
46 | |
47 | pub fn errno() -> Errno { |
48 | unsafe { Errno(*errno_location()) } |
49 | } |
50 | |
51 | pub fn set_errno(Errno(errno: i32): Errno) { |
52 | unsafe { |
53 | *errno_location() = errno; |
54 | } |
55 | } |
56 | |
57 | extern "C" { |
58 | #[cfg_attr ( |
59 | any(target_os = "macos" , target_os = "ios" , target_os = "freebsd" ), |
60 | link_name = "__error" |
61 | )] |
62 | #[cfg_attr ( |
63 | any( |
64 | target_os = "openbsd" , |
65 | target_os = "netbsd" , |
66 | target_os = "bitrig" , |
67 | target_os = "android" , |
68 | target_os = "espidf" |
69 | ), |
70 | link_name = "__errno" |
71 | )] |
72 | #[cfg_attr ( |
73 | any(target_os = "solaris" , target_os = "illumos" ), |
74 | link_name = "___errno" |
75 | )] |
76 | #[cfg_attr (target_os = "haiku" , link_name = "_errnop" )] |
77 | #[cfg_attr ( |
78 | any( |
79 | target_os = "linux" , |
80 | target_os = "hurd" , |
81 | target_os = "redox" , |
82 | target_os = "dragonfly" |
83 | ), |
84 | link_name = "__errno_location" |
85 | )] |
86 | #[cfg_attr (target_os = "aix" , link_name = "_Errno" )] |
87 | #[cfg_attr (target_os = "nto" , link_name = "__get_errno_ptr" )] |
88 | fn errno_location() -> *mut c_int; |
89 | |
90 | #[cfg_attr ( |
91 | any(target_os = "linux" , target_os = "hurd" ), |
92 | link_name = "__xpg_strerror_r" |
93 | )] |
94 | fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; |
95 | } |
96 | |