1use crate::Error;
12use crate::Result;
13use crate::RtFd;
14use crate::RtVdsoVtable;
15use crate::error::*;
16use crate::into_result;
17use core::sync::atomic::Ordering;
18
19#[cfg(not(feature = "rustc-dep-of-std"))]
20extern crate alloc;
21
22pub const TEMP_DIR: &str = "/sys/tmp";
23pub const HANDLE_URL_PREFIX: &str = "handle://";
24
25pub const MAX_PATH_LEN: usize = 1024;
32pub const MAX_FILENAME_LEN: usize = 256;
34pub const MAX_FILE_LEN: u64 = i64::MAX as u64;
36
37pub const FILETYPE_FILE: u8 = 1;
39pub const FILETYPE_DIRECTORY: u8 = 2;
40
41pub const PERM_READ: u64 = 1;
43pub const PERM_WRITE: u64 = 2;
44
45pub const O_READ: u32 = 1 << 0;
47pub const O_WRITE: u32 = 1 << 1;
48pub const O_APPEND: u32 = 1 << 2;
49pub const O_TRUNCATE: u32 = 1 << 3;
50pub const O_CREATE: u32 = 1 << 4;
51pub const O_CREATE_NEW: u32 = 1 << 5;
52pub const O_NONBLOCK: u32 = 1 << 6;
53
54pub const O_HANDLE_CHILD: u32 = 1;
56
57pub const SEEK_SET: u8 = 0;
59pub const SEEK_CUR: u8 = 1;
60pub const SEEK_END: u8 = 2;
61
62#[repr(C, align(16))]
63#[derive(Clone, Copy, PartialEq, Eq, Default)]
64pub struct FileAttr {
65 pub version: u64,
66 pub size: u64,
67 pub perm: u64,
68 pub file_type: u8,
69 pub _reserved: [u8; 7],
70 pub created: u128,
71 pub modified: u128,
72 pub accessed: u128,
73}
74
75impl FileAttr {
76 pub const VERSION: u64 = 1;
77
78 fn new() -> Self {
79 Self {
80 version: Self::VERSION,
81 ..Default::default()
82 }
83 }
84}
85
86#[repr(C, align(16))]
88#[derive(Clone, Copy)]
89pub struct DirEntry {
90 pub version: u64,
91 pub _reserved: u64,
92 pub attr: FileAttr,
93 pub fname_size: u16, pub fname: [u8; MAX_FILENAME_LEN],
95}
96
97impl DirEntry {
98 pub const VERSION: u64 = 1;
99
100 fn new() -> Self {
101 Self {
102 version: Self::VERSION,
103 _reserved: 0,
104 attr: FileAttr::new(),
105 fname_size: 0,
106 fname: [0; MAX_FILENAME_LEN],
107 }
108 }
109}
110
111pub fn is_terminal(rt_fd: RtFd) -> bool {
112 let vdso_is_terminal: extern "C" fn(i32) -> i32 = unsafe {
113 core::mem::transmute(
114 RtVdsoVtable::get().fs_is_terminal.load(Ordering::Relaxed) as usize as *const (),
115 )
116 };
117
118 match vdso_is_terminal(rt_fd) {
119 0 => false,
120 1 => true,
121 _ => panic!(),
122 }
123}
124
125pub fn duplicate(rt_fd: RtFd) -> Result<RtFd> {
126 let vdso_duplicate: extern "C" fn(RtFd) -> RtFd = unsafe {
127 core::mem::transmute(
128 RtVdsoVtable::get().fs_duplicate.load(Ordering::Relaxed) as usize as *const (),
129 )
130 };
131
132 to_result!(vdso_duplicate(rt_fd))
133}
134
135pub fn open(path: &str, opts: u32) -> Result<RtFd> {
137 let vdso_open: extern "C" fn(*const u8, usize, u32) -> i32 = unsafe {
138 core::mem::transmute(
139 RtVdsoVtable::get().fs_open.load(Ordering::Relaxed) as usize as *const ()
140 )
141 };
142
143 let bytes = path.as_bytes();
144 to_result!(vdso_open(bytes.as_ptr(), bytes.len(), opts))
145}
146
147pub fn close(rt_fd: RtFd) -> Result<()> {
148 let vdso_close: extern "C" fn(i32) -> ErrorCode = unsafe {
149 core::mem::transmute(
150 RtVdsoVtable::get().fs_close.load(Ordering::Relaxed) as usize as *const (),
151 )
152 };
153
154 into_result(vdso_close(rt_fd))
155}
156
157pub fn get_file_attr(rt_fd: RtFd) -> Result<FileAttr> {
158 let vdso_get_file_attr: extern "C" fn(i32, *mut FileAttr) -> ErrorCode = unsafe {
159 core::mem::transmute(
160 RtVdsoVtable::get().fs_get_file_attr.load(Ordering::Relaxed) as usize as *const (),
161 )
162 };
163
164 let mut attr = FileAttr::new();
165 into_result(vdso_get_file_attr(rt_fd, &mut attr))?;
166 Ok(attr)
167}
168
169pub fn fsync(rt_fd: RtFd) -> Result<()> {
170 let vdso_fsync: extern "C" fn(i32) -> ErrorCode = unsafe {
171 core::mem::transmute(
172 RtVdsoVtable::get().fs_fsync.load(Ordering::Relaxed) as usize as *const (),
173 )
174 };
175
176 into_result(vdso_fsync(rt_fd))
177}
178
179pub fn datasync(rt_fd: RtFd) -> Result<()> {
180 let vdso_datasync: extern "C" fn(i32) -> ErrorCode = unsafe {
181 core::mem::transmute(
182 RtVdsoVtable::get().fs_datasync.load(Ordering::Relaxed) as usize as *const (),
183 )
184 };
185
186 into_result(vdso_datasync(rt_fd))
187}
188
189pub fn truncate(rt_fd: RtFd, size: u64) -> Result<()> {
190 let vdso_truncate: extern "C" fn(i32, u64) -> ErrorCode = unsafe {
191 core::mem::transmute(
192 RtVdsoVtable::get().fs_truncate.load(Ordering::Relaxed) as usize as *const (),
193 )
194 };
195
196 into_result(vdso_truncate(rt_fd, size))
197}
198
199pub fn read(rt_fd: RtFd, buf: &mut [u8]) -> Result<usize> {
200 let vdso_read: extern "C" fn(i32, *mut u8, usize) -> i64 = unsafe {
201 core::mem::transmute(
202 RtVdsoVtable::get().fs_read.load(Ordering::Relaxed) as usize as *const ()
203 )
204 };
205
206 to_result!(vdso_read(rt_fd, buf.as_mut_ptr(), buf.len()))
207}
208
209pub fn read_vectored(rt_fd: RtFd, bufs: &mut [&mut [u8]]) -> Result<usize> {
210 use alloc::vec::Vec;
211
212 let vdso_read_vectored: extern "C" fn(i32, *const usize, usize) -> i64 = unsafe {
213 core::mem::transmute(
214 RtVdsoVtable::get().fs_read_vectored.load(Ordering::Relaxed) as usize as *const (),
215 )
216 };
217
218 let mut packed = Vec::with_capacity(bufs.len() * 2);
220 for buf in &*bufs {
221 let addr = buf.as_ptr() as usize;
222 let len = buf.len();
223 packed.push(addr);
224 packed.push(len);
225 }
226
227 to_result!(vdso_read_vectored(rt_fd, packed.as_ptr(), bufs.len()))
228}
229
230pub fn write(rt_fd: RtFd, buf: &[u8]) -> Result<usize> {
231 let vdso_write: extern "C" fn(i32, *const u8, usize) -> i64 = unsafe {
232 core::mem::transmute(
233 RtVdsoVtable::get().fs_write.load(Ordering::Relaxed) as usize as *const (),
234 )
235 };
236
237 to_result!(vdso_write(rt_fd, buf.as_ptr(), buf.len()))
238}
239
240pub fn write_vectored(rt_fd: RtFd, bufs: &[&[u8]]) -> Result<usize> {
241 use alloc::vec::Vec;
242
243 let vdso_write_vectored: extern "C" fn(i32, *const usize, usize) -> i64 = unsafe {
244 core::mem::transmute(
245 RtVdsoVtable::get()
246 .fs_write_vectored
247 .load(Ordering::Relaxed) as usize as *const (),
248 )
249 };
250
251 let mut packed = Vec::with_capacity(bufs.len() * 2);
253 #[allow(clippy::borrow_deref_ref)]
254 for buf in &*bufs {
255 let addr = buf.as_ptr() as usize;
256 let len = buf.len();
257 packed.push(addr);
258 packed.push(len);
259 }
260
261 to_result!(vdso_write_vectored(rt_fd, packed.as_ptr(), bufs.len()))
262}
263
264pub fn flush(rt_fd: RtFd) -> Result<()> {
265 let vdso_flush: extern "C" fn(i32) -> ErrorCode = unsafe {
266 core::mem::transmute(
267 RtVdsoVtable::get().fs_flush.load(Ordering::Relaxed) as usize as *const (),
268 )
269 };
270
271 into_result(vdso_flush(rt_fd))
272}
273
274pub fn seek(rt_fd: RtFd, offset: i64, whence: u8) -> Result<u64> {
275 let vdso_seek: extern "C" fn(i32, i64, u8) -> i64 = unsafe {
276 core::mem::transmute(
277 RtVdsoVtable::get().fs_seek.load(Ordering::Relaxed) as usize as *const ()
278 )
279 };
280
281 to_result!(vdso_seek(rt_fd, offset, whence))
282}
283
284pub fn mkdir(path: &str) -> Result<()> {
285 let vdso_mkdir: extern "C" fn(*const u8, usize) -> ErrorCode = unsafe {
286 core::mem::transmute(
287 RtVdsoVtable::get().fs_mkdir.load(Ordering::Relaxed) as usize as *const (),
288 )
289 };
290
291 let bytes = path.as_bytes();
292 into_result(vdso_mkdir(bytes.as_ptr(), bytes.len()))
293}
294
295pub fn unlink(path: &str) -> Result<()> {
296 let vdso_unlink: extern "C" fn(*const u8, usize) -> ErrorCode = unsafe {
297 core::mem::transmute(
298 RtVdsoVtable::get().fs_unlink.load(Ordering::Relaxed) as usize as *const (),
299 )
300 };
301
302 let bytes = path.as_bytes();
303 into_result(vdso_unlink(bytes.as_ptr(), bytes.len()))
304}
305
306pub fn rename(old: &str, new: &str) -> Result<()> {
307 let vdso_rename: extern "C" fn(*const u8, usize, *const u8, usize) -> ErrorCode = unsafe {
308 core::mem::transmute(
309 RtVdsoVtable::get().fs_rename.load(Ordering::Relaxed) as usize as *const (),
310 )
311 };
312
313 let old = old.as_bytes();
314 let new = new.as_bytes();
315 into_result(vdso_rename(
316 old.as_ptr(),
317 old.len(),
318 new.as_ptr(),
319 new.len(),
320 ))
321}
322
323pub fn rmdir(path: &str) -> Result<()> {
324 let vdso_rmdir: extern "C" fn(*const u8, usize) -> ErrorCode = unsafe {
325 core::mem::transmute(
326 RtVdsoVtable::get().fs_rmdir.load(Ordering::Relaxed) as usize as *const (),
327 )
328 };
329
330 let bytes = path.as_bytes();
331 into_result(vdso_rmdir(bytes.as_ptr(), bytes.len()))
332}
333
334pub fn rmdir_all(path: &str) -> Result<()> {
335 let vdso_rmdir_all: extern "C" fn(*const u8, usize) -> ErrorCode = unsafe {
336 core::mem::transmute(
337 RtVdsoVtable::get().fs_rmdir_all.load(Ordering::Relaxed) as usize as *const (),
338 )
339 };
340
341 let bytes = path.as_bytes();
342 into_result(vdso_rmdir_all(bytes.as_ptr(), bytes.len()))
343}
344
345pub fn set_perm(path: &str, perm: u64) -> Result<()> {
346 let vdso_set_perm: extern "C" fn(*const u8, usize, u64) -> ErrorCode = unsafe {
347 core::mem::transmute(
348 RtVdsoVtable::get().fs_set_perm.load(Ordering::Relaxed) as usize as *const (),
349 )
350 };
351
352 let bytes = path.as_bytes();
353 into_result(vdso_set_perm(bytes.as_ptr(), bytes.len(), perm))
354}
355
356pub fn set_file_perm(rt_fd: RtFd, perm: u64) -> Result<()> {
357 let vdso_set_file_perm: extern "C" fn(RtFd, u64) -> ErrorCode = unsafe {
358 core::mem::transmute(
359 RtVdsoVtable::get().fs_set_file_perm.load(Ordering::Relaxed) as usize as *const (),
360 )
361 };
362
363 into_result(vdso_set_file_perm(rt_fd, perm))
364}
365
366pub fn stat(path: &str) -> Result<FileAttr> {
367 let vdso_stat: extern "C" fn(*const u8, usize, *mut FileAttr) -> ErrorCode = unsafe {
368 core::mem::transmute(
369 RtVdsoVtable::get().fs_stat.load(Ordering::Relaxed) as usize as *const ()
370 )
371 };
372
373 let bytes = path.as_bytes();
374 let mut attr = FileAttr::new();
375
376 into_result(vdso_stat(bytes.as_ptr(), bytes.len(), &mut attr))?;
377 Ok(attr)
378}
379
380pub fn canonicalize(path: &str) -> Result<alloc::string::String> {
381 let vdso_canonicalize: extern "C" fn(*const u8, usize, *mut u8, *mut usize) -> ErrorCode = unsafe {
382 core::mem::transmute(
383 RtVdsoVtable::get().fs_canonicalize.load(Ordering::Relaxed) as usize as *const (),
384 )
385 };
386
387 let path = path.as_bytes();
388 let mut bytes = [0_u8; MAX_PATH_LEN];
389 let mut len = 0_usize;
390
391 use alloc::borrow::ToOwned;
392 into_result(vdso_canonicalize(
393 path.as_ptr(),
394 path.len(),
395 bytes.as_mut_ptr(),
396 &mut len,
397 ))?;
398 Ok(core::str::from_utf8(&bytes[..len]).unwrap().to_owned())
399}
400
401pub fn copy(from: &str, to: &str) -> Result<u64> {
402 let vdso_copy: extern "C" fn(*const u8, usize, *const u8, usize) -> i64 = unsafe {
403 core::mem::transmute(
404 RtVdsoVtable::get().fs_copy.load(Ordering::Relaxed) as usize as *const ()
405 )
406 };
407
408 let from = from.as_bytes();
409 let to = to.as_bytes();
410 to_result!(vdso_copy(from.as_ptr(), from.len(), to.as_ptr(), to.len()))
411}
412
413pub fn opendir(path: &str) -> Result<RtFd> {
414 let vdso_opendir: extern "C" fn(*const u8, usize) -> i32 = unsafe {
415 core::mem::transmute(
416 RtVdsoVtable::get().fs_opendir.load(Ordering::Relaxed) as usize as *const (),
417 )
418 };
419
420 let bytes = path.as_bytes();
421 to_result!(vdso_opendir(bytes.as_ptr(), bytes.len()))
422}
423
424pub fn closedir(rt_fd: RtFd) -> Result<()> {
425 let vdso_closedir: extern "C" fn(i32) -> ErrorCode = unsafe {
426 core::mem::transmute(
427 RtVdsoVtable::get().fs_closedir.load(Ordering::Relaxed) as usize as *const (),
428 )
429 };
430
431 into_result(vdso_closedir(rt_fd))
432}
433
434pub fn readdir(rt_fd: RtFd) -> Result<Option<DirEntry>> {
435 let vdso_readdir: extern "C" fn(i32, *mut DirEntry) -> ErrorCode = unsafe {
436 core::mem::transmute(
437 RtVdsoVtable::get().fs_readdir.load(Ordering::Relaxed) as usize as *const (),
438 )
439 };
440
441 let mut dentry = DirEntry::new();
442 match into_result(vdso_readdir(rt_fd, &mut dentry)) {
443 Ok(()) => Ok(Some(dentry)),
444 Err(Error::NotFound) => Ok(None),
445 Err(err) => Err(err),
446 }
447}
448
449pub fn getcwd() -> Result<alloc::string::String> {
450 let vdso_getcwd: extern "C" fn(*mut u8, *mut usize) -> ErrorCode = unsafe {
451 core::mem::transmute(
452 RtVdsoVtable::get().fs_getcwd.load(Ordering::Relaxed) as usize as *const (),
453 )
454 };
455
456 let mut bytes = [0_u8; MAX_PATH_LEN];
457 let mut len = 0_usize;
458
459 use alloc::borrow::ToOwned;
460 into_result(vdso_getcwd(bytes.as_mut_ptr(), &mut len))?;
461 Ok(core::str::from_utf8(&bytes[..len]).unwrap().to_owned())
462}
463
464pub fn chdir(path: &str) -> Result<()> {
465 let vdso_chdir: extern "C" fn(*const u8, usize) -> ErrorCode = unsafe {
466 core::mem::transmute(
467 RtVdsoVtable::get().fs_chdir.load(Ordering::Relaxed) as usize as *const (),
468 )
469 };
470
471 let bytes = path.as_bytes();
472 into_result(vdso_chdir(bytes.as_ptr(), bytes.len()))
473}