Browse Source

Remove libc OS error functions

We aren't actually using any of newlib's error functionality. All of our
errors come from ctrulib functions.
pull/10/head
Fenrir 8 years ago
parent
commit
b1a213f56a
  1. 20
      ctru-sys/src/sys/libc.rs
  2. 211
      src/io/error.rs
  3. 1
      src/sys/mod.rs
  4. 78
      src/sys/os.rs

20
ctru-sys/src/sys/libc.rs

@ -1,24 +1,5 @@
pub const STDOUT_FILENO: c_int = 1; pub const STDOUT_FILENO: c_int = 1;
pub const EPERM: c_int = 1;
pub const ENOENT: c_int = 2;
pub const EINTR: c_int = 4;
pub const EAGAIN: c_int = 11;
pub const EACCES: c_int = 13;
pub const EEXIST: c_int = 17;
pub const EINVAL: c_int = 22;
pub const EPIPE: c_int = 32;
pub const EWOULDBLOCK: c_int = EAGAIN;
pub const EADDRINUSE: c_int = 98;
pub const EADDRNOTAVAIL: c_int = 99;
pub const ECONNABORTED: c_int = 103;
pub const ECONNRESET: c_int = 104;
pub const ENOTCONN: c_int = 107;
pub const ETIMEDOUT: c_int = 110;
pub const ECONNREFUSED: c_int = 111;
pub const EHOSTDOWN: c_int = 112;
#[repr(u8)] #[repr(u8)]
pub enum c_void { pub enum c_void {
__variant1, __variant1,
@ -41,7 +22,6 @@ pub type size_t = usize;
pub type ssize_t = isize; pub type ssize_t = isize;
extern "C" { extern "C" {
pub fn __errno() -> *const c_int;
pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
pub fn strlen(cs: *const c_char) -> size_t; pub fn strlen(cs: *const c_char) -> size_t;

211
src/io/error.rs

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use error; use alloc::boxed::Box;
use core::convert::Into;
use core::fmt; use core::fmt;
use core::marker::{Send, Sync};
use core::option::Option::{self, Some, None};
use core::result; use core::result;
use sys; use error;
use collections::boxed::Box;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O /// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations. /// operations.
@ -52,9 +53,7 @@ pub type Result<T> = result::Result<T, Error>;
/// ///
/// Errors mostly originate from the underlying OS, but custom instances of /// Errors mostly originate from the underlying OS, but custom instances of
/// `Error` can be created with crafted error messages and a particular value of /// `Error` can be created with crafted error messages and a particular value of
/// [`ErrorKind`]. /// `ErrorKind`.
///
/// [`ErrorKind`]: enum.ErrorKind.html
#[derive(Debug)] #[derive(Debug)]
pub struct Error { pub struct Error {
repr: Repr, repr: Repr,
@ -75,11 +74,7 @@ struct Custom {
/// ///
/// This list is intended to grow over time and it is not recommended to /// This list is intended to grow over time and it is not recommended to
/// exhaustively match against it. /// exhaustively match against it.
/// #[derive(Copy, PartialEq, Eq, Clone, Debug)]
/// It is used with the [`io::Error`] type.
///
/// [`io::Error`]: struct.Error.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[allow(deprecated)] #[allow(deprecated)]
pub enum ErrorKind { pub enum ErrorKind {
/// An entity was not found, often a file. /// An entity was not found, often a file.
@ -142,8 +137,7 @@ pub enum ErrorKind {
/// read. /// read.
UnexpectedEof, UnexpectedEof,
/// A marker variant that tells the compiler that users of this enum cannot /// Any I/O error not part of this list.
/// match it exhaustively.
#[doc(hidden)] #[doc(hidden)]
__Nonexhaustive, __Nonexhaustive,
} }
@ -182,48 +176,7 @@ impl Error {
} }
} }
/// Returns an error representing the last OS error which occurred.
///
/// This function reads the value of `errno` for the target platform (e.g.
/// `GetLastError` on Windows) and will return a corresponding instance of
/// `Error` for the error code.
///
/// # Examples
///
/// ```
/// use std::io::Error;
///
/// println!("last OS error: {:?}", Error::last_os_error());
/// ```
pub fn last_os_error() -> Error {
Error::from_raw_os_error(sys::os::errno() as i32)
}
/// Creates a new instance of an `Error` from a particular OS error code. /// Creates a new instance of an `Error` from a particular OS error code.
///
/// # Examples
///
/// On Linux:
///
/// ```
/// # if cfg!(target_os = "linux") {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(98);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
///
/// On Windows:
///
/// ```
/// # if cfg!(windows) {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(10048);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
pub fn from_raw_os_error(code: i32) -> Error { pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) } Error { repr: Repr::Os(code) }
} }
@ -233,27 +186,6 @@ impl Error {
/// If this `Error` was constructed via `last_os_error` or /// If this `Error` was constructed via `last_os_error` or
/// `from_raw_os_error`, then this function will return `Some`, otherwise /// `from_raw_os_error`, then this function will return `Some`, otherwise
/// it will return `None`. /// it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_os_error(err: &Error) {
/// if let Some(raw_os_err) = err.raw_os_error() {
/// println!("raw OS error: {:?}", raw_os_err);
/// } else {
/// println!("Not an OS error");
/// }
/// }
///
/// fn main() {
/// // Will print "raw OS error: ...".
/// print_os_error(&Error::last_os_error());
/// // Will print "Not an OS error".
/// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
pub fn raw_os_error(&self) -> Option<i32> { pub fn raw_os_error(&self) -> Option<i32> {
match self.repr { match self.repr {
Repr::Os(i) => Some(i), Repr::Os(i) => Some(i),
@ -265,27 +197,6 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {:?}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -298,63 +209,6 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
/// use std::{error, fmt};
/// use std::fmt::Display;
///
/// #[derive(Debug)]
/// struct MyError {
/// v: String,
/// }
///
/// impl MyError {
/// fn new() -> MyError {
/// MyError {
/// v: "oh no!".to_owned()
/// }
/// }
///
/// fn change_message(&mut self, new_message: &str) {
/// self.v = new_message.to_owned();
/// }
/// }
///
/// impl error::Error for MyError {
/// fn description(&self) -> &str { &self.v }
/// }
///
/// impl Display for MyError {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// write!(f, "MyError: {}", &self.v)
/// }
/// }
///
/// fn change_error(mut err: Error) -> Error {
/// if let Some(inner_err) = err.get_mut() {
/// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
/// }
/// err
/// }
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&change_error(Error::last_os_error()));
/// // Will print "Inner error: ...".
/// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
/// }
/// ```
pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -366,27 +220,6 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// if let Some(inner_err) = err.into_inner() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> { pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -395,26 +228,9 @@ impl Error {
} }
/// Returns the corresponding `ErrorKind` for this error. /// Returns the corresponding `ErrorKind` for this error.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// println!("{:?}", err.kind());
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
/// }
/// ```
pub fn kind(&self) -> ErrorKind { pub fn kind(&self) -> ErrorKind {
match self.repr { match self.repr {
Repr::Os(code) => sys::os::decode_error_kind(code), Repr::Os(_code) => ErrorKind::Other,
Repr::Custom(ref c) => c.kind, Repr::Custom(ref c) => c.kind,
} }
} }
@ -424,8 +240,7 @@ impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Repr::Os(ref code) => Repr::Os(ref code) =>
fmt.debug_struct("Os").field("code", code) fmt.debug_struct("Os").field("code", code).finish(),
.field("message", &sys::os::error_string(*code)).finish(),
Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(), Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
} }
} }
@ -435,8 +250,7 @@ impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.repr { match self.repr {
Repr::Os(code) => { Repr::Os(code) => {
let detail = sys::os::error_string(code); write!(fmt, "os error {}", code)
write!(fmt, "{} (os error {})", detail, code)
} }
Repr::Custom(ref c) => c.error.fmt(fmt), Repr::Custom(ref c) => c.error.fmt(fmt),
} }
@ -486,9 +300,10 @@ fn _assert_error_is_sync_send() {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use prelude::v1::*;
use super::{Error, ErrorKind}; use super::{Error, ErrorKind};
use error; use error;
use core::fmt; use fmt;
use sys::os::error_string; use sys::os::error_string;
#[test] #[test]

1
src/sys/mod.rs

@ -22,5 +22,4 @@ pub trait FromInner<Inner> {
fn from_inner(inner: Inner) -> Self; fn from_inner(inner: Inner) -> Self;
} }
pub mod os;
pub mod wtf8; pub mod wtf8;

