Add support for lseek syscall

This commit is contained in:
LI Qing 2023-02-20 16:40:04 +08:00 committed by Tate, Hongliang Tian
parent 116b687cae
commit 4e3dfe93da
6 changed files with 59 additions and 18 deletions

View File

@ -2,7 +2,7 @@ use crate::prelude::*;
use crate::tty::get_n_tty; use crate::tty::get_n_tty;
use core::any::Any; 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 /// The basic operations defined on a file
pub trait File: Send + Sync + Any { pub trait File: Send + Sync + Any {
@ -36,4 +36,8 @@ pub trait File: Send + Sync + Any {
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
panic!("metadata unsupported"); panic!("metadata unsupported");
} }
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
panic!("seek unsupported");
}
} }

View File

@ -70,28 +70,28 @@ impl InodeHandle_ {
pub fn seek(&self, pos: SeekFrom) -> Result<usize> { pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
let mut offset = self.offset.lock(); let mut offset = self.offset.lock();
let new_offset: i64 = match pos { let new_offset: isize = match pos {
SeekFrom::Start(off /* as u64 */) => { SeekFrom::Start(off /* as usize */) => {
if off > i64::max_value() as u64 { if off > isize::max_value() as usize {
return_errno_with_message!(Errno::EINVAL, "file offset is too large"); return_errno_with_message!(Errno::EINVAL, "file offset is too large");
} }
off as i64 off as isize
} }
SeekFrom::End(off /* as i64 */) => { SeekFrom::End(off /* as isize */) => {
let file_size = self.dentry.vnode().inode().metadata().size as i64; let file_size = self.dentry.vnode().inode().metadata().size as isize;
assert!(file_size >= 0); assert!(file_size >= 0);
file_size file_size
.checked_add(off) .checked_add(off)
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))? .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) .checked_add(off)
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?, .ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?,
}; };
if new_offset < 0 { if new_offset < 0 {
return_errno_with_message!(Errno::EINVAL, "file offset must not be negative"); 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; let new_offset = new_offset as usize;
*offset = new_offset; *offset = new_offset;
Ok(new_offset) Ok(new_offset)

View File

@ -3,7 +3,7 @@
mod file; mod file;
mod inode_handle; mod inode_handle;
use crate::fs::utils::Metadata; use crate::fs::utils::{Metadata, SeekFrom};
use crate::prelude::*; use crate::prelude::*;
use crate::rights::{ReadOp, WriteOp}; use crate::rights::{ReadOp, WriteOp};
use alloc::sync::Arc; use alloc::sync::Arc;
@ -74,6 +74,13 @@ impl FileHandle {
} }
} }
pub fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
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<()> { pub fn clean_for_close(&self) -> Result<()> {
match &self.inner { match &self.inner {
Inner::Inode(inode_handle) => { Inner::Inode(inode_handle) => {

View File

@ -3,7 +3,7 @@ use crate::tty::{get_n_tty, Tty};
use super::file_handle::File; use super::file_handle::File;
use super::file_table::FileDescripter; 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_STDIN: FileDescripter = 0;
pub const FD_STDOUT: FileDescripter = 1; pub const FD_STDOUT: FileDescripter = 1;
@ -46,6 +46,11 @@ impl File for Stdin {
} }
} }
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
Metadata { Metadata {
dev: 0, dev: 0,
@ -82,6 +87,11 @@ impl File for Stdout {
} }
} }
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
Metadata { Metadata {
dev: 0, dev: 0,
@ -119,6 +129,11 @@ impl File for Stderr {
} }
} }
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
Metadata { Metadata {
dev: 0, dev: 0,

View File

@ -32,9 +32,9 @@ mod vnode;
#[derive(Copy, PartialEq, Eq, Clone, Debug)] #[derive(Copy, PartialEq, Eq, Clone, Debug)]
pub enum SeekFrom { pub enum SeekFrom {
Start(u64), Start(usize),
End(i64), End(isize),
Current(i64), Current(isize),
} }
/// Maximum bytes in a path /// Maximum bytes in a path

View File

@ -1,12 +1,27 @@
use crate::fs::{file_table::FileDescripter, utils::SeekFrom};
use crate::log_syscall_entry; use crate::log_syscall_entry;
use crate::{fs::file_table::FileDescripter, prelude::*}; use crate::prelude::*;
use super::SyscallReturn; use super::SyscallReturn;
use super::SYS_LSEEK; use super::SYS_LSEEK;
pub fn sys_lseek(fd: FileDescripter, offset: usize, whence: u32) -> Result<SyscallReturn> { pub fn sys_lseek(fd: FileDescripter, offset: isize, whence: u32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_LSEEK); log_syscall_entry!(SYS_LSEEK);
debug!("fd = {}, offset = {}, whence = {}", fd, offset, whence); debug!("fd = {}, offset = {}, whence = {}", fd, offset, whence);
// TODO: do lseek let seek_from = match whence {
Ok(SyscallReturn::Return(0)) 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 _))
} }