diff --git a/src/ext2/file.rs b/src/ext2/file.rs index 6ca41c5..7b441f1 100644 --- a/src/ext2/file.rs +++ b/src/ext2/file.rs @@ -11,7 +11,7 @@ use std::io::{self, Read}; /// /// Files are automatically closed when they go out of scope. Errors detected /// on closing are ignored by the implementation of `Drop`. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct File { inode: Inode, block_size: usize, diff --git a/src/main.rs b/src/main.rs index abde40f..afbc1be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,17 +4,24 @@ use std::{ borrow::Cow, fs::File, os::mikros::{ipc, syscalls}, - sync::Arc, + sync::Arc, usize, }; use ext2::Ext2; use itertools::Itertools; use parking_lot::RwLock; +#[derive(Clone)] +struct OpenFile { + file: ext2::File, + pos: u64, + mount_id: usize, +} + #[derive(Clone)] struct Serv { mounts: Arc>>, - files: Arc>>, + files: Arc>>, dirs: Arc, usize)>>>, } @@ -31,7 +38,11 @@ impl fs_rpc::Server for Serv { let mounts = self.mounts.read(); let mount = &mounts[mount_id as usize]; let file = mount.open(path).map_err(|_| ())?; - self.files.write().push((file, mount_id as usize)); + self.files.write().push(OpenFile { + file, + pos: 0, + mount_id: mount_id as usize + }); let res = Ok((None, (self.files.read().len() - 1) as u64)); res } @@ -49,18 +60,20 @@ impl fs_rpc::Server for Serv { } impl file_rpc::Server for Serv { - fn read(&self, fd: u64, pos: u64, len: usize) -> Result, ()> { + fn read(&self, fd: u64, len: usize) -> Result, ()> { let files = self.files.read(); - let (file, mount_id) = &files[fd as usize]; + let file = &files[fd as usize]; let mounts = self.mounts.read(); - let mount = &mounts[*mount_id]; + let mount = &mounts[file.mount_id]; let mut buf = vec![0; len]; - let read_len = file.read_at(&mut buf, pos, mount).map_err(|_| ())?; + let read_len = file.file.read_at(&mut buf, file.pos, mount).map_err(|_| ())?; buf.truncate(read_len); + std::mem::drop(files); + self.files.write()[fd as usize].pos += read_len as u64; Ok(buf.into()) } - fn write(&self, _fd: u64, _pos: u64, _data: &[u8]) -> Result<(), ()> { + fn write(&self, _fd: u64, _data: &[u8]) -> Result<(), ()> { Err(()) } @@ -68,12 +81,43 @@ impl file_rpc::Server for Serv { fn size(&self, fd: u64) -> Option { let files = self.files.read(); - let (file, _mount_id) = &files[fd as usize]; - Some(file.metadata().len()) + let file = &files[fd as usize]; + Some(file.file.metadata().len()) } fn dup(&self, fd: u64) -> Option { - Some(fd) + let mut files = self.files.write(); + let file = files[fd as usize].clone(); + files.push(file); + Some((files.len() - 1) as u64) + } + + fn seek(&self, fd: u64, pos: file_rpc::SeekFrom) -> u64 { + let mut files = self.files.write(); + let file = &mut files[fd as usize]; + match pos { + file_rpc::SeekFrom::Start(offset) => { + file.pos = offset; + }, + file_rpc::SeekFrom::End(offset) => { + if offset <= 0 { + file.pos = file.file.metadata().len() - (-offset) as u64; + } + }, + file_rpc::SeekFrom::Current(offset) => { + if offset > 0 { + file.pos = u64::min(file.pos + offset as u64, file.file.metadata().len()); + } else { + let offset = (-offset) as u64; + if offset > file.pos { + file.pos = 0; + } else { + file.pos -= offset; + } + } + }, + } + file.pos } }