78
src/sys/os.rs

@ -1,78 +0,0 @@
use libctru::libc;
use io::ErrorKind;
use collections::{str, String};
use collections::borrow::ToOwned;
use ffi::CStr;
const TMPBUF_SZ: usize = 128;
pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno as libc::c_int {
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
libc::ECONNRESET => ErrorKind::ConnectionReset,
libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
libc::EPIPE => ErrorKind::BrokenPipe,
libc::ENOTCONN => ErrorKind::NotConnected,
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
libc::EADDRINUSE => ErrorKind::AddrInUse,
libc::ENOENT => ErrorKind::NotFound,
libc::EINTR => ErrorKind::Interrupted,
libc::EINVAL => ErrorKind::InvalidInput,
libc::ETIMEDOUT => ErrorKind::TimedOut,
libc::EEXIST => ErrorKind::AlreadyExists,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,
_ => ErrorKind::Other,
}
}
extern "C" {
#[cfg(not(target_os = "dragonfly"))]
#[cfg_attr(any(target_os = "linux", target_os = "emscripten"),
link_name = "__errno_location")]
#[cfg_attr(any(target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_env = "newlib"),
link_name = "__errno")]
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
#[cfg_attr(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd"),
link_name = "__error")]
fn errno_location() -> *mut libc::c_int;
}
pub fn errno() -> i32 {
unsafe { (*errno_location()) as i32 }
}
/// Gets a detailed string description for the given error number.
pub fn error_string(errno: i32) -> String {
extern "C" {
#[cfg_attr(any(target_os = "linux", target_env = "newlib"),
link_name = "__xpg_strerror_r")]
fn strerror_r(errnum: libc::c_int,
buf: *mut libc::c_char,
buflen: libc::size_t)
-> libc::c_int;
}
let mut buf = [0 as libc::c_char; TMPBUF_SZ];
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as libc::c_int, p, buf.len() as libc::size_t) < 0 {
panic!("strerror_r failure");
}
let p = p as *const _;
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
}
}
Loading…
Cancel
Save