| 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_int, size_t, strerror_r, 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 | let rc: i32 = strerror_r(errnum:err.0, buf.as_mut_ptr() as *mut _, buflen:buf.len() as size_t); | 
|---|
| 34 | if rc != 0 { | 
|---|
| 35 | // Handle negative return codes for compatibility with glibc < 2.13 | 
|---|
| 36 | let fm_err: Errno = match rc < 0 { | 
|---|
| 37 | true => errno(), | 
|---|
| 38 | false => Errno(rc), | 
|---|
| 39 | }; | 
|---|
| 40 | if fm_err != Errno(libc::ERANGE) { | 
|---|
| 41 | return callback(Err(fm_err)); | 
|---|
| 42 | } | 
|---|
| 43 | } | 
|---|
| 44 | let c_str_len: usize = strlen(cs:buf.as_ptr() as *const _); | 
|---|
| 45 | &buf[..c_str_len] | 
|---|
| 46 | }; | 
|---|
| 47 | callback(Ok(from_utf8_lossy(input:c_str))) | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | pub const STRERROR_NAME: &str = "strerror_r"; | 
|---|
| 51 |  | 
|---|
| 52 | pub fn errno() -> Errno { | 
|---|
| 53 | unsafe { Errno(*errno_location()) } | 
|---|
| 54 | } | 
|---|
| 55 |  | 
|---|
| 56 | pub fn set_errno(Errno(errno: i32): Errno) { | 
|---|
| 57 | unsafe { | 
|---|
| 58 | *errno_location() = errno; | 
|---|
| 59 | } | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | unsafeextern "C"{ | 
|---|
| 63 | #[ cfg_attr( | 
|---|
| 64 | any( | 
|---|
| 65 | target_os = "macos", | 
|---|
| 66 | target_os = "ios", | 
|---|
| 67 | target_os = "tvos", | 
|---|
| 68 | target_os = "watchos", | 
|---|
| 69 | target_os = "visionos", | 
|---|
| 70 | target_os = "freebsd" | 
|---|
| 71 | ), | 
|---|
| 72 | link_name = "__error" | 
|---|
| 73 | )] | 
|---|
| 74 | #[ cfg_attr( | 
|---|
| 75 | any( | 
|---|
| 76 | target_os = "openbsd", | 
|---|
| 77 | target_os = "netbsd", | 
|---|
| 78 | target_os = "android", | 
|---|
| 79 | target_os = "espidf", | 
|---|
| 80 | target_env = "newlib" | 
|---|
| 81 | ), | 
|---|
| 82 | link_name = "__errno" | 
|---|
| 83 | )] | 
|---|
| 84 | #[ cfg_attr( | 
|---|
| 85 | any(target_os = "solaris", target_os = "illumos"), | 
|---|
| 86 | link_name = "___errno" | 
|---|
| 87 | )] | 
|---|
| 88 | #[ cfg_attr(target_os = "haiku", link_name = "_errnop")] | 
|---|
| 89 | #[ cfg_attr( | 
|---|
| 90 | any( | 
|---|
| 91 | target_os = "linux", | 
|---|
| 92 | target_os = "hurd", | 
|---|
| 93 | target_os = "redox", | 
|---|
| 94 | target_os = "dragonfly", | 
|---|
| 95 | target_os = "emscripten", | 
|---|
| 96 | ), | 
|---|
| 97 | link_name = "__errno_location" | 
|---|
| 98 | )] | 
|---|
| 99 | #[ cfg_attr(target_os = "aix", link_name = "_Errno")] | 
|---|
| 100 | #[ cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] | 
|---|
| 101 | unsafefn errno_location() -> *mut c_int; | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|