diff --git a/Cargo.lock b/Cargo.lock index c9090c6..4ded565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "byteorder" @@ -107,6 +110,7 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" name = "file_rpc" version = "0.1.0" dependencies = [ + "bitflags", "parking_lot", "postcard", "serde", diff --git a/src/main.rs b/src/main.rs index 6e03ce9..98793e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::{ io::{Read, Seek, SeekFrom}, os::mikros::{ipc, syscalls}, path::Path, - sync::Arc, + sync::{atomic::{AtomicU64, Ordering}, Arc}, }; use dashmap::DashMap; @@ -30,43 +30,96 @@ struct GptEntry { name: String, } +struct OpenFile { + drive_file: (u64, u64), + offset: u64, + part_len: usize, + pos: AtomicU64, +} + +impl Clone for OpenFile { + fn clone(&self) -> Self { + Self { + drive_file: self.drive_file, + offset: self.offset, + part_len: self.part_len, + pos: AtomicU64::new(self.pos.load(Ordering::Relaxed)), + } + } +} + #[derive(Clone)] struct Serv { parts: Arc>, - open_files: Arc>, + open_files: Arc>, } impl dev_driver_rpc::Server for Serv { fn open(&self, path: &std::path::Path) -> Result { let part = *(self.parts.get(path.to_str().unwrap()).ok_or(())?); - Ok(self.open_files.insert(part).unwrap() as u64) + Ok(self.open_files.insert(OpenFile { + drive_file: part.0, + offset: part.1, + part_len: part.2, + pos: AtomicU64::new(0), + }).unwrap() as u64) } } impl file_rpc::Server for Serv { - fn read(&self, fd: u64, pos: u64, len: usize) -> Result, ()> { - let &(drive_file, offset, part_len) = &*self.open_files.get(fd as usize).ok_or(())?; - if pos.saturating_add(len as u64) > part_len as u64 { + fn read(&self, fd: u64, len: usize) -> Result, ()> { + let file = &*self.open_files.get(fd as usize).ok_or(())?; + if file.pos.load(Ordering::Relaxed).saturating_add(len as u64) > file.part_len as u64 { return Err(()); } - Ok(file_rpc::Client::new(drive_file.0) - .read(drive_file.1, offset + pos, len)? + let file_client = file_rpc::Client::new(file.drive_file.0); + file_client.seek(file.drive_file.1, file_rpc::SeekFrom::Start(file.offset + file.pos.load(Ordering::Relaxed))); + Ok(file_client + .read(file.drive_file.1, len)? .into()) } - fn write(&self, _fd: u64, _pos: u64, _data: &[u8]) -> Result<(), ()> { + fn write(&self, _fd: u64, _data: &[u8]) -> Result<(), ()> { todo!() } fn close(&self, _fd: u64) {} fn size(&self, fd: u64) -> Option { - Some(self.open_files.get(fd as usize)?.2 as u64) + Some(self.open_files.get(fd as usize)?.part_len as u64) } fn dup(&self, fd: u64) -> Option { - Some(fd) + let file = self.open_files.get(fd as usize)?.clone(); + self.open_files.insert(file).map(|x| x as u64) + } + + fn seek(&self, fd: u64, pos: file_rpc::SeekFrom) -> u64 { + let file = &*self.open_files.get(fd as usize).unwrap(); + match pos { + file_rpc::SeekFrom::Start(offset) => { + file.pos.store(offset, Ordering::Relaxed); + }, + file_rpc::SeekFrom::End(offset) => { + if offset <= 0 { + file.pos.store(file.part_len as u64 - (-offset) as u64, Ordering::Relaxed); + } + }, + file_rpc::SeekFrom::Current(offset) => { + if offset > 0 { + file.pos.store(u64::min(file.pos.load(Ordering::Relaxed) + offset as u64, file.part_len as u64), Ordering::Relaxed); + } else { + let offset = (-offset) as u64; + if offset > file.pos.load(Ordering::Relaxed) { + file.pos.store(0, Ordering::Relaxed); + } else { + file.pos.fetch_sub(offset, Ordering::Relaxed); + } + } + }, + } + file.pos.load(Ordering::Relaxed) } }