fix errno = 0 and introduce macro 'try_libc'

This commit is contained in:
WangRunji 2019-04-23 00:36:48 +08:00
parent 141094e95e
commit 1326924dbb
5 changed files with 170 additions and 90 deletions

@ -81,19 +81,111 @@ pub enum Errno {
ENOLCK = 37,
ENOSYS = 38,
ENOTEMPTY = 39,
ELOOP = 40,
EWOULDBLOCK = 41,
ENOMSG = 42,
EIDRM = 43,
ECHRNG = 44,
EL2NSYNC = 45,
EL3HLT = 46,
EL3RST = 47,
ELNRNG = 48,
EUNATCH = 49,
ENOCSI = 50,
EL2HLT = 51,
EBADE = 52,
EBADR = 53,
EXFULL = 54,
ENOANO = 55,
EBADRQC = 56,
EBADSLT = 57,
EDEADLOCK = 58,
EBFONT = 59,
ENOSTR = 60,
ENODATA = 61,
ETIME = 62,
ENOSR = 63,
ENONET = 64,
ENOPKG = 65,
EREMOTE = 66,
ENOLINK = 67,
EADV = 68,
ESRMNT = 69,
ECOMM = 70,
EPROTO = 71,
EMULTIHOP = 72,
EDOTDOT = 73,
EBADMSG = 74,
EOVERFLOW = 75,
ENOTUNIQ = 76,
EBADFD = 77,
EREMCHG = 78,
ELIBACC = 79,
ELIBBAD = 80,
ELIBSCN = 81,
ELIBMAX = 82,
ELIBEXEC = 83,
EILSEQ = 84,
ERESTART = 85,
ESTRPIPE = 86,
EUSERS = 87,
ENOTSOCK = 88,
EDESTADDRREQ = 89,
EMSGSIZE = 90,
EPROTOTYPE = 91,
ENOPROTOOPT = 92,
EPROTONOSUPPORT = 93,
ESOCKTNOSUPPORT = 94,
EOPNOTSUPP = 95,
EPFNOSUPPORT = 96,
EAFNOSUPPORT = 97,
EADDRINUSE = 98,
EADDRNOTAVAIL = 99,
ENETDOWN = 100,
ENETUNREACH = 101,
ENETRESET = 102,
ECONNABORTED = 103,
ECONNRESET = 104,
ENOBUFS = 105,
EISCONN = 106,
ENOTCONN = 107,
ESHUTDOWN = 108,
ETOOMANYREFS = 109,
ETIMEDOUT = 110,
ECONNREFUSED = 111,
EHOSTDOWN = 112,
EHOSTUNREACH = 113,
EALREADY = 114,
EINPROGRESS = 115,
ESTALE = 116,
EUCLEAN = 117,
ENOTNAM = 118,
ENAVAIL = 119,
EISNAM = 120,
EREMOTEIO = 121,
EDQUOT = 122,
ENOMEDIUM = 123,
EMEDIUMTYPE = 124,
ECANCELED = 125,
ENOKEY = 126,
EKEYEXPIRED = 127,
EKEYREVOKED = 128,
EKEYREJECTED = 129,
EOWNERDEAD = 130,
ENOTRECOVERABLE = 131,
ERFKILL = 132,
EHWPOISON = 133,
}
impl Errno {
pub fn as_retval(&self) -> i32 {
-(*self as i32)
}
pub fn from_retval(ret: i32) -> Self {
let ret = if ret <= 0 && ret >= -39 {
(-ret) as u8
} else {
0
};
unsafe { core::mem::transmute(ret) }
pub fn from_errno(mut errno: i32) -> Self {
if errno < 0 || errno > 133 {
errno = 0;
}
unsafe { core::mem::transmute(errno as u8) }
}
}

@ -57,11 +57,7 @@ pub fn do_select(
Some(tv) => (tv.tv_sec * 1000 + tv.tv_usec / 1000) as i32,
};
let ret = unsafe { libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout));
// convert fd back and write fdset
readfds.clear();
@ -96,14 +92,9 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize, Erro
let socket = file_ref.as_socket()?;
poll.fd = socket.fd();
}
let ret = unsafe { libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout) };
let ret = try_libc!(libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout));
// recover fd ?
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(ret as usize)
}
Ok(ret as usize)
}
pub fn do_epoll_create1(flags: c_int) -> Result<FileDesc, Error> {
@ -211,10 +202,7 @@ struct EpollFileInner {
impl EpollFileInner {
/// Create a new Linux epoll file descriptor
pub fn new() -> Result<Self, Error> {
let ret = unsafe { libc::ocall::epoll_create1(0) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::epoll_create1(0));
Ok(EpollFileInner { epoll_fd: ret })
}
@ -225,10 +213,7 @@ impl EpollFileInner {
event: *const libc::epoll_event,
) -> Result<(), Error> {
let ret =
unsafe { libc::ocall::epoll_ctl(self.epoll_fd, op, host_fd as c_int, event as *mut _) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
try_libc!(libc::ocall::epoll_ctl(self.epoll_fd, op, host_fd as c_int, event as *mut _));
Ok(())
}
@ -239,17 +224,14 @@ impl EpollFileInner {
events: &mut [libc::epoll_event],
timeout: c_int,
) -> Result<usize, Error> {
let ret = unsafe {
let ret = try_libc!(
libc::ocall::epoll_wait(
self.epoll_fd,
events.as_mut_ptr(),
events.len() as c_int,
timeout,
)
};
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
);
Ok(ret as usize)
}
}

@ -9,12 +9,8 @@ pub struct SocketFile {
impl SocketFile {
pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
let ret = unsafe { libc::ocall::socket(domain, socket_type, protocol) };
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(SocketFile { fd: ret })
}
let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol));
Ok(SocketFile { fd: ret })
}
pub fn accept(
@ -23,12 +19,8 @@ impl SocketFile {
addr_len: *mut libc::socklen_t,
flags: c_int,
) -> Result<Self, Error> {
let ret = unsafe { libc::ocall::accept4(self.fd, addr, addr_len, flags) };
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(SocketFile { fd: ret })
}
let ret = try_libc!(libc::ocall::accept4(self.fd, addr, addr_len, flags));
Ok(SocketFile { fd: ret })
}
pub fn fd(&self) -> c_int {
@ -40,28 +32,21 @@ impl Drop for SocketFile {
fn drop(&mut self) {
let ret = unsafe { libc::ocall::close(self.fd) };
if ret < 0 {
warn!("socket (host fd: {}) close failed", self.fd);
let errno = unsafe { libc::errno() };
warn!("socket (host fd: {}) close failed: errno = {}", self.fd, errno);
}
}
}
impl File for SocketFile {
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let ret = unsafe { libc::ocall::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(ret as usize)
}
let ret = try_libc!(libc::ocall::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()));
Ok(ret as usize)
}
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
let ret = unsafe { libc::ocall::write(self.fd, buf.as_ptr() as *const c_void, buf.len()) };
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(ret as usize)
}
let ret = try_libc!(libc::ocall::write(self.fd, buf.as_ptr() as *const c_void, buf.len()));
Ok(ret as usize)
}
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {

@ -35,7 +35,7 @@ macro_rules! debug_trace {
}
macro_rules! errno {
($errno: expr, $msg: expr) => {{
($errno: ident, $msg: expr) => {{
println!(
"ERROR: {} ({}, line {} in file {})",
$errno,
@ -47,6 +47,25 @@ macro_rules! errno {
}};
}
// return Err(errno) if libc return -1
macro_rules! try_libc {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret == -1 {
let errno = unsafe { libc::errno() };
// println will cause libc ocall and overwrite errno
println!(
"ERROR from libc: {} (line {} in file {})",
errno,
line!(),
file!()
);
return Err(Error::new(Errno::from_errno(errno), "libc error"));
}
ret
}};
}
pub fn align_up(addr: usize, align: usize) -> usize {
(addr + (align - 1)) / align * align
}

@ -941,10 +941,7 @@ fn do_connect(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::connect(socket.fd(), addr, addr_len) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
Ok(ret as isize)
}
@ -977,10 +974,7 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::shutdown(socket.fd(), how) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
Ok(ret as isize)
}
@ -995,10 +989,7 @@ fn do_bind(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::bind(socket.fd(), addr, addr_len) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
Ok(ret as isize)
}
@ -1009,10 +1000,7 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::listen(socket.fd(), backlog) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
Ok(ret as isize)
}
@ -1032,10 +1020,13 @@ fn do_setsockopt(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::setsockopt(socket.fd(), level, optname, optval, optlen) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::setsockopt(
socket.fd(),
level,
optname,
optval,
optlen
));
Ok(ret as isize)
}
@ -1055,10 +1046,13 @@ fn do_getsockopt(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::getsockopt(socket.fd(), level, optname, optval, optlen) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::getsockopt(
socket.fd(),
level,
optname,
optval,
optlen
));
Ok(ret as isize)
}
@ -1079,10 +1073,14 @@ fn do_sendto(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::sendto(socket.fd(), base, len, flags, addr, addr_len) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::sendto(
socket.fd(),
base,
len,
flags,
addr,
addr_len
));
Ok(ret as isize)
}
@ -1103,10 +1101,14 @@ fn do_recvfrom(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::recvfrom(socket.fd(), base, len, flags, addr, addr_len) };
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
let ret = try_libc!(libc::ocall::recvfrom(
socket.fd(),
base,
len,
flags,
addr,
addr_len
));
Ok(ret as isize)
}