How to convert nix::Error into io::Error?


#1

I’m currently struggling to figure out how to convert a nix::Error to an io::Error. It seems like one could convert a nix::Errno into an i32 and then use from_raw_os_error, except in the case where you have an InvalidPath, which presumably would translate into either InvalidInput or InvalidData.

Surely I am not the first person attempting this translation? Is there an easier way than writing a little function translating as described above, and then inserting that function into each try!?


#2

Sounds like what you actually want is something that can fail in multiple ways?

pub enum MyError {
    IO(io::Error),
    Nix(nix::Error),
}

#3

I could do something like that, but it would be redundant, as every nix::Error can be translated directly into an io::Error. So there should be no reason for any error type other than an io::Error!

Perhaps this is a bug in nix, which should implement From to convert to io::Error?

The issue here is that I would like a cross-platform API with separate implementations on different platforms, which to me argues against explicitly returning any nix::Errors, which are strictly redundant with those described in io::Error.


#4

Sorry, I’m unfamiliar with nix. Yeah, it seems odd for them to have their own errors in that case, if it’s redundant with io::Error.


#5

It’s not entirely odd, because they can guarantee that their errors will always (or almost always) be raw unix errno codes, so it is nice to be explicit. But it seems inconvenient when trying to write a nice API (which should use io::Error).


#6

Sounds like it’d make a good PR to nix. :wink:


#7

It sounds like nix should implement both From<io::Error> and Into<io:Error> for nix::Error – then it can freely convert in both directions.


#8

I don’t think it can implement Fromio::Error, since I think there are io::Errors that cannot be represented as nix::Error (which is why it is reasonable for nix::Error to exist), but I will see about submitting a PR for an Intoio::Error for nix::Error.

EDIT:

It looks like nix already supports Intoio::Error, but for some reason rust isn’t picking this up, presumably because there is something I need to “use” in order to have the Fromnix::Error implementation for io::Error visible. :frowning:

nix already has the following implementation:

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        match err {
            Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
            Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        }
    }
}

but for some reason I am getting the following error:

<std macros>:6:1: 6:32 error: the trait `core::convert::From<nix::Error>` is not implemented for the type `std::io::error::Error` [E0277]
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:1:1: 6:48 note: in expansion of try!
src/linux.rs:13:21: 13:46 note: expansion site
<std macros>:6:1: 6:32 help: run `rustc --explain E0277` to see a detailed explanation

Any ideas what I might need in order to fix this?


#9

I finally found out that the problem was that this issue is already fixed in the upstream nix-rust repository, but the fix hasn’t yet found its way onto crates.io. So I “fixed” the problem by specifying

nix = { git = "https://github.com/carllerche/nix-rust" }

in my Cargo.toml. It’s a hokey temporary solution, but I’m just experimenting for now, and this works.