Skip to content

Commit

Permalink
Implements VFile read (obhq#789)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuchAFuriousDeath committed Mar 31, 2024
1 parent 807686a commit 01c1a5d
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 126 deletions.
4 changes: 2 additions & 2 deletions src/kernel/src/fs/dev/cdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl FileBackend for CharacterDevice {
file: &VFile,
buf: &mut UioMut,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
todo!()
}

Expand All @@ -126,7 +126,7 @@ impl FileBackend for CharacterDevice {
file: &VFile,
buf: &mut Uio,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
todo!()
}

Expand Down
4 changes: 2 additions & 2 deletions src/kernel/src/fs/dev/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl crate::fs::VnodeBackend for VnodeBackend {
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut UioMut,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
todo!()
}

Expand All @@ -181,7 +181,7 @@ impl crate::fs::VnodeBackend for VnodeBackend {
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut Uio,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
todo!()
}
}
Expand Down
71 changes: 36 additions & 35 deletions src/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::shm::SharedMemory;
use bitflags::bitflags;
use macros::Errno;
use std::fmt::Debug;
use std::io::{Read, Seek, SeekFrom, Write};
use std::io::{ErrorKind, Read, Seek, SeekFrom};
use std::sync::Arc;
use thiserror::Error;

Expand Down Expand Up @@ -62,13 +62,7 @@ impl VFile {

// TODO: consider implementing ktrace.

let res = self.read(&mut uio, td);

if let Err(ref e) = res {
todo!()
}

res
todo!()
}

/// See `dofilewrite` on the PS4 for a reference.
Expand All @@ -81,16 +75,10 @@ impl VFile {
// TODO: consider implementing ktrace.
// TODO: implement bwillwrite.

let res = self.write(&mut uio, td);

if let Err(ref e) = res {
todo!()
}

res
todo!()
}

