Skip to main content

strat9_kernel/syscall/
fcntl.rs

1//! `fcntl()` syscall implementation for file descriptor control.
2//!
3//! Provides fcntl operations for file descriptor flags (CLOEXEC).
4
5use crate::{process::current_task_clone, syscall::error::SyscallError};
6
7// fcntl commands
8pub 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
14// File descriptor flags
15pub const FD_CLOEXEC: u64 = 1;
16
17/// SYS_FCNTL (313): manipulate file descriptor.
18///
19/// Supported commands:
20/// - F_GETFD (1): Get file descriptor flags
21/// - F_SETFD (2): Set file descriptor flags (FD_CLOEXEC)
22pub fn sys_fcntl(fd: u64, cmd: u64, arg: u64) -> Result<u64, SyscallError> {
23    if fd > u32::MAX as u64 {
24        return Err(SyscallError::BadHandle);
25    }
26    let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
27
28    match cmd {
29        F_GETFD => {
30            // Get file descriptor flags
31            unsafe {
32                let fd_table = &*task.process.fd_table.get();
33                let cloexec = fd_table.get_cloexec(fd as u32)?;
34                Ok(if cloexec { FD_CLOEXEC } else { 0 })
35            }
36        }
37        F_SETFD => {
38            // Set file descriptor flags
39            unsafe {
40                let fd_table = &mut *task.process.fd_table.get();
41                let cloexec = (arg & FD_CLOEXEC) != 0;
42                fd_table.set_cloexec(fd as u32, cloexec)?;
43                Ok(0)
44            }
45        }
46        F_DUPFD => {
47            if arg > u32::MAX as u64 {
48                return Err(SyscallError::InvalidArgument);
49            }
50            unsafe {
51                let fd_table = &mut *task.process.fd_table.get();
52                let new_fd = fd_table.duplicate_from(fd as u32, arg as u32)?;
53                Ok(new_fd as u64)
54            }
55        }
56        F_GETFL | F_SETFL => {
57            // Get/set file status flags (not implemented yet)
58            Err(SyscallError::NotImplemented)
59        }
60        _ => Err(SyscallError::InvalidArgument),
61    }
62}