1#[cfg(not(feature = "rustc-dep-of-std"))]
5extern crate alloc;
6
7use super::types::{
8 OptionalPtrMut, OptionalStrPtr, Pid, RequiredPtr, RequiredPtrMut, Ri, StrPtr, StrPtrMut,
9 SyscallResult,
10};
11use super::SyscallNum;
12use super::{define_syscall, DirEntry, FileAttr, RawSlice, RawSliceMut};
13use super::{err_from_u16, ErrorStatus};
14use crate::process::{sysmeta_stderr, sysmeta_stdin, sysmeta_stdout};
15use alloc::vec::Vec;
16use core::ptr;
17use safa_abi::raw::processes::SpawnFlags;
18use safa_abi::raw::Optional;
19
20define_syscall!(SyscallNum::SysGetDirEntry => {
21 sysgetdirentry(path_ptr: StrPtr, path_len: usize, dest_direntry: OptionalPtrMut<DirEntry>)
25});
26
27#[inline]
28pub fn getdirentry(path: &str) -> Result<DirEntry, ErrorStatus> {
29 let mut dest_direntry: DirEntry = unsafe { core::mem::zeroed() };
30 err_from_u16!(
31 sysgetdirentry(path.as_ptr(), path.len(), &raw mut dest_direntry),
32 dest_direntry
33 )
34}
35
36define_syscall! {
37 SyscallNum::SysOpen => {
38 sysopen(path_ptr: StrPtr, path_len: usize, dest_fd: *mut Ri)
42 },
43 SyscallNum::SysCreate => {
44 syscreate_file(path_ptr: StrPtr, path_len: usize)
47 },
48 SyscallNum::SysCreateDir => {
49 syscreate_dir(path_ptr: StrPtr, path_len: usize)
53 },
54 SyscallNum::SysClose => {
55 sysclose(fd: Ri)
57 }
58}
59
60#[inline]
61pub fn open(path: &str) -> Result<Ri, ErrorStatus> {
65 let mut dest_fd = 0xAAAAAAAAAAAAAAAAusize;
66 err_from_u16!(
67 sysopen(path.as_ptr(), path.len(), &raw mut dest_fd),
68 dest_fd
69 )
70}
71
72#[inline]
73pub fn create(path: &str) -> Result<(), ErrorStatus> {
77 err_from_u16!(syscreate_file(path.as_ptr(), path.len()))
78}
79
80#[inline]
81pub fn createdir(path: &str) -> Result<(), ErrorStatus> {
85 err_from_u16!(syscreate_dir(path.as_ptr(), path.len()))
86}
87
88#[inline]
89pub fn close(fd: Ri) -> Result<(), ErrorStatus> {
93 err_from_u16!(sysclose(fd))
94}
95
96define_syscall! {
98 SyscallNum::SysDirIterOpen =>
99 {
100 sysdiriter_open(dir_ri: Ri, dest_ri: RequiredPtrMut<Ri>)
102 },
103 SyscallNum::SysDirIterClose => {
104 sysdiriter_close(fd: Ri)
106 },
107 SyscallNum::SysDirIterNext => {
108 sysdiriter_next(dir_ri: Ri, dest_direntry: OptionalPtrMut<DirEntry>)
116 }
117}
118
119#[inline]
120pub fn diriter_close(fd: Ri) -> Result<(), ErrorStatus> {
124 err_from_u16!(sysdiriter_close(fd))
125}
126
127#[inline]
128pub fn diriter_open(dir_ri: Ri) -> Result<Ri, ErrorStatus> {
133 let mut dest_fd: usize = 0xAAAAAAAAAAAAAAAAusize;
134 err_from_u16!(sysdiriter_open(dir_ri, &raw mut dest_fd), dest_fd)
135}
136
137#[inline]
138pub fn diriter_next(dir_ri: Ri) -> Result<DirEntry, ErrorStatus> {
142 let mut dest_direntry: DirEntry = unsafe { core::mem::zeroed() };
143 err_from_u16!(
144 sysdiriter_next(dir_ri, &raw mut dest_direntry),
145 dest_direntry
146 )
147}
148
149define_syscall! {
151 SyscallNum::SysWrite => {
152 syswrite(fd: Ri, offset: isize, buf: RequiredPtr<u8>, len: usize, dest_wrote: OptionalPtrMut<usize>)
156 },
157 SyscallNum::SysTruncate => {
158 systruncate(fd: Ri, len: usize)
160 },
161 SyscallNum::SysFSize => {
162 sysfsize(fd: Ri, dest_size: OptionalPtrMut<usize>)
164 },
165 SyscallNum::SysFAttrs => {
166 sysfattrs(fd: Ri, dest_attrs: OptionalPtrMut<FileAttr>)
168 },
169 SyscallNum::SysRead => {
170 sysread(fd: Ri, offset: isize, buf: RequiredPtrMut<u8>, len: usize, dest_read: OptionalPtrMut<usize>)
174 },
175 SyscallNum::SysSync => {
176 syssync(ri: Ri)
178 },
179 SyscallNum::SysDup => {
180 sysdup(ri: Ri, dest_ri: RequiredPtrMut<Ri>)
182 }
183}
184
185#[inline]
186pub fn write(fd: Ri, offset: isize, buf: &[u8]) -> Result<usize, ErrorStatus> {
189 let mut dest_wrote = 0;
190 err_from_u16!(
191 syswrite(fd, offset, buf.as_ptr(), buf.len(), &mut dest_wrote),
192 dest_wrote
193 )
194}
195
196#[inline]
197pub fn truncate(fd: Ri, len: usize) -> Result<(), ErrorStatus> {
199 err_from_u16!(systruncate(fd, len))
200}
201
202#[inline]
203pub fn fsize(fd: Ri) -> Result<usize, ErrorStatus> {
205 let mut dest_size = 0;
206 err_from_u16!(sysfsize(fd, &raw mut dest_size), dest_size)
207}
208
209#[inline]
210pub fn fattrs(fd: Ri) -> Result<FileAttr, ErrorStatus> {
212 let mut attrs: FileAttr = unsafe { core::mem::zeroed() };
213 err_from_u16!(sysfattrs(fd, &raw mut attrs), attrs)
214}
215
216#[inline]
217pub fn read(fd: Ri, offset: isize, buf: &mut [u8]) -> Result<Ri, ErrorStatus> {
219 let mut dest_read = 0;
220 err_from_u16!(
221 sysread(fd, offset, buf.as_mut_ptr(), buf.len(), &mut dest_read),
222 dest_read
223 )
224}
225
226#[inline]
227pub fn sync(ri: Ri) -> Result<(), ErrorStatus> {
229 err_from_u16!(syssync(ri))
230}
231
232#[inline]
233pub fn dup(ri: Ri) -> Result<Ri, ErrorStatus> {
236 let mut dest_ri = 0xAAAAAAAAAAAAAAAAusize;
237 err_from_u16!(sysdup(ri, &mut dest_ri), dest_ri)
238}
239
240define_syscall! {
242 SyscallNum::SysSbrk => {
243 syssbrk(size: isize, target_ptr: OptionalPtrMut<*mut u8>)
245 },
246 SyscallNum::SysExit => {
247 sysexit(code: usize) unreachable
249 },
250 SyscallNum::SysYield => {
251 sysyield()
253 },
254 SyscallNum::SysWait => {
255 syswait(pid: Pid, exit_code: *mut usize)
258 },
259 SyscallNum::SysCHDir => {
260 syschdir(buf_ptr: StrPtr, buf_len: usize)
263 },
264 SyscallNum::SysGetCWD => {
265 sysgetcwd(cwd_buf: StrPtrMut, cwd_buf_len: usize, dest_len: OptionalPtrMut<usize>)
270 }
271}
272
273#[inline]
274pub fn sbrk(size: isize) -> Result<*mut u8, ErrorStatus> {
279 let mut target_ptr: *mut u8 = core::ptr::null_mut();
280 err_from_u16!(syssbrk(size, &mut target_ptr), target_ptr)
281}
282
283#[inline]
284pub fn exit(code: usize) -> ! {
285 sysexit(code)
286}
287
288#[inline]
289pub fn yield_now() {
290 debug_assert!(sysyield().is_success())
291}
292
293#[inline]
294pub fn wait(pid: Pid) -> Result<usize, ErrorStatus> {
299 let mut dest_exit_code = 0;
300 err_from_u16!(syswait(pid, &mut dest_exit_code), dest_exit_code)
301}
302
303#[inline]
304pub fn chdir(path: &str) -> Result<(), ErrorStatus> {
306 let path = path.as_bytes();
307 err_from_u16!(syschdir(path.as_ptr(), path.len()))
308}
309
310use alloc::string::String;
311#[inline]
312pub fn getcwd() -> Result<String, ErrorStatus> {
314 let mut buffer = Vec::with_capacity(safa_abi::consts::MAX_PATH_LENGTH);
315 unsafe {
316 buffer.set_len(buffer.capacity());
317 }
318
319 let mut dest_len: usize = 0xAAAAAAAAAAAAAAAAusize;
320 let len = err_from_u16!(
321 sysgetcwd(buffer.as_mut_ptr(), buffer.len(), &raw mut dest_len),
322 dest_len
323 )?;
324
325 buffer.truncate(len);
326 unsafe { Ok(String::from_utf8_unchecked(buffer)) }
327}
328
329define_syscall! {
330 SyscallNum::SysShutdown => {
331 sysshutdown() unreachable
333 },
334 SyscallNum::SysReboot => {
335 sysreboot() unreachable
337 }
338}
339
340#[inline]
341pub fn shutdown() -> ! {
342 sysshutdown()
343}
344
345#[inline]
346pub fn reboot() -> ! {
347 sysreboot()
348}
349
350#[cfg_attr(
352 not(any(feature = "std", feature = "rustc-dep-of-std")),
353 unsafe(no_mangle)
354)]
355#[inline(always)]
356extern "C" fn syspspawn(
363 name_ptr: OptionalStrPtr,
364 name_len: usize,
365 path_ptr: StrPtr,
366 path_len: usize,
367 argv_ptr: OptionalPtrMut<RawSlice<u8>>,
368 argv_len: usize,
369 flags: SpawnFlags,
370 dest_pid: OptionalPtrMut<Pid>,
371 stdin: Optional<usize>,
372 stdout: Optional<usize>,
373 stderr: Optional<usize>,
374) -> SyscallResult {
375 use safa_abi::raw::processes::SpawnConfig;
376 use safa_abi::raw::processes::TaskMetadata;
377 let (mut stdin, mut stdout, mut stderr): (Option<_>, Option<_>, Option<_>) =
378 (stdin.into(), stdout.into(), stderr.into());
379
380 let metadata = {
381 if stdin.is_none() && stdout.is_none() && stderr.is_none() {
382 None
383 } else {
384 stdout.get_or_insert_with(|| sysmeta_stdout());
385 stdin.get_or_insert_with(|| sysmeta_stdin());
386 stderr.get_or_insert_with(|| sysmeta_stderr());
387
388 Some(TaskMetadata::new(stdout, stdin, stderr))
389 }
390 };
391
392 let metadata = metadata.as_ref();
393 let meta_ptr = metadata.map(|m| m as *const _).unwrap_or(core::ptr::null());
394
395 let config = SpawnConfig {
396 version: 1,
397 name: unsafe { RawSlice::from_raw_parts(name_ptr, name_len) },
398 argv: unsafe { RawSliceMut::from_raw_parts(argv_ptr, argv_len) },
399 flags,
400 metadata: meta_ptr,
401 };
402 syscall!(
403 SyscallNum::SysPSpawn,
404 path_ptr as usize,
405 path_len,
406 (&raw const config) as usize,
407 dest_pid as *mut _ as usize,
408 )
409}
410
411#[inline]
418pub unsafe fn unsafe_pspawn(
419 name: Option<&str>,
420 path: &str,
421 argv: *mut [&str],
422 flags: SpawnFlags,
423 stdin: Option<usize>,
424 stdout: Option<usize>,
425 stderr: Option<usize>,
426) -> Result<usize, ErrorStatus> {
427 let mut pid = 0;
428
429 let name = name.map(|s| s.as_bytes());
430 let name_ptr = name.map(|s| s.as_ptr()).unwrap_or(ptr::null());
431 let name_len = name.map(|s| s.len()).unwrap_or(0);
432
433 let argv: *mut [&[u8]] = argv as *mut [&[u8]];
434 let argv = unsafe { RawSliceMut::from_slices(argv) };
435 err_from_u16!(
436 syspspawn(
437 name_ptr,
438 name_len,
439 path.as_ptr(),
440 path.len(),
441 argv.as_mut_ptr(),
442 argv.len(),
443 flags,
444 &mut pid,
445 stdin.into(),
446 stdout.into(),
447 stderr.into(),
448 ),
449 pid
450 )
451}
452
453#[inline]
455pub fn pspawn(
456 name: Option<&str>,
457 path: &str,
458 mut argv: Vec<&str>,
459 flags: SpawnFlags,
460 stdin: Option<usize>,
461 stdout: Option<usize>,
462 stderr: Option<usize>,
463) -> Result<usize, ErrorStatus> {
464 let argv: &mut [&str] = &mut argv;
465 unsafe { unsafe_pspawn(name, path, argv as *mut _, flags, stdin, stdout, stderr) }
466}