fn read(&self, buf: &mut UioMut, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
fn read(&self, buf: &mut UioMut, td: Option<&VThread>) -> Result<(), Box<dyn Errno>> {
match &self.ty {
VFileType::Vnode(vn) => FileBackend::read(vn, self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.read(self, buf, td),
Expand All @@ -101,7 +89,7 @@ impl VFile {
}
}

fn write(&self, buf: &mut Uio, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
fn write(&self, buf: &mut Uio, td: Option<&VThread>) -> Result<(), Box<dyn Errno>> {
match &self.ty {
VFileType::Vnode(vn) => FileBackend::write(vn, self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.write(self, buf, td),
Expand Down Expand Up @@ -152,9 +140,27 @@ impl VFile {
}

impl Seek for VFile {
#[allow(unused_variables)] // TODO: Remove when implementing.
fn seek(&mut self, _pos: SeekFrom) -> std::io::Result<u64> {
todo!()
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
self.seekable_vnode().ok_or(ErrorKind::Other)?;

// Negative seeks should not be allowed here
let offset: u64 = match pos {
SeekFrom::Start(offset) => offset,
SeekFrom::Current(_) => {
todo!()
}
SeekFrom::End(_) => {
todo!()
}
};

self.offset = if let Ok(offset) = offset.try_into() {
offset
} else {
todo!()
};

Ok(offset as u64)
}

fn rewind(&mut self) -> std::io::Result<()> {
Expand All @@ -174,14 +180,20 @@ impl Seek for VFile {

impl Read for VFile {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let total = buf.len();

let ref mut iovec = IoVec::from_slice(buf);

let mut uio = UioMut::from_single_vec(iovec);
let mut uio = UioMut::from_single_vec(iovec, self.offset);

if let Err(e) = VFile::read(self, &mut uio, None) {
println!("Error: {:?}", e);

let Ok(read) = VFile::read(self, &mut uio, None) else {
todo!()
};

let read = total - uio.bytes_left;

if let Ok(read) = TryInto::<i64>::try_into(read) {
self.offset += read;
} else {
Expand All @@ -192,17 +204,6 @@ impl Read for VFile {
}
}

impl Write for VFile {
#[allow(unused_variables)] // TODO: Remove when implementing.
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
todo!()
}

fn flush(&mut self) -> std::io::Result<()> {
todo!()
}
}

/// Type of [`VFile`].
#[derive(Debug)]
pub enum VFileType {
Expand Down Expand Up @@ -233,7 +234,7 @@ pub trait FileBackend: Debug + Send + Sync + 'static {
file: &VFile,
buf: &mut UioMut,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
Err(Box::new(DefaultFileBackendError::ReadNotSupported))
}

Expand All @@ -244,7 +245,7 @@ pub trait FileBackend: Debug + Send + Sync + 'static {
file: &VFile,
buf: &mut Uio,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
Err(Box::new(DefaultFileBackendError::WriteNotSupported))
}

Expand Down
88 changes: 82 additions & 6 deletions src/kernel/src/fs/host/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl HostFile {
use std::ptr::null_mut;
use windows_sys::Wdk::{
Foundation::OBJECT_ATTRIBUTES,
Storage::FileSystem::{NtCreateFile, FILE_CREATE, FILE_DIRECTORY_FILE},
Storage::FileSystem::{NtCreateFile, FILE_DIRECTORY_FILE, FILE_OPEN},
};
use windows_sys::Win32::{
Foundation::{RtlNtStatusToDosError, STATUS_SUCCESS, UNICODE_STRING},
Expand Down Expand Up @@ -256,7 +256,7 @@ impl HostFile {
null_mut(),
FILE_ATTRIBUTE_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_CREATE,
FILE_OPEN,
FILE_DIRECTORY_FILE,
null_mut(),
0,
Expand All @@ -274,13 +274,89 @@ impl HostFile {
}

#[cfg(unix)]
pub(super) fn read(&self, buf: &mut UioMut) -> Result<usize, Error> {
todo!()
pub(super) fn read(&self, buf: &mut UioMut) -> Result<(), Error> {
use libc::pread;

buf.write_with::<Error>(|iov, mut offset| {
let nbytes = if let Ok(nbytes) = iov.len().try_into() {
nbytes
} else {
todo!()
};

let nread = unsafe { pread(self.raw, iov.ptr().cast(), nbytes, offset) };

match nread {
0.. if nread == nbytes as isize => Ok(nread as u64),
0.. => todo!(),
_ => todo!(),
}
})?;

Ok(())
}

#[cfg(windows)]
pub(super) fn read(&self, buf: &mut UioMut) -> Result<usize, Error> {
todo!()
pub(super) fn read(&self, buf: &mut UioMut) -> Result<(), Error> {
use std::ptr::null_mut;
use windows_sys::{
Wdk::Storage::FileSystem::NtReadFile,
Win32::{
Foundation::{STATUS_END_OF_FILE, STATUS_PENDING},
System::{
Threading::{WaitForSingleObject, INFINITE},
IO::{IO_STATUS_BLOCK, IO_STATUS_BLOCK_0},
},
},
};

buf.write_with::<Error>(|iov, mut offset| {
let nbytes = if let Ok(nbytes) = iov.len().try_into() {
nbytes
} else {
todo!()
};

let mut io_status = IO_STATUS_BLOCK {
Anonymous: IO_STATUS_BLOCK_0 {
Status: STATUS_PENDING,
},
Information: 0,
};

let status = unsafe {
NtReadFile(
self.raw,
0,
None,
null_mut(),
&mut io_status,
iov.ptr().cast(),
nbytes,
&mut offset,
null_mut(),
)
};

let status = if status == STATUS_PENDING {
unsafe {
WaitForSingleObject(self.raw, INFINITE);
io_status.Anonymous.Status
}
} else {
status
};

match status {
STATUS_PENDING => todo!(),
STATUS_END_OF_FILE => todo!(),
0.. if io_status.Information == nbytes as usize => Ok(io_status.Information as u64),
0.. => todo!(),
_ => todo!(),
}
})?;

Ok(())
}

#[cfg(unix)]
Expand Down
4 changes: 2 additions & 2 deletions src/kernel/src/fs/host/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl crate::fs::VnodeBackend for VnodeBackend {
_: &Arc<Vnode>,
buf: &mut UioMut,
_: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
let read = self.file.read(buf).map_err(ReadError::ReadFailed)?;

Ok(read)
Expand All @@ -140,7 +140,7 @@ impl crate::fs::VnodeBackend for VnodeBackend {
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut Uio,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
) -> Result<(), Box<dyn Errno>> {
todo!()
}
}
Expand Down
Loading

0 comments on commit 01c1a5d

Please sign in to comment.