1#[cfg(target_family = "unix")]
2mod arch {
3 use ckb_vm::{
4 Error, Memory, Register, SupportMachine, Syscalls,
5 registers::{A0, A1, A2, A7},
6 };
7 use std::os::fd::BorrowedFd;
8
9 #[derive(Clone, Debug, Default)]
10 #[repr(C)]
11 struct AbiStat {
12 dev: u64,
13 ino: u64,
14 mode: u32,
15 nlink: i32,
16 uid: u32,
17 gid: u32,
18 rdev: u64,
19 __pad1: u64,
20 size: i64,
21 blksize: i32,
22 __pad2: i32,
23 blocks: i64,
24 atime: i64,
25 atime_nsec: i64,
26 mtime: i64,
27 mtime_nsec: i64,
28 ctime: i64,
29 ctime_nsec: i64,
30 __unused4: i32,
31 __unused5: i32,
32 }
33
34 #[derive(Default)]
35 pub struct Stdio {
36 keep_stdios: bool,
37 }
38
39 impl Stdio {
40 pub fn new(keep_stdios: bool) -> Self {
41 Stdio { keep_stdios }
42 }
43
44 fn close<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
45 let fd = machine.registers()[A0].to_i32();
46 if (fd >= 0 && fd <= 2) && self.keep_stdios {
47 machine.set_register(A0, Mac::REG::zero());
48 return Ok(());
49 }
50 let ret = match nix::unistd::close(fd) {
51 Ok(()) => 0,
52 Err(e) => {
53 println!("Error: {:?}", e);
54 (-1i64) as u64
55 }
56 };
57 machine.set_register(A0, Mac::REG::from_u64(ret));
58 Ok(())
59 }
60
61 fn fstat<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
62 let stat = match nix::sys::stat::fstat(unsafe { BorrowedFd::borrow_raw(machine.registers()[A0].to_i32()) })
63 {
64 Ok(stat) => stat,
65 Err(e) => {
66 println!("Error: {:?}", e);
67 machine.set_register(A0, Mac::REG::from_i8(-1));
68 return Ok(());
69 }
70 };
71 let mut abi_stat = AbiStat::default();
72 abi_stat.dev = stat.st_dev as u64;
73 abi_stat.ino = stat.st_ino;
74 abi_stat.mode = stat.st_mode as u32;
75 abi_stat.nlink = stat.st_nlink as i32;
76 abi_stat.uid = stat.st_uid;
77 abi_stat.gid = stat.st_gid;
78 abi_stat.rdev = stat.st_rdev as u64;
79 abi_stat.size = stat.st_size;
80 abi_stat.blksize = stat.st_blksize as i32;
81 abi_stat.blocks = stat.st_blocks;
82 abi_stat.atime = stat.st_atime;
83 abi_stat.atime_nsec = stat.st_atime_nsec;
84 abi_stat.mtime = stat.st_mtime;
85 abi_stat.mtime_nsec = stat.st_mtime_nsec;
86 abi_stat.ctime = stat.st_ctime;
87 abi_stat.ctime_nsec = stat.st_ctime_nsec;
88 let len = std::mem::size_of::<AbiStat>();
89 let b: &[u8] = unsafe { std::slice::from_raw_parts(&abi_stat as *const AbiStat as *const u8, len) };
90 let addr = machine.registers()[A1].to_u64();
91 machine.memory_mut().store_bytes(addr, b)?;
92 machine.set_register(A0, Mac::REG::zero());
93 Ok(())
94 }
95
96 fn lseek<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
97 let fd = machine.registers()[A0].to_i32();
98 let offset = machine.registers()[A1].to_i64();
99 let whence = match machine.registers()[A2].to_i32() {
100 libc::SEEK_SET => nix::unistd::Whence::SeekSet,
101 libc::SEEK_CUR => nix::unistd::Whence::SeekCur,
102 libc::SEEK_END => nix::unistd::Whence::SeekEnd,
103 _ => return Err(Error::Unexpected("Unexpected whence".into())),
104 };
105 let ret = nix::unistd::lseek(unsafe { BorrowedFd::borrow_raw(fd) }, offset, whence).unwrap_or_else(|e| {
106 println!("Error: {:?}", e);
107 -1
108 });
109 machine.set_register(A0, Mac::REG::from_i64(ret));
110 Ok(())
111 }
112
113 fn read<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
114 let fd = machine.registers()[A0].to_i32();
115 let addr = machine.registers()[A1].to_u64();
116 let size = machine.registers()[A2].to_u64() as usize;
117 let mut buf = vec![0u8; size];
118
119 match nix::unistd::read(unsafe { BorrowedFd::borrow_raw(fd) }, &mut buf) {
120 Ok(read_size) => {
121 machine.memory_mut().store_bytes(addr, &buf[0..read_size])?;
122 machine.set_register(A0, Mac::REG::from_u64(read_size as u64));
123 }
124 Err(e) => {
125 println!("Error: {:?}", e);
126 machine.set_register(A0, Mac::REG::from_i64(-1i64));
127 }
128 };
129 Ok(())
130 }
131
132 fn write<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
133 let fd = machine.registers()[A0].to_i32();
134 let addr = machine.registers()[A1].to_u64();
135 let size = machine.registers()[A2].to_u64() as usize;
136 let mut buf = vec![0u8; size];
137 for i in 0..size {
138 buf[i] = machine.memory_mut().load8(&Mac::REG::from_u64(addr + i as u64))?.to_u8();
139 }
140 let ret = nix::unistd::write(unsafe { BorrowedFd::borrow_raw(fd) }, &buf).unwrap_or_else(|e| {
141 println!("Error: {:?}", e);
142 (-1isize) as usize
143 });
144 machine.set_register(A0, Mac::REG::from_u64(ret as u64));
145 Ok(())
146 }
147
148 fn writev<Mac: SupportMachine>(&mut self, machine: &mut Mac) -> Result<(), Error> {
149 let fd = machine.registers()[A0].to_i32();
150 let iov = machine.registers()[A1].to_u64();
151 let iovcnt = machine.registers()[A2].to_u64();
152
153 let mut written = 0;
154 for i in 0..iovcnt {
155 let base = machine.memory_mut().load64(&Mac::REG::from_u64(iov + i * 16))?.to_u64();
156 let len = machine.memory_mut().load64(&Mac::REG::from_u64(iov + i * 16 + 8))?.to_u64();
157
158 let buf = machine.memory_mut().load_bytes(base, len)?;
159
160 written += match nix::unistd::write(unsafe { BorrowedFd::borrow_raw(fd) }, &buf) {
161 Ok(w) => w as u64,
162 Err(e) => {
163 println!("Error: {:?}", e);
164 machine.set_register(A0, Mac::REG::from_i64(-1));
165 return Ok(());
166 }
167 };
168 }
169 machine.set_register(A0, Mac::REG::from_u64(written));
170 Ok(())
171 }
172 }
173
174 impl<Mac: SupportMachine> Syscalls<Mac> for Stdio {
175 fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> {
176 Ok(())
177 }
178
179 fn ecall(&mut self, machine: &mut Mac) -> Result<bool, Error> {
180 match machine.registers()[A7].to_u64() {
181 57 => self.close(machine)?,
182 62 => self.lseek(machine)?,
183 63 => self.read(machine)?,
184 64 => self.write(machine)?,
185 66 => self.writev(machine)?,
186 80 => self.fstat(machine)?,
187 _ => return Ok(false),
188 };
189 Ok(true)
190 }
191 }
192}
193
194#[cfg(any(target_family = "wasm", target_family = "windows"))]
195mod arch {
196 use ckb_vm::{Error, SupportMachine, Syscalls};
197
198 #[derive(Default)]
199 pub struct Stdio {}
200
201 impl Stdio {
202 pub fn new(_: bool) -> Self {
203 Stdio {}
204 }
205 }
206
207 impl<Mac: SupportMachine> Syscalls<Mac> for Stdio {
208 fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> {
209 Ok(())
210 }
211
212 fn ecall(&mut self, _machine: &mut Mac) -> Result<bool, Error> {
213 Ok(false)
214 }
215 }
216}
217
218pub use arch::Stdio;