diff --git a/libcc2rs/src/libc_shims/termios.rs b/libcc2rs/src/libc_shims/termios.rs index 66e3d9db..5d96f474 100644 --- a/libcc2rs/src/libc_shims/termios.rs +++ b/libcc2rs/src/libc_shims/termios.rs @@ -48,6 +48,68 @@ impl Clone for Termios { impl ByteRepr for Termios {} +impl Termios { + #[allow(clippy::unnecessary_cast)] + pub fn from_libc(t: &::libc::termios) -> Self { + let s = Self::default(); + *s.c_iflag.borrow_mut() = t.c_iflag as u32; + *s.c_oflag.borrow_mut() = t.c_oflag as u32; + *s.c_cflag.borrow_mut() = t.c_cflag as u32; + *s.c_lflag.borrow_mut() = t.c_lflag as u32; + #[cfg(target_os = "linux")] + { + *s.c_line.borrow_mut() = t.c_line; + } + { + let mut cc = s.c_cc.borrow_mut(); + let n = t.c_cc.len().min(cc.len()); + cc[..n].copy_from_slice(&t.c_cc[..n]); + } + *s.c_ispeed.borrow_mut() = t.c_ispeed as u32; + *s.c_ospeed.borrow_mut() = t.c_ospeed as u32; + s + } + + #[cfg(target_os = "linux")] + pub fn to_libc(&self) -> ::libc::termios { + ::libc::termios { + c_iflag: *self.c_iflag.borrow(), + c_oflag: *self.c_oflag.borrow(), + c_cflag: *self.c_cflag.borrow(), + c_lflag: *self.c_lflag.borrow(), + c_line: *self.c_line.borrow(), + c_cc: { + let mut cc = [0u8; 32]; + let src = self.c_cc.borrow(); + let n = src.len().min(cc.len()); + cc[..n].copy_from_slice(&src[..n]); + cc + }, + c_ispeed: *self.c_ispeed.borrow(), + c_ospeed: *self.c_ospeed.borrow(), + } + } + + #[cfg(target_os = "macos")] + pub fn to_libc(&self) -> ::libc::termios { + ::libc::termios { + c_iflag: *self.c_iflag.borrow() as u64, + c_oflag: *self.c_oflag.borrow() as u64, + c_cflag: *self.c_cflag.borrow() as u64, + c_lflag: *self.c_lflag.borrow() as u64, + c_cc: { + let mut cc = [0u8; 20]; + let src = self.c_cc.borrow(); + let n = src.len().min(cc.len()); + cc[..n].copy_from_slice(&src[..n]); + cc + }, + c_ispeed: *self.c_ispeed.borrow() as u64, + c_ospeed: *self.c_ospeed.borrow() as u64, + } + } +} + #[derive(Default)] pub struct Winsize { pub ws_row: Value, diff --git a/rules/stat/tgt_refcount.rs b/rules/stat/tgt_refcount.rs index bf577f5c..636e87c0 100644 --- a/rules/stat/tgt_refcount.rs +++ b/rules/stat/tgt_refcount.rs @@ -20,6 +20,19 @@ fn f1(a0: Ptr, a1: Ptr) -> i32 { } } +fn f2(a0: i32, a1: Ptr) -> i32 { + match FdRegistry::with_fd(a0, |__fd| nix::sys::stat::fstat(__fd)) { + Ok(__s) => { + a1.with_mut(|__st| *__st = Stat::from_libc(&__s)); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} + fn f3(a0: Ptr, a1: ::libc::mode_t) -> i32 { match nix::unistd::mkdir( a0.to_rust_string().as_str(), diff --git a/rules/termios/tgt_refcount.rs b/rules/termios/tgt_refcount.rs index 1c5f47f6..79140e21 100644 --- a/rules/termios/tgt_refcount.rs +++ b/rules/termios/tgt_refcount.rs @@ -10,3 +10,35 @@ fn t1() -> libcc2rs::Termios { fn t2() -> libcc2rs::Winsize { Default::default() } + +fn f1(a0: i32, a1: i32, a2: Ptr) -> i32 { + let __action = match a1 { + 0 => nix::sys::termios::SetArg::TCSANOW, + 1 => nix::sys::termios::SetArg::TCSADRAIN, + 2 => nix::sys::termios::SetArg::TCSAFLUSH, + __a => panic!("tcsetattr: unsupported action {__a}"), + }; + let __t = nix::sys::termios::Termios::from(a2.with(|__src| __src.to_libc())); + match FdRegistry::with_fd(a0, |__fd| { + nix::sys::termios::tcsetattr(__fd, __action, &__t) + }) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} + +fn f2(a0: i32, a1: Ptr) -> i32 { + match FdRegistry::with_fd(a0, |__fd| nix::sys::termios::tcgetattr(__fd)) { + Ok(__t) => { + a1.with_mut(|__dst| *__dst = Termios::from_libc(&__t.into())); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} diff --git a/tests/unit/fstat.c b/tests/unit/fstat.c new file mode 100644 index 00000000..a879e16d --- /dev/null +++ b/tests/unit/fstat.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +int main(void) { + const char *path = "/tmp/cpp2rust_fstat_test.tmp"; + int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); + assert(fd >= 0); + assert(write(fd, "hello", 5) == 5); + struct stat st; + assert(fstat(fd, &st) == 0); + assert(st.st_size == 5); + assert(close(fd) == 0); + assert(unlink(path) == 0); + return 0; +} diff --git a/tests/unit/out/refcount/fstat.rs b/tests/unit/out/refcount/fstat.rs new file mode 100644 index 00000000..207cfb95 --- /dev/null +++ b/tests/unit/out/refcount/fstat.rs @@ -0,0 +1,78 @@ +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 path: Value> = Rc::new(RefCell::new(Ptr::from_string_literal( + b"/tmp/cpp2rust_fstat_test.tmp", + ))); + let fd: Value = Rc::new(RefCell::new({ + let __mode = match &[(420).into()].first() { + Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t), + None => nix::sys::stat::Mode::empty(), + }; + match nix::fcntl::open( + (*path.borrow()).to_rust_string().as_str(), + nix::fcntl::OFlag::from_bits_retain( + ((::libc::O_RDWR | ::libc::O_CREAT) | ::libc::O_TRUNC), + ), + __mode, + ) { + Ok(__ofd) => FdRegistry::register(__ofd), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } + })); + assert!(((((*fd.borrow()) >= 0) as i32) != 0)); + assert!( + (((match FdRegistry::with_fd((*fd.borrow()), |__fd| { + Ptr::from_string_literal(b"hello") + .to_any() + .reinterpret_cast::() + .with_slice(5_usize, |__buf| nix::unistd::write(__fd, __buf)) + }) { + Ok(__n) => __n as isize, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == 5_isize) as i32) + != 0) + ); + let st: Value = Rc::new(RefCell::new(Default::default())); + assert!( + (((match FdRegistry::with_fd((*fd.borrow()), |__fd| nix::sys::stat::fstat(__fd)) { + Ok(__s) => { + (st.as_pointer()).with_mut(|__st| *__st = Stat::from_libc(&__s)); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == 0) as i32) + != 0) + ); + assert!(((((*(*st.borrow()).st_size.borrow()) == 5_i64) as i32) != 0)); + assert!((((FdRegistry::close((*fd.borrow())) == 0) as i32) != 0)); + assert!( + (((match nix::unistd::unlink((*path.borrow()).to_rust_string().as_str()) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == 0) as i32) + != 0) + ); + return 0; +} diff --git a/tests/unit/out/refcount/termios.rs b/tests/unit/out/refcount/termios.rs new file mode 100644 index 00000000..5371707f --- /dev/null +++ b/tests/unit/out/refcount/termios.rs @@ -0,0 +1,84 @@ +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 path: Value> = Rc::new(RefCell::new(Ptr::from_string_literal( + b"/tmp/cpp2rust_termios_test.tmp", + ))); + let fd: Value = Rc::new(RefCell::new({ + let __mode = match &[(420).into()].first() { + Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t), + None => nix::sys::stat::Mode::empty(), + }; + match nix::fcntl::open( + (*path.borrow()).to_rust_string().as_str(), + nix::fcntl::OFlag::from_bits_retain( + ((::libc::O_RDWR | ::libc::O_CREAT) | ::libc::O_TRUNC), + ), + __mode, + ) { + Ok(__ofd) => FdRegistry::register(__ofd), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } + })); + assert!(((((*fd.borrow()) >= 0) as i32) != 0)); + let tio: Value = Rc::new(RefCell::new(Default::default())); + assert!( + (((match FdRegistry::with_fd((*fd.borrow()), |__fd| nix::sys::termios::tcgetattr(__fd)) { + Ok(__t) => { + (tio.as_pointer()).with_mut(|__dst| *__dst = Termios::from_libc(&__t.into())); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == -1_i32) as i32) + != 0) + ); + assert!( + ((({ + let __action = match 0 { + 0 => nix::sys::termios::SetArg::TCSANOW, + 1 => nix::sys::termios::SetArg::TCSADRAIN, + 2 => nix::sys::termios::SetArg::TCSAFLUSH, + __a => panic!("tcsetattr: unsupported action {__a}"), + }; + let __t = + nix::sys::termios::Termios::from((tio.as_pointer()).with(|__src| __src.to_libc())); + match FdRegistry::with_fd((*fd.borrow()), |__fd| { + nix::sys::termios::tcsetattr(__fd, __action, &__t) + }) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } + } == -1_i32) as i32) + != 0) + ); + assert!((((FdRegistry::close((*fd.borrow())) == 0) as i32) != 0)); + assert!( + (((match nix::unistd::unlink((*path.borrow()).to_rust_string().as_str()) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == 0) as i32) + != 0) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fstat.rs b/tests/unit/out/unsafe/fstat.rs new file mode 100644 index 00000000..9a6ba69c --- /dev/null +++ b/tests/unit/out/unsafe/fstat.rs @@ -0,0 +1,39 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut path: *const libc::c_char = + (c"/tmp/cpp2rust_fstat_test.tmp".as_ptr().cast_mut()).cast_const(); + let mut fd: i32 = (unsafe { + libc::open( + path as *const i8, + (((::libc::O_RDWR) | (::libc::O_CREAT)) | (::libc::O_TRUNC)) as i32, + (420), + ) + }); + assert!(((((fd) >= (0)) as i32) != 0)); + assert!( + ((((libc::write( + fd, + (c"hello".as_ptr().cast_mut() as *const libc::c_char as *const ::libc::c_void), + 5_usize + )) == (5_isize)) as i32) + != 0) + ); + let mut st: ::libc::stat = unsafe { std::mem::zeroed() }; + assert!(((((libc::fstat(fd, (&mut st as *mut ::libc::stat))) == (0)) as i32) != 0)); + assert!(((((st.st_size) == (5_i64)) as i32) != 0)); + assert!(((((libc::close(fd)) == (0)) as i32) != 0)); + assert!(((((libc::unlink(path)) == (0)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/termios.rs b/tests/unit/out/unsafe/termios.rs new file mode 100644 index 00000000..a0659541 --- /dev/null +++ b/tests/unit/out/unsafe/termios.rs @@ -0,0 +1,37 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut path: *const libc::c_char = + (c"/tmp/cpp2rust_termios_test.tmp".as_ptr().cast_mut()).cast_const(); + let mut fd: i32 = (unsafe { + libc::open( + path as *const i8, + (((::libc::O_RDWR) | (::libc::O_CREAT)) | (::libc::O_TRUNC)) as i32, + (420), + ) + }); + assert!(((((fd) >= (0)) as i32) != 0)); + let mut tio: ::libc::termios = unsafe { std::mem::zeroed() }; + assert!( + ((((libc::tcgetattr(fd, (&mut tio as *mut ::libc::termios))) == (-1_i32)) as i32) != 0) + ); + assert!( + ((((libc::tcsetattr(fd, 0, (&mut tio as *mut ::libc::termios).cast_const())) == (-1_i32)) + as i32) + != 0) + ); + assert!(((((libc::close(fd)) == (0)) as i32) != 0)); + assert!(((((libc::unlink(path)) == (0)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/termios.c b/tests/unit/termios.c new file mode 100644 index 00000000..79bd869e --- /dev/null +++ b/tests/unit/termios.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +int main(void) { + const char *path = "/tmp/cpp2rust_termios_test.tmp"; + int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); + assert(fd >= 0); + struct termios tio; + assert(tcgetattr(fd, &tio) == -1); + assert(tcsetattr(fd, TCSANOW, &tio) == -1); + assert(close(fd) == 0); + assert(unlink(path) == 0); + return 0; +}