Skip to content

Commit fa08dc1

Browse files
authored
Replace std::fs::File with libcc2rs::CFile (#286)
1 parent a4f9c89 commit fa08dc1

34 files changed

Lines changed: 1556 additions & 818 deletions

‎libcc2rs/src/fd.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ pub struct FdRegistry {
99
}
1010

1111
thread_local! {
12-
static FD_REGISTRY: RefCell<FdRegistry> = const { RefCell::new(FdRegistry { fds: Vec::new() }) };
12+
static FD_REGISTRY: RefCell<FdRegistry> = RefCell::new(FdRegistry {
13+
fds: vec![
14+
std::io::stdin().as_fd().try_clone_to_owned().ok(),
15+
std::io::stdout().as_fd().try_clone_to_owned().ok(),
16+
std::io::stderr().as_fd().try_clone_to_owned().ok(),
17+
],
18+
});
1319
}
1420

1521
impl FdRegistry {

‎libcc2rs/src/io.rs‎

Lines changed: 30 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4-
use crate::{AnyPtr, AsPointer, Ptr, Value};
4+
use crate::{AnyPtr, AsPointer, CFile, Ptr, Value};
55
use std::cell::{RefCell, UnsafeCell};
66
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
77
use std::rc::Rc;
@@ -48,6 +48,24 @@ thread_local! {
4848
};
4949
}
5050

51+
thread_local! {
52+
static C_STDIN: Value<CFile> = Rc::new(RefCell::new(CFile::new(0)));
53+
static C_STDOUT: Value<CFile> = Rc::new(RefCell::new(CFile::new(1)));
54+
static C_STDERR: Value<CFile> = Rc::new(RefCell::new(CFile::new(2)));
55+
}
56+
57+
pub fn c_stdin() -> Ptr<CFile> {
58+
C_STDIN.with(AsPointer::as_pointer)
59+
}
60+
61+
pub fn c_stdout() -> Ptr<CFile> {
62+
C_STDOUT.with(AsPointer::as_pointer)
63+
}
64+
65+
pub fn c_stderr() -> Ptr<CFile> {
66+
C_STDERR.with(AsPointer::as_pointer)
67+
}
68+
5169
pub fn cin() -> Ptr<std::fs::File> {
5270
SAFE_STDIN.with(AsPointer::as_pointer)
5371
}
@@ -84,79 +102,24 @@ pub unsafe fn cerr_unsafe() -> *mut std::fs::File {
84102
UNSAFE_STDERR.with(UnsafeCell::get)
85103
}
86104

87-
pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
105+
pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<CFile>) -> usize {
88106
let total = a1.saturating_mul(a2);
89-
let mut dst = a0.reinterpret_cast::<u8>();
90-
91-
let f = (*a3.upgrade().deref())
92-
.try_clone()
93-
.expect("try_clone failed");
94-
let mut reader = std::io::BufReader::with_capacity(64 * 1024, f);
95-
96-
let mut read_bytes: usize = 0;
97-
let mut buffer: [u8; 8192] = [0; 8192];
98-
99-
while read_bytes < total {
100-
let remaining = total - read_bytes;
101-
let to_read = std::cmp::min(buffer.len(), remaining);
102-
103-
let n = match std::io::Read::read(&mut reader, &mut buffer[..to_read]) {
104-
Ok(0) => break,
105-
Ok(n) => n,
106-
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
107-
Err(e) => panic!("Unhandled error in fread: {e}"),
108-
};
109-
110-
for &byte in &buffer[..n] {
111-
dst.write(byte);
112-
dst += 1;
113-
}
114-
115-
read_bytes += n;
107+
if total == 0 {
108+
return 0;
116109
}
117-
110+
let dst = a0.reinterpret_cast::<u8>();
111+
let read_bytes = dst.with_slice_mut(total, |buf| a3.with_mut(|f| f.read(buf)));
118112
read_bytes / a1
119113
}
120114

121-
pub fn fwrite_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
115+
pub fn fwrite_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<CFile>) -> usize {
122116
let total = a1.saturating_mul(a2);
123-
let mut src = a0.reinterpret_cast::<u8>();
124-
125-
let f = (*a3.upgrade().deref())
126-
.try_clone()
127-
.expect("try_clone failed");
128-
let mut writer = std::io::BufWriter::with_capacity(64 * 1024, f);
129-
130-
let mut written_bytes: usize = 0;
131-
let mut buffer: [u8; 8192] = [0; 8192];
132-
133-
while written_bytes < total {
134-
let remaining = total - written_bytes;
135-
let to_fill = std::cmp::min(buffer.len(), remaining);
136-
137-
for b in buffer.iter_mut().take(to_fill) {
138-
*b = src.read();
139-
src += 1;
140-
}
141-
142-
let mut off = 0;
143-
while off < to_fill {
144-
match std::io::Write::write(&mut writer, &buffer[off..to_fill]) {
145-
Ok(0) => break,
146-
Ok(n) => off += n,
147-
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
148-
Err(e) => panic!("Unhandled error in fwrite: {e}"),
149-
}
150-
}
151-
152-
if off == 0 {
153-
break;
154-
}
155-
156-
written_bytes += off;
117+
if total == 0 {
118+
return 0;
157119
}
158-
159-
written_bytes / a1
120+
let src = a0.reinterpret_cast::<u8>();
121+
let written = src.with_slice(total, |bytes| a3.with_mut(|f| f.write(bytes)));
122+
written / a1
160123
}
161124

162125
unsafe extern "C" {

‎libcc2rs/src/libc_shims/cfile.rs‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
use crate::FdRegistry;
5+
6+
pub struct CFile {
7+
pub fd: i32,
8+
pub eof: bool,
9+
pub err: bool,
10+
}
11+
12+
impl CFile {
13+
pub fn new(fd: i32) -> Self {
14+
CFile {
15+
fd,
16+
eof: false,
17+
err: false,
18+
}
19+
}
20+
21+
pub fn open(path: &str, mode: &str) -> Option<CFile> {
22+
let flags = match mode {
23+
"rb" => nix::fcntl::OFlag::O_RDONLY,
24+
"wb" => nix::fcntl::OFlag::O_WRONLY
25+
.union(nix::fcntl::OFlag::O_CREAT)
26+
.union(nix::fcntl::OFlag::O_TRUNC),
27+
m => panic!("fopen: unsupported mode {:?}", m),
28+
};
29+
match nix::fcntl::open(path, flags, nix::sys::stat::Mode::from_bits_truncate(0o666)) {
30+
Ok(ofd) => Some(CFile::new(FdRegistry::register(ofd))),
31+
Err(e) => {
32+
crate::cpp2rust_errno().write(e as i32);
33+
None
34+
}
35+
}
36+
}
37+
38+
pub fn read(&mut self, buf: &mut [u8]) -> usize {
39+
let mut n = 0;
40+
while n < buf.len() {
41+
match FdRegistry::with_fd(self.fd, |b| nix::unistd::read(b, &mut buf[n..])) {
42+
Ok(0) => {
43+
self.eof = true;
44+
break;
45+
}
46+
Ok(k) => n += k,
47+
Err(nix::errno::Errno::EINTR) => {}
48+
Err(e) => {
49+
self.err = true;
50+
crate::cpp2rust_errno().write(e as i32);
51+
break;
52+
}
53+
}
54+
}
55+
n
56+
}
57+
58+
pub fn write(&mut self, buf: &[u8]) -> usize {
59+
let mut n = 0;
60+
while n < buf.len() {
61+
match FdRegistry::with_fd(self.fd, |b| nix::unistd::write(b, &buf[n..])) {
62+
Ok(0) => {
63+
self.err = true;
64+
break;
65+
}
66+
Ok(k) => n += k,
67+
Err(nix::errno::Errno::EINTR) => {}
68+
Err(e) => {
69+
self.err = true;
70+
crate::cpp2rust_errno().write(e as i32);
71+
break;
72+
}
73+
}
74+
}
75+
n
76+
}
77+
78+
pub fn seek(&mut self, offset: i64, whence: i32) -> i64 {
79+
let w = match whence {
80+
0 => nix::unistd::Whence::SeekSet,
81+
1 => nix::unistd::Whence::SeekCur,
82+
2 => nix::unistd::Whence::SeekEnd,
83+
other => panic!("fseek: unsupported whence {}", other),
84+
};
85+
match FdRegistry::with_fd(self.fd, |b| nix::unistd::lseek(b, offset, w)) {
86+
Ok(off) => {
87+
self.eof = false;
88+
off
89+
}
90+
Err(e) => {
91+
crate::cpp2rust_errno().write(e as i32);
92+
-1
93+
}
94+
}
95+
}
96+
97+
pub fn tell(&self) -> i64 {
98+
match FdRegistry::with_fd(self.fd, |b| {
99+
nix::unistd::lseek(b, 0, nix::unistd::Whence::SeekCur)
100+
}) {
101+
Ok(off) => off,
102+
Err(e) => {
103+
crate::cpp2rust_errno().write(e as i32);
104+
-1
105+
}
106+
}
107+
}
108+
109+
pub fn getc(&mut self) -> i32 {
110+
let mut b = [0u8; 1];
111+
match self.read(&mut b) {
112+
1 => b[0] as i32,
113+
_ => -1,
114+
}
115+
}
116+
117+
pub fn close(&self) -> i32 {
118+
FdRegistry::close(self.fd)
119+
}
120+
}
121+
122+
impl crate::ByteRepr for CFile {}

‎libcc2rs/src/libc_shims/mod.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
mod cfile;
45
mod dirent;
56
mod fdset;
67
mod ifaddrs;
@@ -13,6 +14,7 @@ mod stat;
1314
mod termios;
1415
mod time;
1516

17+
pub use cfile::*;
1618
pub use dirent::*;
1719
pub use fdset::*;
1820
pub use ifaddrs::*;

‎rules/stdio/src.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ int f23(FILE *stream) { return getc(stream); }
7171
int f24(FILE *stream, char *buf, int mode, size_t size) {
7272
return setvbuf(stream, buf, mode, size);
7373
}
74+
75+
int f25(void) { return SEEK_SET; }
76+
77+
int f26(void) { return SEEK_CUR; }
78+
79+
int f27(void) { return SEEK_END; }

0 commit comments

Comments
 (0)