diff --git a/c-scape/src/io/epoll.rs b/c-scape/src/io/epoll.rs index 660b6089..2e1ff257 100644 --- a/c-scape/src/io/epoll.rs +++ b/c-scape/src/io/epoll.rs @@ -1,5 +1,5 @@ -use rustix::fd::{FromRawFd, IntoRawFd, OwnedFd}; -use rustix::io::epoll::{CreateFlags, Epoll, Owning}; +use rustix::fd::{BorrowedFd, IntoRawFd}; +use rustix::io::epoll::{epoll_add, epoll_del, epoll_mod, CreateFlags, EventFlags, EventVec}; use errno::{set_errno, Errno}; use libc::c_int; @@ -24,7 +24,7 @@ unsafe extern "C" fn epoll_create1(flags: c_int) -> c_int { let flags = CreateFlags::from_bits(flags as _).unwrap(); - match convert_res(Epoll::new(flags, Owning::::new())) { + match convert_res(rustix::io::epoll::epoll_create(flags)) { Some(epoll) => epoll.into_raw_fd(), None => -1, } @@ -38,27 +38,68 @@ unsafe extern "C" fn epoll_ctl( fd: c_int, event: *mut libc::epoll_event, ) -> c_int { - let epoll = Epoll::from_raw_fd(epfd); + libc!(libc::epoll_ctl(epfd, op, fd, event)); - // let res = match op { - // libc::EPOLL_CTL_ADD => epoll.add(), - // }; + let epfd = BorrowedFd::borrow_raw(epfd); + let fd = BorrowedFd::borrow_raw(fd); + let res = match op { + libc::EPOLL_CTL_ADD => { + let libc::epoll_event { events, r#u64 } = event.read(); + let events = EventFlags::from_bits(events).unwrap(); + epoll_add(epfd, fd, r#u64, events) + } + libc::EPOLL_CTL_MOD => { + let libc::epoll_event { events, r#u64 } = event.read(); + let events = EventFlags::from_bits(events).unwrap(); + epoll_mod(epfd, fd, r#u64, events) + } + libc::EPOLL_CTL_DEL => epoll_del(epfd, fd), + _ => { + set_errno(Errno(libc::EINVAL)); + return -1; + } + }; - todo!() + match convert_res(res) { + Some(()) => 0, + None => -1, + } } #[no_mangle] unsafe extern "C" fn epoll_wait( - _epfd: c_int, - _events: *mut libc::epoll_event, - _maxevents: c_int, - _timeout: c_int, + epfd: c_int, + events: *mut libc::epoll_event, + maxevents: c_int, + timeout: c_int, ) -> c_int { - libc!(libc::epoll_wait( - _epfd, - _events, - _maxevents, - _timeout - )); - unimplemented!("epoll_wait") + libc!(libc::epoll_wait(epfd, events, maxevents, timeout)); + + if maxevents <= 0 { + set_errno(Errno(libc::EINVAL)); + return -1; + } + + // TODO: We should add an `EventVec::from_raw_parts` to allow `epoll_wait` + // to write events directly into the user's buffer, rather then allocating + // and copying here. + let mut events_vec = EventVec::with_capacity(maxevents as usize); + match convert_res(rustix::io::epoll::epoll_wait( + BorrowedFd::borrow_raw(epfd), + &mut events_vec, + timeout, + )) { + Some(()) => { + let mut events = events; + for (flags, data) in events_vec.iter() { + events.write(libc::epoll_event { + events: flags.bits(), + r#u64: data, + }); + events = events.add(1); + } + events_vec.len() as c_int + } + None => -1, + } } diff --git a/c-scape/src/io/mod.rs b/c-scape/src/io/mod.rs index 283f27a1..c1612cdf 100644 --- a/c-scape/src/io/mod.rs +++ b/c-scape/src/io/mod.rs @@ -1,7 +1,7 @@ #[cfg(not(target_os = "wasi"))] mod dup; -// #[cfg(any(target_os = "android", target_os = "linux"))] -// mod epoll; +#[cfg(any(target_os = "android", target_os = "linux"))] +mod epoll; mod isatty; mod pipe; mod poll;