Il ven 21 feb 2025, 11:41 Zhao Liu <[email protected]> ha scritto:

> Hi Paolo,
>
> > It is a common convention in QEMU to return a positive value in case of
> > success, and a negated errno value in case of error.  Unfortunately,
> > using errno portably in Rust is a bit complicated; on Unix the errno
> > values are supported natively by io::Error, but on Windows they are not;
> > so, use the libc crate.
>
> I'm a bit confused. The doc of error.h just said the negative value for
> failure:
>
> • integer-valued functions return non-negative / negative.
>
> Why do we need to using libc's -errno for Windows as well?
>

error.h doesn't explicitly mention errno because there are functions that
return -1 on all errors, but errno is a common convention for negative
return values too.

Converting `io::Error::last_os_error().raw_os_error().unwrap()` to a
> negative value seems compatible with Windows, except it returns Windows
> error codes.
>

... but that's not what C functions expect. They might pass it to set
error_setg_errno for example.

> +// On Unix, from_raw_os_error takes an errno value and OS errors
> > +// are printed using strerror.  On Windows however it takes a
> > +// GetLastError() value; therefore we need to convert errno values
> > +// into io::Error by hand.  This is the same mapping that the
> > +// standard library uses to retrieve the kind of OS errors
> > +// (`std::sys::pal::unix::decode_error_kind`).
> > +impl From<Errno> for ErrorKind {
> > +    fn from(value: Errno) -> ErrorKind {
>
> What about `use ErrorKind::*;` to omit the following "ErrorKind::"
> prefix?
>

Yeah, that's possible.


> > +        let Errno(errno) = value;
> > +        match i32::from(errno) {
>
> Maybe `match i32::from(errno.0)` ?


Well, I don't like .0 too much...

> +            libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
> > +            libc::ENOENT => ErrorKind::NotFound,
> > +            libc::EINTR => ErrorKind::Interrupted,
> > +            x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
> ErrorKind::WouldBlock,
> > +            libc::ENOMEM => ErrorKind::OutOfMemory,
> > +            libc::EEXIST => ErrorKind::AlreadyExists,
> > +            libc::EINVAL => ErrorKind::InvalidInput,
> > +            libc::EPIPE => ErrorKind::BrokenPipe,
> > +            libc::EADDRINUSE => ErrorKind::AddrInUse,
> > +            libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
> > +            libc::ECONNABORTED => ErrorKind::ConnectionAborted,
> > +            libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
> > +            libc::ECONNRESET => ErrorKind::ConnectionReset,
> > +            libc::ENOTCONN => ErrorKind::NotConnected,
> > +            libc::ENOTSUP => ErrorKind::Unsupported,
> > +            libc::ETIMEDOUT => ErrorKind::TimedOut,
> > +            _ => ErrorKind::Other,
>
> Are these errno cases specifically selected? It seems to have fewer than
> `decode_error_kind` lists. Why not support all the cases
> `decode_error_kind`
> mentions?


Not all of them are in all Rust versions; see
https://stdrs.dev/nightly/x86_64-unknown-linux-gnu/src/std/io/error.rs.html#179-395
.

> +// This is used on Windows for all io::Errors, but also on Unix if the
> > +// io::Error does not have a raw OS error.  This is the reversed
> > +// mapping of the above.
>
> Maybe:
>
> This is the "almost" reversed (except the default case) mapping
>

True, thanks.

Paolo

Reply via email to