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, ENOLCK = 37,
ENOSYS = 38, ENOSYS = 38,
ENOTEMPTY = 39, 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 { impl Errno {
pub fn as_retval(&self) -> i32 { pub fn as_retval(&self) -> i32 {
-(*self as i32) -(*self as i32)
} }
pub fn from_retval(ret: i32) -> Self { pub fn from_errno(mut errno: i32) -> Self {
let ret = if ret <= 0 && ret >= -39 { if errno < 0 || errno > 133 {
(-ret) as u8 errno = 0;
} else { }
0 unsafe { core::mem::transmute(errno as u8) }
};
unsafe { core::mem::transmute(ret) }
} }
} }

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

@ -9,13 +9,9 @@ pub struct SocketFile {
impl SocketFile { impl SocketFile {
pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<Self, Error> { 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) }; let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol));
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(SocketFile { fd: ret }) Ok(SocketFile { fd: ret })
} }
}
pub fn accept( pub fn accept(
&self, &self,
@ -23,13 +19,9 @@ impl SocketFile {
addr_len: *mut libc::socklen_t, addr_len: *mut libc::socklen_t,
flags: c_int, flags: c_int,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let ret = unsafe { libc::ocall::accept4(self.fd, addr, addr_len, flags) }; let ret = try_libc!(libc::ocall::accept4(self.fd, addr, addr_len, flags));
if ret < 0 {
errno!(Errno::from_retval(unsafe { libc::errno() }), "")
} else {
Ok(SocketFile { fd: ret }) Ok(SocketFile { fd: ret })
} }
}
pub fn fd(&self) -> c_int { pub fn fd(&self) -> c_int {
self.fd self.fd
@ -40,29 +32,22 @@ impl Drop for SocketFile {
fn drop(&mut self) { fn drop(&mut self) {
let ret = unsafe { libc::ocall::close(self.fd) }; let ret = unsafe { libc::ocall::close(self.fd) };
if ret < 0 { 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 { impl File for SocketFile {
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { 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()) }; let ret = try_libc!(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) Ok(ret as usize)
} }
}
fn write(&self, buf: &[u8]) -> Result<usize, Error> { 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()) }; let ret = try_libc!(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) Ok(ret as usize)
} }
}
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> { fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
self.read(buf) self.read(buf)

@ -35,7 +35,7 @@ macro_rules! debug_trace {
} }
macro_rules! errno { macro_rules! errno {
($errno: expr, $msg: expr) => {{ ($errno: ident, $msg: expr) => {{
println!( println!(
"ERROR: {} ({}, line {} in file {})", "ERROR: {} ({}, line {} in file {})",
$errno, $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 { pub fn align_up(addr: usize, align: usize) -> usize {
(addr + (align - 1)) / align * align (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 file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::connect(socket.fd(), addr, addr_len) }; let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
Ok(ret as isize) 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 file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::shutdown(socket.fd(), how) }; let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
Ok(ret as isize) Ok(ret as isize)
} }
@ -995,10 +989,7 @@ fn do_bind(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::bind(socket.fd(), addr, addr_len) }; let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
Ok(ret as isize) 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 file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::listen(socket.fd(), backlog) }; let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
if ret < 0 {
return errno!(Errno::from_retval(unsafe { libc::errno() }), "");
}
Ok(ret as isize) Ok(ret as isize)
} }
@ -1032,10 +1020,13 @@ fn do_setsockopt(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::setsockopt(socket.fd(), level, optname, optval, optlen) }; let ret = try_libc!(libc::ocall::setsockopt(
if ret < 0 { socket.fd(),
return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); level,
} optname,
optval,
optlen
));
Ok(ret as isize) Ok(ret as isize)
} }
@ -1055,10 +1046,13 @@ fn do_getsockopt(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::getsockopt(socket.fd(), level, optname, optval, optlen) }; let ret = try_libc!(libc::ocall::getsockopt(
if ret < 0 { socket.fd(),
return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); level,
} optname,
optval,
optlen
));
Ok(ret as isize) Ok(ret as isize)
} }
@ -1079,10 +1073,14 @@ fn do_sendto(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::sendto(socket.fd(), base, len, flags, addr, addr_len) }; let ret = try_libc!(libc::ocall::sendto(
if ret < 0 { socket.fd(),
return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); base,
} len,
flags,
addr,
addr_len
));
Ok(ret as isize) Ok(ret as isize)
} }
@ -1103,10 +1101,14 @@ fn do_recvfrom(
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; let socket = file_ref.as_socket()?;
let ret = unsafe { libc::ocall::recvfrom(socket.fd(), base, len, flags, addr, addr_len) }; let ret = try_libc!(libc::ocall::recvfrom(
if ret < 0 { socket.fd(),
return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); base,
} len,
flags,
addr,
addr_len
));
Ok(ret as isize) Ok(ret as isize)
} }