mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Add and refactor read-write syscalls
This commit is contained in:
parent
e8a3e00dec
commit
12db7ec55d
@ -38,8 +38,8 @@ provided by Linux on x86-64 architecture.
|
||||
| 15 | rt_sigreturn | ✅ |
|
||||
| 16 | ioctl | ✅ |
|
||||
| 17 | pread64 | ✅ |
|
||||
| 18 | pwrite64 | ❌ |
|
||||
| 19 | readv | ❌ |
|
||||
| 18 | pwrite64 | ✅ |
|
||||
| 19 | readv | ✅ |
|
||||
| 20 | writev | ✅ |
|
||||
| 21 | access | ✅ |
|
||||
| 22 | pipe | ✅ |
|
||||
@ -315,8 +315,8 @@ provided by Linux on x86-64 architecture.
|
||||
| 292 | dup3 | ✅ |
|
||||
| 293 | pipe2 | ✅ |
|
||||
| 294 | inotify_init1 | ❌ |
|
||||
| 295 | preadv | ❌ |
|
||||
| 296 | pwritev | ❌ |
|
||||
| 295 | preadv | ✅ |
|
||||
| 296 | pwritev | ✅ |
|
||||
| 297 | rt_tgsigqueueinfo | ❌ |
|
||||
| 298 | perf_event_open | ❌ |
|
||||
| 299 | recvmmsg | ❌ |
|
||||
@ -336,6 +336,8 @@ provided by Linux on x86-64 architecture.
|
||||
| 313 | finit_module | ❌ |
|
||||
| 318 | getrandom | ✅ |
|
||||
| 322 | execveat | ✅ |
|
||||
| 327 | preadv2 | ✅ |
|
||||
| 328 | pwritev2 | ✅ |
|
||||
| 435 | clone3 | ✅ |
|
||||
|
||||
## File Systems
|
||||
|
@ -32,7 +32,7 @@ pub trait FileLike: Send + Sync + Any {
|
||||
///
|
||||
/// [`read`]: FileLike::read
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
return_errno_with_message!(Errno::EINVAL, "read_at is not supported");
|
||||
return_errno_with_message!(Errno::ESPIPE, "read_at is not supported");
|
||||
}
|
||||
|
||||
/// Write at the given file offset.
|
||||
@ -43,7 +43,7 @@ pub trait FileLike: Send + Sync + Any {
|
||||
///
|
||||
/// [`write`]: FileLike::write
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
return_errno_with_message!(Errno::EINVAL, "write_at is not supported");
|
||||
return_errno_with_message!(Errno::ESPIPE, "write_at is not supported");
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||
|
@ -66,7 +66,10 @@ use crate::syscall::{
|
||||
poll::sys_poll,
|
||||
prctl::sys_prctl,
|
||||
pread64::sys_pread64,
|
||||
preadv::{sys_preadv, sys_preadv2, sys_readv},
|
||||
prlimit64::sys_prlimit64,
|
||||
pwrite64::sys_pwrite64,
|
||||
pwritev::{sys_pwritev, sys_pwritev2, sys_writev},
|
||||
read::sys_read,
|
||||
readlink::{sys_readlink, sys_readlinkat},
|
||||
recvfrom::sys_recvfrom,
|
||||
@ -121,7 +124,6 @@ use crate::syscall::{
|
||||
wait4::sys_wait4,
|
||||
waitid::sys_waitid,
|
||||
write::sys_write,
|
||||
writev::sys_writev,
|
||||
};
|
||||
|
||||
impl_syscall_nums_and_dispatch_fn! {
|
||||
@ -143,6 +145,8 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_RT_SIGRETURN = 15 => sys_rt_sigreturn(args[..0], &mut context);
|
||||
SYS_IOCTL = 16 => sys_ioctl(args[..3]);
|
||||
SYS_PREAD64 = 17 => sys_pread64(args[..4]);
|
||||
SYS_PWRITE64 = 18 => sys_pwrite64(args[..4]);
|
||||
SYS_READV = 19 => sys_readv(args[..3]);
|
||||
SYS_WRITEV = 20 => sys_writev(args[..3]);
|
||||
SYS_ACCESS = 21 => sys_access(args[..2]);
|
||||
SYS_PIPE = 22 => sys_pipe(args[..1]);
|
||||
@ -282,8 +286,12 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_EPOLL_CREATE1 = 291 => sys_epoll_create1(args[..1]);
|
||||
SYS_DUP3 = 292 => sys_dup3(args[..3]);
|
||||
SYS_PIPE2 = 293 => sys_pipe2(args[..2]);
|
||||
SYS_PREADV = 295 => sys_preadv(args[..4]);
|
||||
SYS_PWRITEV = 296 => sys_pwritev(args[..4]);
|
||||
SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]);
|
||||
SYS_GETRANDOM = 318 => sys_getrandom(args[..3]);
|
||||
SYS_EXECVEAT = 322 => sys_execveat(args[..5], &mut context);
|
||||
SYS_PREADV2 = 327 => sys_preadv2(args[..5]);
|
||||
SYS_PWRITEV2 = 328 => sys_pwritev2(args[..5]);
|
||||
SYS_CLONE3 = 435 => sys_clone3(args[..2], &context);
|
||||
}
|
||||
|
@ -73,7 +73,10 @@ mod pipe;
|
||||
mod poll;
|
||||
mod prctl;
|
||||
mod pread64;
|
||||
mod preadv;
|
||||
mod prlimit64;
|
||||
mod pwrite64;
|
||||
mod pwritev;
|
||||
mod read;
|
||||
mod readlink;
|
||||
mod recvfrom;
|
||||
@ -128,7 +131,6 @@ mod utimens;
|
||||
mod wait4;
|
||||
mod waitid;
|
||||
mod write;
|
||||
mod writev;
|
||||
|
||||
/// This macro is used to define syscall handler.
|
||||
/// The first param is ths number of parameters,
|
||||
|
@ -1,29 +1,39 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
fs::{file_table::FileDesc, utils::SeekFrom},
|
||||
prelude::*,
|
||||
util::write_bytes_to_user,
|
||||
};
|
||||
use crate::{fs::file_table::FileDesc, prelude::*, util::write_bytes_to_user};
|
||||
|
||||
pub fn sys_pread64(fd: FileDesc, buf_ptr: Vaddr, count: usize, pos: i64) -> Result<SyscallReturn> {
|
||||
pub fn sys_pread64(
|
||||
fd: FileDesc,
|
||||
user_buf_ptr: Vaddr,
|
||||
user_buf_len: usize,
|
||||
offset: i64,
|
||||
) -> Result<SyscallReturn> {
|
||||
debug!(
|
||||
"fd = {}, buf = 0x{:x}, count = 0x{:x}, pos = 0x{:x}",
|
||||
fd, buf_ptr, count, pos
|
||||
"fd = {}, buf = 0x{:x}, user_buf_len = 0x{:x}, offset = 0x{:x}",
|
||||
fd, user_buf_ptr, user_buf_len, offset
|
||||
);
|
||||
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let file = file_table.get_file(fd)?;
|
||||
|
||||
let seek_from = SeekFrom::Start(pos as usize);
|
||||
file.seek(seek_from)?;
|
||||
if offset < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset cannot be negative");
|
||||
}
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
// TODO: Check (f.file->f_mode & FMODE_PREAD); We don't have f_mode in our FileLike trait
|
||||
if user_buf_len == 0 {
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
if offset.checked_add(user_buf_len as i64).is_none() {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset + user_buf_len overflow");
|
||||
}
|
||||
|
||||
let read_len = {
|
||||
let mut buffer = vec![0u8; count];
|
||||
let read_len = file.read(&mut buffer)?;
|
||||
write_bytes_to_user(buf_ptr, &buffer)?;
|
||||
let mut buffer = vec![0u8; user_buf_len];
|
||||
let read_len = file.read_at(offset as usize, &mut buffer)?;
|
||||
write_bytes_to_user(user_buf_ptr, &buffer)?;
|
||||
read_len
|
||||
};
|
||||
|
||||
|
171
kernel/aster-nix/src/syscall/preadv.rs
Normal file
171
kernel/aster-nix/src/syscall/preadv.rs
Normal file
@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
fs::file_table::FileDesc,
|
||||
prelude::*,
|
||||
util::{copy_iovs_from_user, IoVec},
|
||||
};
|
||||
|
||||
pub fn sys_readv(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<SyscallReturn> {
|
||||
let res = do_sys_readv(fd, io_vec_ptr, io_vec_count)?;
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
pub fn sys_preadv(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
) -> Result<SyscallReturn> {
|
||||
let res = do_sys_preadv(fd, io_vec_ptr, io_vec_count, offset, RWFFlag::empty())?;
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
pub fn sys_preadv2(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
flags: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
let flags = match RWFFlag::from_bits(flags) {
|
||||
Some(flags) => flags,
|
||||
None => return_errno_with_message!(Errno::EINVAL, "invalid flags"),
|
||||
};
|
||||
let res = if offset == -1 {
|
||||
do_sys_readv(fd, io_vec_ptr, io_vec_count)?
|
||||
} else {
|
||||
do_sys_preadv(fd, io_vec_ptr, io_vec_count, offset, flags)?
|
||||
};
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
fn do_sys_preadv(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
_flags: RWFFlag,
|
||||
) -> Result<usize> {
|
||||
debug!(
|
||||
"preadv: fd = {}, io_vec_ptr = 0x{:x}, io_vec_counter = 0x{:x}, offset = 0x{:x}",
|
||||
fd, io_vec_ptr, io_vec_count, offset
|
||||
);
|
||||
|
||||
if offset < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset cannot be negative");
|
||||
}
|
||||
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
|
||||
if io_vec_count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Calculate the total buffer length and check for overflow
|
||||
let total_len = io_vec_count
|
||||
.checked_mul(core::mem::size_of::<IoVec>())
|
||||
.and_then(|val| val.checked_add(offset as usize));
|
||||
if total_len.is_none() {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset + io_vec_count overflow");
|
||||
}
|
||||
|
||||
let mut total_len: usize = 0;
|
||||
let mut cur_offset = offset as usize;
|
||||
|
||||
let io_vecs = copy_iovs_from_user(io_vec_ptr, io_vec_count)?;
|
||||
for io_vec in io_vecs.as_ref() {
|
||||
if io_vec.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if total_len.checked_add(io_vec.len()).is_none()
|
||||
|| total_len
|
||||
.checked_add(io_vec.len())
|
||||
.and_then(|sum| sum.checked_add(cur_offset))
|
||||
.is_none()
|
||||
|| total_len
|
||||
.checked_add(io_vec.len())
|
||||
.and_then(|sum| sum.checked_add(cur_offset))
|
||||
.map(|sum| sum > isize::MAX as usize)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return_errno_with_message!(Errno::EINVAL, "Total length overflow");
|
||||
}
|
||||
|
||||
let mut buffer = vec![0u8; io_vec.len()];
|
||||
|
||||
// TODO: According to the man page
|
||||
// at <https://man7.org/linux/man-pages/man2/readv.2.html>,
|
||||
// readv must be atomic,
|
||||
// but the current implementation does not ensure atomicity.
|
||||
// A suitable fix would be to add a `readv` method for the `FileLike` trait,
|
||||
// allowing each subsystem to implement atomicity.
|
||||
let read_len = file.read_at(cur_offset, &mut buffer)?;
|
||||
io_vec.write_exact_to_user(&buffer)?;
|
||||
total_len += read_len;
|
||||
cur_offset += read_len;
|
||||
if read_len == 0 || read_len < buffer.len() {
|
||||
// End of file reached or no more data to read
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn do_sys_readv(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<usize> {
|
||||
debug!(
|
||||
"fd = {}, io_vec_ptr = 0x{:x}, io_vec_counter = 0x{:x}",
|
||||
fd, io_vec_ptr, io_vec_count
|
||||
);
|
||||
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
|
||||
if io_vec_count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let mut total_len = 0;
|
||||
|
||||
let io_vecs = copy_iovs_from_user(io_vec_ptr, io_vec_count)?;
|
||||
for io_vec in io_vecs.as_ref() {
|
||||
if io_vec.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut buffer = vec![0u8; io_vec.len()];
|
||||
// TODO: According to the man page
|
||||
// at <https://man7.org/linux/man-pages/man2/readv.2.html>,
|
||||
// readv must be atomic,
|
||||
// but the current implementation does not ensure atomicity.
|
||||
// A suitable fix would be to add a `readv` method for the `FileLike` trait,
|
||||
// allowing each subsystem to implement atomicity.
|
||||
let read_len = file.read(&mut buffer)?;
|
||||
io_vec.write_exact_to_user(&buffer)?;
|
||||
total_len += read_len;
|
||||
if read_len == 0 || read_len < buffer.len() {
|
||||
// End of file reached or no more data to read
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct RWFFlag: u32 {
|
||||
const RWF_DSYNC = 0x00000001;
|
||||
const RWF_HIPRI = 0x00000002;
|
||||
const RWF_SYNC = 0x00000004;
|
||||
const RWF_NOWAIT = 0x00000008;
|
||||
}
|
||||
}
|
36
kernel/aster-nix/src/syscall/pwrite64.rs
Normal file
36
kernel/aster-nix/src/syscall/pwrite64.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{fs::file_table::FileDesc, prelude::*, util::read_bytes_from_user};
|
||||
|
||||
pub fn sys_pwrite64(
|
||||
fd: FileDesc,
|
||||
user_buf_ptr: Vaddr,
|
||||
user_buf_len: usize,
|
||||
offset: i64,
|
||||
) -> Result<SyscallReturn> {
|
||||
debug!(
|
||||
"fd = {}, user_buf_ptr = 0x{:x}, user_buf_len = 0x{:x}, offset = 0x{:x}",
|
||||
fd, user_buf_ptr, user_buf_len, offset
|
||||
);
|
||||
if offset < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset cannot be negative");
|
||||
}
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
// TODO: Check (f.file->f_mode & FMODE_PWRITE); We don't have f_mode in our FileLike trait
|
||||
if user_buf_len == 0 {
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
if offset.checked_add(user_buf_len as i64).is_none() {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset + user_buf_len overflow");
|
||||
}
|
||||
|
||||
let mut buffer = vec![0u8; user_buf_len];
|
||||
read_bytes_from_user(user_buf_ptr, &mut buffer)?;
|
||||
let write_len = file.write_at(offset as _, &buffer)?;
|
||||
Ok(SyscallReturn::Return(write_len as _))
|
||||
}
|
149
kernel/aster-nix/src/syscall/pwritev.rs
Normal file
149
kernel/aster-nix/src/syscall/pwritev.rs
Normal file
@ -0,0 +1,149 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{fs::file_table::FileDesc, prelude::*, util::copy_iovs_from_user};
|
||||
|
||||
pub fn sys_writev(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<SyscallReturn> {
|
||||
let res = do_sys_writev(fd, io_vec_ptr, io_vec_count)?;
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
pub fn sys_pwritev(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
) -> Result<SyscallReturn> {
|
||||
let res = do_sys_pwritev(fd, io_vec_ptr, io_vec_count, offset, RWFFlag::empty())?;
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
pub fn sys_pwritev2(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
flags: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
let flags = match RWFFlag::from_bits(flags) {
|
||||
Some(flags) => flags,
|
||||
None => return_errno_with_message!(Errno::EINVAL, "invalid flags"),
|
||||
};
|
||||
let res = if offset == -1 {
|
||||
do_sys_writev(fd, io_vec_ptr, io_vec_count)?
|
||||
} else {
|
||||
do_sys_pwritev(fd, io_vec_ptr, io_vec_count, offset, flags)?
|
||||
};
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
fn do_sys_pwritev(
|
||||
fd: FileDesc,
|
||||
io_vec_ptr: Vaddr,
|
||||
io_vec_count: usize,
|
||||
offset: i64,
|
||||
_flags: RWFFlag,
|
||||
) -> Result<usize> {
|
||||
// TODO: Implement flags support
|
||||
debug!(
|
||||
"fd = {}, io_vec_ptr = 0x{:x}, io_vec_counter = 0x{:x}, offset = 0x{:x}",
|
||||
fd, io_vec_ptr, io_vec_count, offset
|
||||
);
|
||||
if offset < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "offset cannot be negative");
|
||||
}
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
// TODO: Check (f.file->f_mode & FMODE_PREAD); We don't have f_mode in our FileLike trait
|
||||
if io_vec_count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let mut total_len: usize = 0;
|
||||
let mut cur_offset = offset as usize;
|
||||
|
||||
let io_vecs = copy_iovs_from_user(io_vec_ptr, io_vec_count)?;
|
||||
for io_vec in io_vecs.as_ref() {
|
||||
if io_vec.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if total_len.checked_add(io_vec.len()).is_none()
|
||||
|| total_len
|
||||
.checked_add(io_vec.len())
|
||||
.and_then(|sum| sum.checked_add(cur_offset))
|
||||
.is_none()
|
||||
|| total_len
|
||||
.checked_add(io_vec.len())
|
||||
.and_then(|sum| sum.checked_add(cur_offset))
|
||||
.map(|sum| sum > isize::MAX as usize)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return_errno_with_message!(Errno::EINVAL, "Total length overflow");
|
||||
}
|
||||
|
||||
let buffer = {
|
||||
let mut buffer = vec![0u8; io_vec.len()];
|
||||
io_vec.read_exact_from_user(&mut buffer)?;
|
||||
buffer
|
||||
};
|
||||
|
||||
// TODO: According to the man page
|
||||
// at <https://man7.org/linux/man-pages/man2/readv.2.html>,
|
||||
// writev must be atomic,
|
||||
// but the current implementation does not ensure atomicity.
|
||||
// A suitable fix would be to add a `writev` method for the `FileLike` trait,
|
||||
// allowing each subsystem to implement atomicity.
|
||||
let write_len = file.write_at(cur_offset, &buffer)?;
|
||||
total_len += write_len;
|
||||
cur_offset += write_len;
|
||||
}
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn do_sys_writev(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<usize> {
|
||||
debug!(
|
||||
"fd = {}, io_vec_ptr = 0x{:x}, io_vec_counter = 0x{:x}",
|
||||
fd, io_vec_ptr, io_vec_count
|
||||
);
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
let mut total_len = 0;
|
||||
|
||||
let io_vecs = copy_iovs_from_user(io_vec_ptr, io_vec_count)?;
|
||||
for io_vec in io_vecs.as_ref() {
|
||||
if io_vec.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let buffer = {
|
||||
let mut buffer = vec![0u8; io_vec.len()];
|
||||
io_vec.read_exact_from_user(&mut buffer)?;
|
||||
buffer
|
||||
};
|
||||
|
||||
// TODO: According to the man page
|
||||
// at <https://man7.org/linux/man-pages/man2/readv.2.html>,
|
||||
// writev must be atomic,
|
||||
// but the current implementation does not ensure atomicity.
|
||||
// A suitable fix would be to add a `writev` method for the `FileLike` trait,
|
||||
// allowing each subsystem to implement atomicity.
|
||||
let write_len = file.write(&buffer)?;
|
||||
total_len += write_len;
|
||||
}
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
struct RWFFlag: u32 {
|
||||
const RWF_DSYNC = 0x00000001;
|
||||
const RWF_HIPRI = 0x00000002;
|
||||
const RWF_SYNC = 0x00000004;
|
||||
const RWF_NOWAIT = 0x00000008;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{fs::file_table::FileDesc, prelude::*, util::copy_iovs_from_user};
|
||||
|
||||
pub fn sys_writev(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<SyscallReturn> {
|
||||
let res = do_sys_writev(fd, io_vec_ptr, io_vec_count)?;
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
fn do_sys_writev(fd: FileDesc, io_vec_ptr: Vaddr, io_vec_count: usize) -> Result<usize> {
|
||||
debug!(
|
||||
"fd = {}, io_vec_ptr = 0x{:x}, io_vec_counter = 0x{:x}",
|
||||
fd, io_vec_ptr, io_vec_count
|
||||
);
|
||||
let file = {
|
||||
let current = current!();
|
||||
let filetable = current.file_table().lock();
|
||||
filetable.get_file(fd)?.clone()
|
||||
};
|
||||
|
||||
let mut total_len = 0;
|
||||
|
||||
let io_vecs = copy_iovs_from_user(io_vec_ptr, io_vec_count)?;
|
||||
for io_vec in io_vecs.as_ref() {
|
||||
if io_vec.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let buffer = {
|
||||
let mut buffer = vec![0u8; io_vec.len()];
|
||||
io_vec.read_exact_from_user(&mut buffer)?;
|
||||
buffer
|
||||
};
|
||||
|
||||
// FIXME: According to the man page
|
||||
// at <https://man7.org/linux/man-pages/man2/readv.2.html>,
|
||||
// writev must be atomic,
|
||||
// but the current implementation does not ensure atomicity.
|
||||
// A suitable fix would be to add a `writev` method for the `FileLike` trait,
|
||||
// allowing each subsystem to implement atomicity.
|
||||
let write_len = file.write(&buffer)?;
|
||||
total_len += write_len;
|
||||
}
|
||||
Ok(total_len)
|
||||
}
|
@ -24,19 +24,13 @@ TESTS ?= \
|
||||
mount_test \
|
||||
open_create_test \
|
||||
open_test \
|
||||
pread64_test \
|
||||
preadv2_test \
|
||||
pwrite64_test \
|
||||
pwritev2_test \
|
||||
pty_test \
|
||||
read_test \
|
||||
rename_test \
|
||||
sendfile_test \
|
||||
stat_test \
|
||||
statfs_test \
|
||||
symlink_test \
|
||||
sync_test \
|
||||
timers_test \
|
||||
truncate_test \
|
||||
uidgid_test \
|
||||
unlink_test \
|
||||
vdso_clock_gettime_test \
|
||||
readv_test \
|
||||
write_test \
|
||||
utimes_test \
|
||||
# The end of the list
|
||||
|
@ -1,3 +1,2 @@
|
||||
EventfdTest.IllegalPwrite
|
||||
EventfdTest.SpliceFromPipePartialSucceeds
|
||||
EventfdTest.NotifyNonZero_NoRandomSave
|
1
regression/syscall_test/blocklists/pread64_test
Normal file
1
regression/syscall_test/blocklists/pread64_test
Normal file
@ -0,0 +1 @@
|
||||
Pread64Test.Overflow
|
3
regression/syscall_test/blocklists/preadv2_test
Normal file
3
regression/syscall_test/blocklists/preadv2_test
Normal file
@ -0,0 +1,3 @@
|
||||
Preadv2Test.TestInvalidFlag
|
||||
Preadv2Test.TestUnreadableFile
|
||||
Preadv2Test.TestUnseekableFileInvalid
|
1
regression/syscall_test/blocklists/pwritev2_test
Normal file
1
regression/syscall_test/blocklists/pwritev2_test
Normal file
@ -0,0 +1 @@
|
||||
Pwritev2Test.InvalidFlag
|
5
regression/syscall_test/blocklists/readv_test
Normal file
5
regression/syscall_test/blocklists/readv_test
Normal file
@ -0,0 +1,5 @@
|
||||
ReadvTest.BadIovecBase_File
|
||||
ReadvTest.BadIovecBase_Pipe
|
||||
ReadvTest.NotReadable_Pipe
|
||||
ReadvTest.IovecOutsideTaskAddressRangeInNonemptyArray
|
||||
ReadvTestNoFixture.TruncatedAtMax_NoRandomSave
|
Loading…
x
Reference in New Issue
Block a user