strat9_kernel/syscall/
fcntl.rs1use crate::{process::current_task_clone, syscall::error::SyscallError, vfs::scheme::OpenFlags};
6
7pub const F_DUPFD: u64 = 0;
9pub const F_GETFD: u64 = 1;
10pub const F_SETFD: u64 = 2;
11pub const F_GETFL: u64 = 3;
12pub const F_SETFL: u64 = 4;
13
14pub const FD_CLOEXEC: u64 = 1;
16
17pub fn sys_fcntl(fd: u64, cmd: u64, arg: u64) -> Result<u64, SyscallError> {
26 if fd > u32::MAX as u64 {
27 return Err(SyscallError::BadHandle);
28 }
29 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
30
31 match cmd {
32 F_GETFD => unsafe {
33 let fd_table = &*task.process.fd_table.get();
34 let cloexec = fd_table.get_cloexec(fd as u32)?;
35 Ok(if cloexec { FD_CLOEXEC } else { 0 })
36 },
37 F_SETFD => unsafe {
38 let fd_table = &mut *task.process.fd_table.get();
39 let cloexec = (arg & FD_CLOEXEC) != 0;
40 fd_table.set_cloexec(fd as u32, cloexec)?;
41 Ok(0)
42 },
43 F_DUPFD => {
44 if arg > u32::MAX as u64 {
45 return Err(SyscallError::InvalidArgument);
46 }
47 unsafe {
48 let fd_table = &mut *task.process.fd_table.get();
49 let new_fd = fd_table.duplicate_from(fd as u32, arg as u32)?;
50 Ok(new_fd as u64)
51 }
52 }
53 F_GETFL => {
54 let fd_table = unsafe { &*task.process.fd_table.get() };
55 let file = fd_table.get(fd as u32)?;
56 Ok(file.open_flags().bits() as u64)
57 }
58 F_SETFL => {
59 const CHANGEABLE: u32 = OpenFlags::APPEND.bits() | OpenFlags::NONBLOCK.bits();
61 let new_flags = OpenFlags::from_bits_truncate((arg as u32) & CHANGEABLE);
62 unsafe {
63 let fd_table = &mut *task.process.fd_table.get();
64 fd_table.replace_open_flags(fd as u32, new_flags)?;
65 }
66 Ok(0)
67 }
68 _ => Err(SyscallError::InvalidArgument),
69 }
70}