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
15use core::str;
16use libc::{self, c_char, c_int, size_t, strlen};
17
18use crate::Errno;
19
20fn 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
27pub fn with_description<F, T>(err: Errno, callback: F) -> T
28where
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
45pub const STRERROR_NAME: &str = "strerror_r";
46
47pub fn errno() -> Errno {
48 unsafe { Errno(*errno_location()) }
49}
50
51pub fn set_errno(Errno(errno: i32): Errno) {
52 unsafe {
53 *errno_location() = errno;
54 }
55}
56
57extern "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