diff --git a/libcc2rs/src/libc_shims/dirent.rs b/libcc2rs/src/libc_shims/dirent.rs index f36bd5ad..eeb6cec5 100644 --- a/libcc2rs/src/libc_shims/dirent.rs +++ b/libcc2rs/src/libc_shims/dirent.rs @@ -25,6 +25,21 @@ impl Default for Dirent { } } +impl Dirent { + pub fn from_entry(ino: u64, name: &[u8], d_type: u8) -> Self { + let de = Dirent::default(); + *de.d_ino.borrow_mut() = ino; + *de.d_type.borrow_mut() = d_type; + { + let mut nm = de.d_name.borrow_mut(); + let n = name.len().min(nm.len() - 1); + nm[..n].copy_from_slice(&name[..n]); + nm[n] = 0; + } + de + } +} + impl Clone for Dirent { fn clone(&self) -> Self { Self { @@ -44,6 +59,29 @@ pub struct CDir { pub pos: Cell, } +impl CDir { + pub fn from_dir(dir: nix::dir::Dir) -> Self { + let mut entries: Vec<(u64, Vec, u8)> = Vec::new(); + for ent in dir.into_iter().flatten() { + let ty = match ent.file_type() { + Some(nix::dir::Type::Fifo) => ::libc::DT_FIFO, + Some(nix::dir::Type::CharacterDevice) => ::libc::DT_CHR, + Some(nix::dir::Type::Directory) => ::libc::DT_DIR, + Some(nix::dir::Type::BlockDevice) => ::libc::DT_BLK, + Some(nix::dir::Type::File) => ::libc::DT_REG, + Some(nix::dir::Type::Symlink) => ::libc::DT_LNK, + Some(nix::dir::Type::Socket) => ::libc::DT_SOCK, + None => ::libc::DT_UNKNOWN, + }; + entries.push((ent.ino(), ent.file_name().to_bytes().to_vec(), ty)); + } + Self { + entries, + pos: Cell::new(0), + } + } +} + impl ByteRepr for CDir {} impl ByteRepr for ::libc::dirent {} diff --git a/libcc2rs/src/libc_shims/pwd.rs b/libcc2rs/src/libc_shims/pwd.rs index dd76bde2..a18be065 100644 --- a/libcc2rs/src/libc_shims/pwd.rs +++ b/libcc2rs/src/libc_shims/pwd.rs @@ -16,6 +16,25 @@ pub struct Passwd { pub pw_shell: Value>, } +impl Passwd { + pub fn from_user(u: &nix::unistd::User) -> Self { + let mk = |s: &[u8]| -> Value> { + let mut v = s.to_vec(); + v.push(0); + Rc::new(RefCell::new(Ptr::alloc_array(v.into_boxed_slice()))) + }; + Self { + pw_name: mk(u.name.as_bytes()), + pw_passwd: mk(u.passwd.as_bytes()), + pw_uid: Rc::new(RefCell::new(u.uid.as_raw())), + pw_gid: Rc::new(RefCell::new(u.gid.as_raw())), + pw_gecos: mk(u.gecos.as_bytes()), + pw_dir: mk(u.dir.as_os_str().as_encoded_bytes()), + pw_shell: mk(u.shell.as_os_str().as_encoded_bytes()), + } + } +} + impl Clone for Passwd { fn clone(&self) -> Self { Self { diff --git a/libcc2rs/src/libc_shims/stat.rs b/libcc2rs/src/libc_shims/stat.rs index b73b6acb..792bff49 100644 --- a/libcc2rs/src/libc_shims/stat.rs +++ b/libcc2rs/src/libc_shims/stat.rs @@ -22,6 +22,27 @@ pub struct Stat { pub st_ctime: Value, } +impl Stat { + #[allow(clippy::unnecessary_cast)] + pub fn from_libc(s: &::libc::stat) -> Self { + Self { + st_dev: Rc::new(RefCell::new(s.st_dev as u64)), + st_ino: Rc::new(RefCell::new(s.st_ino as u64)), + st_nlink: Rc::new(RefCell::new(s.st_nlink as u64)), + st_mode: Rc::new(RefCell::new(s.st_mode as u32)), + st_uid: Rc::new(RefCell::new(s.st_uid)), + st_gid: Rc::new(RefCell::new(s.st_gid)), + st_rdev: Rc::new(RefCell::new(s.st_rdev as u64)), + st_size: Rc::new(RefCell::new(s.st_size as i64)), + st_blksize: Rc::new(RefCell::new(s.st_blksize as i64)), + st_blocks: Rc::new(RefCell::new(s.st_blocks as i64)), + st_atime: Rc::new(RefCell::new(s.st_atime as i64)), + st_mtime: Rc::new(RefCell::new(s.st_mtime as i64)), + st_ctime: Rc::new(RefCell::new(s.st_ctime as i64)), + } + } +} + impl Clone for Stat { fn clone(&self) -> Self { Self { diff --git a/rules/cstdlib/tgt_refcount.rs b/rules/cstdlib/tgt_refcount.rs index 5c52137d..cb04f452 100644 --- a/rules/cstdlib/tgt_refcount.rs +++ b/rules/cstdlib/tgt_refcount.rs @@ -19,6 +19,17 @@ fn f5(a0: usize, a1: usize) -> AnyPtr { libcc2rs::calloc_refcount(a0, a1) } +fn f6(a0: Ptr) -> Ptr { + match ::std::env::var(a0.to_rust_string()) { + Ok(__val) => { + let mut __bytes = __val.into_bytes(); + __bytes.push(0); + Ptr::alloc_array(__bytes.into_boxed_slice()) + } + Err(_) => Ptr::null(), + } +} + fn f8(a0: AnyPtr, a1: AnyPtr, a2: usize, a3: usize, a4: fn(AnyPtr, AnyPtr) -> i32) -> AnyPtr { let __base = a1.reinterpret_cast::(); let mut __lo: isize = 0; diff --git a/rules/dirent/tgt_refcount.rs b/rules/dirent/tgt_refcount.rs index cb0b8f9b..29f823ee 100644 --- a/rules/dirent/tgt_refcount.rs +++ b/rules/dirent/tgt_refcount.rs @@ -10,3 +10,35 @@ fn t1() -> Ptr { fn t2() -> libcc2rs::Dirent { Default::default() } + +fn f1(a0: Ptr) -> Ptr { + match nix::dir::Dir::open( + a0.to_rust_string().as_str(), + nix::fcntl::OFlag::O_RDONLY, + nix::sys::stat::Mode::empty(), + ) { + Ok(__dir) => Ptr::alloc(CDir::from_dir(__dir)), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + Ptr::null() + } + } +} + +fn f2(a0: Ptr) -> Ptr { + a0.with(|__d| { + let __i = __d.pos.get(); + if __i >= __d.entries.len() { + Ptr::null() + } else { + __d.pos.set(__i + 1); + let __e = &__d.entries[__i]; + Ptr::alloc(Dirent::from_entry(__e.0, &__e.1, __e.2)) + } + }) +} + +fn f3(a0: Ptr) -> i32 { + a0.delete(); + 0 +} diff --git a/rules/locale/tgt_refcount.rs b/rules/locale/tgt_refcount.rs new file mode 100644 index 00000000..0e432f58 --- /dev/null +++ b/rules/locale/tgt_refcount.rs @@ -0,0 +1,12 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use libcc2rs::*; + +// Rust does not have support for localization. +// +// TODO: we need to track ourselves the locale settings and change the behavior of the relevant +// functions based on the set locale. +fn f1(a0: i32, a1: Ptr) -> Ptr { + Ptr::from_string_literal(b"C") +} diff --git a/rules/pwd/tgt_refcount.rs b/rules/pwd/tgt_refcount.rs index 31c14099..8257ef1b 100644 --- a/rules/pwd/tgt_refcount.rs +++ b/rules/pwd/tgt_refcount.rs @@ -6,3 +6,14 @@ use libcc2rs::*; fn t1() -> libcc2rs::Passwd { Default::default() } + +fn f1(a0: u32) -> Ptr { + match nix::unistd::User::from_uid(nix::unistd::Uid::from_raw(a0)) { + Ok(Some(__u)) => Ptr::alloc(Passwd::from_user(&__u)), + Ok(None) => Ptr::null(), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + Ptr::null() + } + } +} diff --git a/rules/src/modules.rs b/rules/src/modules.rs index 65dbeae7..baef05d8 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -84,6 +84,8 @@ pub mod ip_tgt_refcount; pub mod ip_tgt_unsafe; #[path = r#"../limits/tgt_unsafe.rs"#] pub mod limits_tgt_unsafe; +#[path = r#"../locale/tgt_refcount.rs"#] +pub mod locale_tgt_refcount; #[path = r#"../locale/tgt_unsafe.rs"#] pub mod locale_tgt_unsafe; #[path = r#"../map/tgt_refcount.rs"#] diff --git a/rules/stat/tgt_refcount.rs b/rules/stat/tgt_refcount.rs index 32856e53..bf577f5c 100644 --- a/rules/stat/tgt_refcount.rs +++ b/rules/stat/tgt_refcount.rs @@ -6,3 +6,29 @@ use libcc2rs::*; fn t1() -> libcc2rs::Stat { Default::default() } + +fn f1(a0: Ptr, a1: Ptr) -> i32 { + match nix::sys::stat::stat(a0.to_rust_string().as_str()) { + 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(), + nix::sys::stat::Mode::from_bits_truncate(a1), + ) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} diff --git a/tests/unit/libc_char_ptr_field.c b/tests/unit/libc_char_ptr_field.c index dd37e238..f898aef1 100644 --- a/tests/unit/libc_char_ptr_field.c +++ b/tests/unit/libc_char_ptr_field.c @@ -1,4 +1,3 @@ -// no-compile: refcount #include #include #include diff --git a/tests/unit/out/refcount/libc_char_ptr_field.rs b/tests/unit/out/refcount/libc_char_ptr_field.rs new file mode 100644 index 00000000..f68896e5 --- /dev/null +++ b/tests/unit/out/refcount/libc_char_ptr_field.rs @@ -0,0 +1,58 @@ +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 pw: Value> = Rc::new(RefCell::new( + match nix::unistd::User::from_uid(nix::unistd::Uid::from_raw( + nix::unistd::geteuid().as_raw(), + )) { + Ok(Some(__u)) => Ptr::alloc(Passwd::from_user(&__u)), + Ok(None) => Ptr::null(), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + Ptr::null() + } + }, + )); + if !!(*pw.borrow()).is_null() { + return 0; + } + let home: Value> = Rc::new(RefCell::new( + (*(*(*pw.borrow()).upgrade().deref()).pw_dir.borrow()).clone(), + )); + let d: Value> = Rc::new(RefCell::new( + match nix::dir::Dir::open( + Ptr::from_string_literal(b"/tmp").to_rust_string().as_str(), + nix::fcntl::OFlag::O_RDONLY, + nix::sys::stat::Mode::empty(), + ) { + Ok(__dir) => Ptr::alloc(CDir::from_dir(__dir)), + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + Ptr::null() + } + } + .with(|__d| { + let __i = __d.pos.get(); + if __i >= __d.entries.len() { + Ptr::null() + } else { + __d.pos.set(__i + 1); + let __e = &__d.entries[__i]; + Ptr::alloc(Dirent::from_entry(__e.0, &__e.1, __e.2)) + } + }), + )); + let dname: Value> = Rc::new(RefCell::new( + ((*(*d.borrow()).upgrade().deref()).d_name.as_pointer() as Ptr), + )); + return 0; +}