Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions libcc2rs/src/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,26 @@ impl FdRegistry {
raw
}

fn lookup(&self, fd: i32) -> BorrowedFd<'_> {
self.fds
.get(fd as usize)
.and_then(|slot| slot.as_ref())
.unwrap_or_else(|| panic!("ub: bad fd {fd}"))
.as_fd()
}

pub fn with_fd<R>(fd: i32, f: impl FnOnce(BorrowedFd<'_>) -> R) -> R {
FD_REGISTRY.with(|r| {
let reg = r.borrow();
let owned = reg
.fds
.get(fd as usize)
.and_then(|slot| slot.as_ref())
.unwrap_or_else(|| panic!("ub: bad fd {fd}"));
f(owned.as_fd())
f(reg.lookup(fd))
})
}

pub fn with_fds<R>(fds: &[i32], f: impl FnOnce(&[BorrowedFd<'_>]) -> R) -> R {
FD_REGISTRY.with(|r| {
let reg = r.borrow();
let borrowed: Vec<BorrowedFd<'_>> = fds.iter().map(|&fd| reg.lookup(fd)).collect();
f(&borrowed)
})
}

Expand Down
18 changes: 17 additions & 1 deletion libcc2rs/src/libc_shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,23 @@ impl Clone for Timeval {
}
}

impl ByteRepr for Timeval {}
impl ByteRepr for Timeval {
fn byte_size() -> usize {
16
}

fn to_bytes(&self, buf: &mut [u8]) {
(*self.tv_sec.borrow()).to_bytes(&mut buf[0..8]);
(*self.tv_usec.borrow()).to_bytes(&mut buf[8..16]);
}

fn from_bytes(buf: &[u8]) -> Self {
Self {
tv_sec: Rc::new(RefCell::new(i64::from_bytes(&buf[0..8]))),
tv_usec: Rc::new(RefCell::new(i64::from_bytes(&buf[8..16]))),
}
}
}

#[derive(Default)]
pub struct Timespec {
Expand Down
1 change: 1 addition & 0 deletions rules/poll/src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <poll.h>

typedef struct pollfd t1;
typedef nfds_t t2;

int f1(struct pollfd *fds, nfds_t nfds, int timeout) {
return poll(fds, nfds, timeout);
Expand Down
49 changes: 49 additions & 0 deletions rules/poll/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,52 @@ use libcc2rs::*;
fn t1() -> libcc2rs::Pollfd {
Default::default()
}

fn f1(a0: Ptr<Pollfd>, a1: u64, a2: i32) -> i32 {
let __p = a0.clone();
let __timeout = match nix::poll::PollTimeout::try_from(a2) {
Ok(__t) => __t,
Err(_) => panic!("poll: unsupported timeout {}", a2),
};
let mut __idx = Vec::new();
let mut __wanted = Vec::new();
let mut __events = Vec::new();
for __i in 0..(a1 as usize) {
let (__fd, __ev) = __p
.offset(__i)
.with(|__e| (*__e.fd.borrow(), *__e.events.borrow()));
__p.offset(__i)
.with_mut(|__e| *__e.revents.borrow_mut() = 0);
if __fd >= 0 {
__idx.push(__i);
__wanted.push(__fd);
__events.push(__ev);
}
}
FdRegistry::with_fds(&__wanted, |__b| {
let mut __pfds: Vec<nix::poll::PollFd> = __b
.iter()
.zip(&__events)
.map(|(&__fd, &__ev)| {
nix::poll::PollFd::new(__fd, nix::poll::PollFlags::from_bits_truncate(__ev))
})
.collect();
match nix::poll::poll(&mut __pfds, __timeout) {
Ok(__count) => {
for (__slot, &__i) in __pfds.iter().zip(&__idx) {
let __rev = match __slot.revents() {
Some(__r) => __r.bits(),
None => 0,
};
__p.offset(__i)
.with_mut(|__e| *__e.revents.borrow_mut() = __rev);
}
__count
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
})
}
6 changes: 5 additions & 1 deletion rules/poll/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ fn t1() -> ::libc::pollfd {
unsafe { std::mem::zeroed() }
}

unsafe fn f1(a0: *mut ::libc::pollfd, a1: u64, a2: i32) -> i32 {
fn t2() -> ::libc::nfds_t {
0
}

unsafe fn f1(a0: *mut ::libc::pollfd, a1: ::libc::nfds_t, a2: i32) -> i32 {
libc::poll(a0, a1 as ::libc::nfds_t, a2)
}
106 changes: 106 additions & 0 deletions rules/select/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,109 @@ fn f4(a0: i32, a1: Ptr<CFdSet>) -> i32 {
fn f5(a0: Ptr<CFdSet>) {
a0.with_mut(|__s| __s.zero());
}

fn f1(a0: i32, a1: Ptr<CFdSet>, a2: Ptr<CFdSet>, a3: Ptr<CFdSet>, a4: Ptr<Timeval>) -> i32 {
let __rp = a1.clone();
let __wp = a2.clone();
let __ep = a3.clone();
let __tp = a4.clone();
let __r_fds: Vec<i32> = match __rp.is_null() {
true => Vec::new(),
false => __rp.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
};
let __w_fds: Vec<i32> = match __wp.is_null() {
true => Vec::new(),
false => __wp.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
};
let __e_fds: Vec<i32> = match __ep.is_null() {
true => Vec::new(),
false => __ep.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
};
let mut __wanted = Vec::new();
__wanted.extend(&__r_fds);
__wanted.extend(&__w_fds);
__wanted.extend(&__e_fds);
FdRegistry::with_fds(&__wanted, |__b| {
let __rn = __r_fds.len();
let __wn = __w_fds.len();
let mut __rs = nix::sys::select::FdSet::new();
let mut __ws = nix::sys::select::FdSet::new();
let mut __es = nix::sys::select::FdSet::new();
for __bfd in &__b[..__rn] {
__rs.insert(*__bfd);
}
for __bfd in &__b[__rn..__rn + __wn] {
__ws.insert(*__bfd);
}
for __bfd in &__b[__rn + __wn..] {
__es.insert(*__bfd);
}
let mut __tv = match __tp.is_null() {
true => None,
false => Some(__tp.with(|__t| {
nix::sys::time::TimeVal::new(*__t.tv_sec.borrow() as _, *__t.tv_usec.borrow() as _)
})),
};
match nix::sys::select::select(
a0,
match __rp.is_null() {
true => None,
false => Some(&mut __rs),
},
match __wp.is_null() {
true => None,
false => Some(&mut __ws),
},
match __ep.is_null() {
true => None,
false => Some(&mut __es),
},
__tv.as_mut(),
) {
Ok(__n) => {
if !__rp.is_null() {
__rp.with_mut(|__s| {
__s.zero();
for (__fd, __bfd) in __r_fds.iter().zip(&__b[..__rn]) {
if __rs.contains(*__bfd) {
__s.set(*__fd);
}
}
});
}
if !__wp.is_null() {
__wp.with_mut(|__s| {
__s.zero();
for (__fd, __bfd) in __w_fds.iter().zip(&__b[__rn..__rn + __wn]) {
if __ws.contains(*__bfd) {
__s.set(*__fd);
}
}
});
}
if !__ep.is_null() {
__ep.with_mut(|__s| {
__s.zero();
for (__fd, __bfd) in __e_fds.iter().zip(&__b[__rn + __wn..]) {
if __es.contains(*__bfd) {
__s.set(*__fd);
}
}
});
}
match (__tp.is_null(), __tv.as_ref()) {
(false, Some(__t)) => __tp.with_mut(|__dst| {
*__dst.tv_sec.borrow_mut() = __t.tv_sec() as i64;
*__dst.tv_usec.borrow_mut() = __t.tv_usec() as i64;
}),
_ => {}
}
__n
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
})
}
131 changes: 131 additions & 0 deletions tests/unit/out/refcount/poll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let fds: Value<Box<[i32]>> = Rc::new(RefCell::new(
(0..2).map(|_| <i32>::default()).collect::<Box<[i32]>>(),
));
assert!(
(((match nix::unistd::pipe() {
Ok((__r, __w)) => {
let __fds = (fds.as_pointer() as Ptr<i32>).clone();
__fds.write(FdRegistry::register(__r));
__fds.offset(1).write(FdRegistry::register(__w));
0
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
} == 0) as i32)
!= 0)
);
assert!(
(((match FdRegistry::with_fd((*fds.borrow())[(1) as usize], |__fd| {
Ptr::from_string_literal(b"x")
.to_any()
.reinterpret_cast::<u8>()
.with_slice(1_usize, |__buf| nix::unistd::write(__fd, __buf))
}) {
Ok(__n) => __n as isize,
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
} == 1_isize) as i32)
!= 0)
);
let pfd: Value<Box<[libcc2rs::Pollfd]>> = Rc::new(RefCell::new(
(0..2)
.map(|_| Default::default())
.collect::<Box<[libcc2rs::Pollfd]>>(),
));
(*(*pfd.borrow())[(0) as usize].fd.borrow_mut()) = (*fds.borrow())[(0) as usize];
(*(*pfd.borrow())[(0) as usize].events.borrow_mut()) = 1_i16;
(*(*pfd.borrow())[(0) as usize].revents.borrow_mut()) = 0_i16;
(*(*pfd.borrow())[(1) as usize].fd.borrow_mut()) = -1_i32;
(*(*pfd.borrow())[(1) as usize].events.borrow_mut()) = 1_i16;
(*(*pfd.borrow())[(1) as usize].revents.borrow_mut()) = 42_i16;
assert!(
((({
let __p = (pfd.as_pointer() as Ptr<libcc2rs::Pollfd>).clone();
let __timeout = match nix::poll::PollTimeout::try_from(0) {
Ok(__t) => __t,
Err(_) => panic!("poll: unsupported timeout {}", 0),
};
let mut __idx = Vec::new();
let mut __wanted = Vec::new();
let mut __events = Vec::new();
for __i in 0..((2 as ::libc::nfds_t) as usize) {
let (__fd, __ev) = __p
.offset(__i)
.with(|__e| (*__e.fd.borrow(), *__e.events.borrow()));
__p.offset(__i)
.with_mut(|__e| *__e.revents.borrow_mut() = 0);
if __fd >= 0 {
__idx.push(__i);
__wanted.push(__fd);
__events.push(__ev);
}
}
FdRegistry::with_fds(&__wanted, |__b| {
let mut __pfds: Vec<nix::poll::PollFd> = __b
.iter()
.zip(&__events)
.map(|(&__fd, &__ev)| {
nix::poll::PollFd::new(__fd, nix::poll::PollFlags::from_bits_truncate(__ev))
})
.collect();
match nix::poll::poll(&mut __pfds, __timeout) {
Ok(__count) => {
for (__slot, &__i) in __pfds.iter().zip(&__idx) {
let __rev = match __slot.revents() {
Some(__r) => __r.bits(),
None => 0,
};
__p.offset(__i)
.with_mut(|__e| *__e.revents.borrow_mut() = __rev);
}
__count
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
})
} == 1) as i32)
!= 0)
);
assert!(
((((((*(*pfd.borrow())[(0) as usize].revents.borrow()) as i32) & 1) != 0) as i32) != 0)
);
assert!((((((*(*pfd.borrow())[(1) as usize].revents.borrow()) as i32) == 0) as i32) != 0));
let ch: Value<u8> = <Value<u8>>::default();
assert!(
(((match FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
((ch.as_pointer()) as Ptr<u8>)
.to_any()
.reinterpret_cast::<u8>()
.with_slice_mut(1_usize, |__buf| nix::unistd::read(__fd, __buf))
}) {
Ok(__n) => __n as isize,
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
} == 1_isize) as i32)
!= 0)
);
assert!((((FdRegistry::close((*fds.borrow())[(0) as usize]) == 0) as i32) != 0));
assert!((((FdRegistry::close((*fds.borrow())[(1) as usize]) == 0) as i32) != 0));
return 0;
}
Loading
Loading