asterinas/kernel/aster-nix/src/syscall/ioctl.rs

44 lines
1.4 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::{
fs::{
file_table::FileDesc,
utils::{IoctlCmd, StatusFlags},
},
prelude::*,
};
pub fn sys_ioctl(fd: FileDesc, cmd: u32, arg: Vaddr) -> Result<SyscallReturn> {
let ioctl_cmd = IoctlCmd::try_from(cmd)?;
debug!(
"fd = {}, ioctl_cmd = {:?}, arg = 0x{:x}",
fd, ioctl_cmd, arg
);
let current = current!();
let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?;
let res = match ioctl_cmd {
IoctlCmd::FIONBIO => {
let is_nonblocking = CurrentUserSpace::get().read_val::<i32>(arg)? != 0;
let mut flags = file.status_flags();
flags.set(StatusFlags::O_NONBLOCK, is_nonblocking);
file.set_status_flags(flags)?;
0
}
IoctlCmd::FIOASYNC => {
let is_async = CurrentUserSpace::get().read_val::<i32>(arg)? != 0;
let mut flags = file.status_flags();
// Set `O_ASYNC` flags will send `SIGIO` signal to a process when
// I/O is possible, user should call `fcntl(fd, F_SETOWN, pid)`
// first to let the kernel know just whom to notify.
flags.set(StatusFlags::O_ASYNC, is_async);
file.set_status_flags(flags)?;
0
}
_ => file.ioctl(ioctl_cmd, arg)?,
};
Ok(SyscallReturn::Return(res as _))
}