System error message without the suffix "os error n"

Error messages displayed std::io::Errorcontain the suffix "(os error n)", which is easily reproduced when the program starts, for example:

use std::fs;
use std::io::Write;

fn main() {
    let fl = "no such file";
    if let Err(e) = fs::metadata(fl) {
        writeln!(std::io::stderr(), "{}: {}", fl, e).unwrap();
    }
}

Conclusion:

no such file: No such file or directory (os error 2)

How to get the system error message provided by the system, that is, without the "os error 2" part?

I tried:

  • a call e.description()that returns another error message ("object not found"), which is useful, but not what I'm looking for;

  • checking the structure of an object Error, for example. using a debug display {:?}that shows that the object contains a string without a decorated error, but seems to be hidden in an internal field.

Please note that I am targeting a portable rather than a Linux solution.

+4
1

code, os 2:

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.repr {
            Repr::Os(code) => {
                let detail = sys::os::error_string(code);
                write!(fmt, "{} (os error {})", detail, code)
            }
            Repr::Custom(ref c) => c.error.fmt(fmt),
            Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
        }
    }
}

, sys::os::error_string . .

#![feature(libc)]
extern crate libc;

use std::fs;
use std::io::Write;
use std::os::raw::{c_int, c_char};
use std::str;
use std::ffi::CStr;

const TMPBUF_SZ: usize = 128;

// from: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/os.rs#L84
pub fn error_string(errno: i32) -> String {
    extern {
        #[cfg_attr(any(target_os = "linux", target_env = "newlib"),
                   link_name = "__xpg_strerror_r")]
        fn strerror_r(errnum: c_int, buf: *mut c_char,
                      buflen: libc::size_t) -> c_int;
    }

    let mut buf = [0 as c_char; TMPBUF_SZ];

    let p = buf.as_mut_ptr();
    unsafe {
        if strerror_r(errno as c_int, p, buf.len()) < 0 {
            panic!("strerror_r failure");
        }

        let p = p as *const _;
        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
    }
}

fn main() {
    let fl = "no such file";
    if let Err(e) = fs::metadata(fl) {
        writeln!(std::io::stderr(), "{}: {}", fl, e).unwrap();
        writeln!(std::io::stderr(), "{}", &error_string(e.raw_os_error().unwrap())).unwrap();
    }
}

:

no such file: No such file or directory (os error 2)
No such file or directory
+2

Source: https://habr.com/ru/post/1661387/


All Articles