diff --git a/src/services/libs/jinux-std/src/fs/file_handle/file.rs b/src/services/libs/jinux-std/src/fs/file_handle/file.rs index 69e1a33de..4a5a8be9e 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/file.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/file.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use crate::tty::get_n_tty; use core::any::Any; -use crate::fs::utils::{IoEvents, IoctlCmd, Metadata}; +use crate::fs::utils::{IoEvents, IoctlCmd, Metadata, SeekFrom}; /// The basic operations defined on a file pub trait File: Send + Sync + Any { @@ -36,4 +36,8 @@ pub trait File: Send + Sync + Any { fn metadata(&self) -> Metadata { panic!("metadata unsupported"); } + + fn seek(&self, seek_from: SeekFrom) -> Result { + panic!("seek unsupported"); + } } diff --git a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs index 11b8c5680..558c74a48 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs @@ -70,28 +70,28 @@ impl InodeHandle_ { pub fn seek(&self, pos: SeekFrom) -> Result { let mut offset = self.offset.lock(); - let new_offset: i64 = match pos { - SeekFrom::Start(off /* as u64 */) => { - if off > i64::max_value() as u64 { + let new_offset: isize = match pos { + SeekFrom::Start(off /* as usize */) => { + if off > isize::max_value() as usize { return_errno_with_message!(Errno::EINVAL, "file offset is too large"); } - off as i64 + off as isize } - SeekFrom::End(off /* as i64 */) => { - let file_size = self.dentry.vnode().inode().metadata().size as i64; + SeekFrom::End(off /* as isize */) => { + let file_size = self.dentry.vnode().inode().metadata().size as isize; assert!(file_size >= 0); file_size .checked_add(off) .ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))? } - SeekFrom::Current(off /* as i64 */) => (*offset as i64) + SeekFrom::Current(off /* as isize */) => (*offset as isize) .checked_add(off) .ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?, }; if new_offset < 0 { return_errno_with_message!(Errno::EINVAL, "file offset must not be negative"); } - // Invariant: 0 <= new_offset <= i64::max_value() + // Invariant: 0 <= new_offset <= isize::max_value() let new_offset = new_offset as usize; *offset = new_offset; Ok(new_offset) diff --git a/src/services/libs/jinux-std/src/fs/file_handle/mod.rs b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs index 8ef1625e2..d588c3f41 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/mod.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs @@ -3,7 +3,7 @@ mod file; mod inode_handle; -use crate::fs::utils::Metadata; +use crate::fs::utils::{Metadata, SeekFrom}; use crate::prelude::*; use crate::rights::{ReadOp, WriteOp}; use alloc::sync::Arc; @@ -74,6 +74,13 @@ impl FileHandle { } } + pub fn seek(&self, seek_from: SeekFrom) -> Result { + match &self.inner { + Inner::File(file) => file.seek(seek_from), + Inner::Inode(inode_handle) => inode_handle.seek(seek_from), + } + } + pub fn clean_for_close(&self) -> Result<()> { match &self.inner { Inner::Inode(inode_handle) => { diff --git a/src/services/libs/jinux-std/src/fs/stdio.rs b/src/services/libs/jinux-std/src/fs/stdio.rs index 4d6b2b452..5ef7da837 100644 --- a/src/services/libs/jinux-std/src/fs/stdio.rs +++ b/src/services/libs/jinux-std/src/fs/stdio.rs @@ -3,7 +3,7 @@ use crate::tty::{get_n_tty, Tty}; use super::file_handle::File; use super::file_table::FileDescripter; -use super::utils::{InodeMode, InodeType, IoEvents, Metadata}; +use super::utils::{InodeMode, InodeType, IoEvents, Metadata, SeekFrom}; pub const FD_STDIN: FileDescripter = 0; pub const FD_STDOUT: FileDescripter = 1; @@ -46,6 +46,11 @@ impl File for Stdin { } } + fn seek(&self, seek_from: SeekFrom) -> Result { + // TODO: do real seek + Ok(0) + } + fn metadata(&self) -> Metadata { Metadata { dev: 0, @@ -82,6 +87,11 @@ impl File for Stdout { } } + fn seek(&self, seek_from: SeekFrom) -> Result { + // TODO: do real seek + Ok(0) + } + fn metadata(&self) -> Metadata { Metadata { dev: 0, @@ -119,6 +129,11 @@ impl File for Stderr { } } + fn seek(&self, seek_from: SeekFrom) -> Result { + // TODO: do real seek + Ok(0) + } + fn metadata(&self) -> Metadata { Metadata { dev: 0, diff --git a/src/services/libs/jinux-std/src/fs/utils/mod.rs b/src/services/libs/jinux-std/src/fs/utils/mod.rs index 99461d92c..23dad11c0 100644 --- a/src/services/libs/jinux-std/src/fs/utils/mod.rs +++ b/src/services/libs/jinux-std/src/fs/utils/mod.rs @@ -32,9 +32,9 @@ mod vnode; #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum SeekFrom { - Start(u64), - End(i64), - Current(i64), + Start(usize), + End(isize), + Current(isize), } /// Maximum bytes in a path diff --git a/src/services/libs/jinux-std/src/syscall/lseek.rs b/src/services/libs/jinux-std/src/syscall/lseek.rs index 6cf8b897c..d37e28460 100644 --- a/src/services/libs/jinux-std/src/syscall/lseek.rs +++ b/src/services/libs/jinux-std/src/syscall/lseek.rs @@ -1,12 +1,27 @@ +use crate::fs::{file_table::FileDescripter, utils::SeekFrom}; use crate::log_syscall_entry; -use crate::{fs::file_table::FileDescripter, prelude::*}; +use crate::prelude::*; use super::SyscallReturn; use super::SYS_LSEEK; -pub fn sys_lseek(fd: FileDescripter, offset: usize, whence: u32) -> Result { +pub fn sys_lseek(fd: FileDescripter, offset: isize, whence: u32) -> Result { log_syscall_entry!(SYS_LSEEK); debug!("fd = {}, offset = {}, whence = {}", fd, offset, whence); - // TODO: do lseek - Ok(SyscallReturn::Return(0)) + let seek_from = match whence { + 0 => { + if offset < 0 { + return_errno!(Errno::EINVAL); + } + SeekFrom::Start(offset as usize) + } + 1 => SeekFrom::Current(offset), + 2 => SeekFrom::End(offset), + _ => return_errno!(Errno::EINVAL), + }; + let current = current!(); + let file_table = current.file_table().lock(); + let file = file_table.get_file(fd)?; + let offset = file.seek(seek_from)?; + Ok(SyscallReturn::Return(offset as _)) }