arceos_posix_api/imp/
io.rs

1use crate::ctypes;
2use axerrno::{LinuxError, LinuxResult};
3use core::ffi::{c_int, c_void};
4
5#[cfg(feature = "fd")]
6use crate::imp::fd_ops::get_file_like;
7#[cfg(not(feature = "fd"))]
8use axio::prelude::*;
9
10/// Read data from the file indicated by `fd`.
11///
12/// Return the read size if success.
13pub fn sys_read(fd: c_int, buf: *mut c_void, count: usize) -> ctypes::ssize_t {
14    debug!("sys_read <= {} {:#x} {}", fd, buf as usize, count);
15    syscall_body!(sys_read, {
16        if buf.is_null() {
17            return Err(LinuxError::EFAULT);
18        }
19        let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, count) };
20        #[cfg(feature = "fd")]
21        {
22            Ok(get_file_like(fd)?.read(dst)? as ctypes::ssize_t)
23        }
24        #[cfg(not(feature = "fd"))]
25        match fd {
26            0 => Ok(super::stdio::stdin().read(dst)? as ctypes::ssize_t),
27            1 | 2 => Err(LinuxError::EPERM),
28            _ => Err(LinuxError::EBADF),
29        }
30    })
31}
32
33fn write_impl(fd: c_int, buf: *const c_void, count: usize) -> LinuxResult<ctypes::ssize_t> {
34    if buf.is_null() {
35        return Err(LinuxError::EFAULT);
36    }
37    let src = unsafe { core::slice::from_raw_parts(buf as *const u8, count) };
38    #[cfg(feature = "fd")]
39    {
40        Ok(get_file_like(fd)?.write(src)? as ctypes::ssize_t)
41    }
42    #[cfg(not(feature = "fd"))]
43    match fd {
44        0 => Err(LinuxError::EPERM),
45        1 | 2 => Ok(super::stdio::stdout().write(src)? as ctypes::ssize_t),
46        _ => Err(LinuxError::EBADF),
47    }
48}
49
50/// Write data to the file indicated by `fd`.
51///
52/// Return the written size if success.
53pub fn sys_write(fd: c_int, buf: *const c_void, count: usize) -> ctypes::ssize_t {
54    debug!("sys_write <= {} {:#x} {}", fd, buf as usize, count);
55    syscall_body!(sys_write, write_impl(fd, buf, count))
56}
57
58/// Write a vector.
59pub unsafe fn sys_writev(fd: c_int, iov: *const ctypes::iovec, iocnt: c_int) -> ctypes::ssize_t {
60    debug!("sys_writev <= fd: {}", fd);
61    syscall_body!(sys_writev, {
62        if !(0..=1024).contains(&iocnt) {
63            return Err(LinuxError::EINVAL);
64        }
65
66        let iovs = unsafe { core::slice::from_raw_parts(iov, iocnt as usize) };
67        let mut ret = 0;
68        for iov in iovs.iter() {
69            let result = write_impl(fd, iov.iov_base, iov.iov_len)?;
70            ret += result;
71
72            if result < iov.iov_len as isize {
73                break;
74            }
75        }
76
77        Ok(ret)
78    })
79}