microfetch_lib/
syscall.rs1use std::io;
12
13#[inline]
26#[must_use]
27pub unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
28 #[cfg(target_arch = "x86_64")]
29 unsafe {
30 let fd: i64;
31 std::arch::asm!(
32 "syscall",
33 in("rax") 2i64, in("rdi") path,
35 in("rsi") flags,
36 in("rdx") 0i32, lateout("rax") fd,
38 lateout("rcx") _,
39 lateout("r11") _,
40 options(nostack)
41 );
42 #[allow(clippy::cast_possible_truncation)]
43 {
44 fd as i32
45 }
46 }
47 #[cfg(target_arch = "aarch64")]
48 unsafe {
49 let fd: i64;
50 std::arch::asm!(
51 "svc #0",
52 in("x8") 56i64, in("x0") -100i32, in("x1") path,
55 in("x2") flags,
56 in("x3") 0i32, lateout("x0") fd,
58 options(nostack)
59 );
60 #[allow(clippy::cast_possible_truncation)]
61 {
62 fd as i32
63 }
64 }
65 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
66 {
67 compile_error!("Unsupported architecture for inline assembly syscalls");
68 }
69}
70
71#[inline]
83pub unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
84 #[cfg(target_arch = "x86_64")]
85 unsafe {
86 let ret: i64;
87 std::arch::asm!(
88 "syscall",
89 in("rax") 0i64, in("rdi") fd,
91 in("rsi") buf,
92 in("rdx") count,
93 lateout("rax") ret,
94 lateout("rcx") _,
95 lateout("r11") _,
96 options(nostack)
97 );
98 #[allow(clippy::cast_possible_truncation)]
99 {
100 ret as isize
101 }
102 }
103 #[cfg(target_arch = "aarch64")]
104 unsafe {
105 let ret: i64;
106 std::arch::asm!(
107 "svc #0",
108 in("x8") 63i64, in("x0") fd,
110 in("x1") buf,
111 in("x2") count,
112 lateout("x0") ret,
113 options(nostack)
114 );
115 #[allow(clippy::cast_possible_truncation)]
116 {
117 ret as isize
118 }
119 }
120 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
121 {
122 compile_error!("Unsupported architecture for inline assembly syscalls");
123 }
124}
125
126#[inline]
132#[must_use]
133pub unsafe fn sys_close(fd: i32) -> i32 {
134 #[cfg(target_arch = "x86_64")]
135 unsafe {
136 let ret: i64;
137 std::arch::asm!(
138 "syscall",
139 in("rax") 3i64, in("rdi") fd,
141 lateout("rax") ret,
142 lateout("rcx") _,
143 lateout("r11") _,
144 options(nostack)
145 );
146 #[allow(clippy::cast_possible_truncation)]
147 {
148 ret as i32
149 }
150 }
151 #[cfg(target_arch = "aarch64")]
152 unsafe {
153 let ret: i64;
154 std::arch::asm!(
155 "svc #0",
156 in("x8") 57i64, in("x0") fd,
158 lateout("x0") ret,
159 options(nostack)
160 );
161 #[allow(clippy::cast_possible_truncation)]
162 {
163 ret as i32
164 }
165 }
166 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
167 {
168 compile_error!("Unsupported architecture for inline assembly syscalls");
169 }
170}
171
172#[inline]
179pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
180 const O_RDONLY: i32 = 0;
181
182 let path_bytes = path.as_bytes();
184 if path_bytes.len() >= 256 {
185 return Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long"));
186 }
187
188 let mut path_buf = [0u8; 256];
189 path_buf[..path_bytes.len()].copy_from_slice(path_bytes);
190 unsafe {
193 let fd = sys_open(path_buf.as_ptr(), O_RDONLY);
194 if fd < 0 {
195 return Err(io::Error::last_os_error());
196 }
197
198 let bytes_read = sys_read(fd, buffer.as_mut_ptr(), buffer.len());
199 let _ = sys_close(fd);
200
201 if bytes_read < 0 {
202 return Err(io::Error::last_os_error());
203 }
204
205 #[allow(clippy::cast_sign_loss)]
206 {
207 Ok(bytes_read as usize)
208 }
209 }
210}