diff --git a/src/main.rs b/src/main.rs index 4b6aef2..c711554 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,18 @@ use std::{ use parking_lot::RwLock; use tar::Archive; +#[derive(Clone)] +struct OpenFile { + mount_id: usize, + file_offset: u64, + len: usize, + pos: u64, +} + #[derive(Clone)] struct Serv { mounts: Arc)>>>, - files: Arc>>, + files: Arc>>, } impl fs_rpc::Server for Serv { @@ -40,48 +48,87 @@ impl fs_rpc::Server for Serv { .ok_or(())?; self.files .write() - .push((mount_id as usize, file_offset, file_size)); + .push(OpenFile { + mount_id: mount_id as usize, + file_offset, + len: file_size, + pos: 0, + }); Ok((None, (self.files.read().len() - 1) as u64)) } - fn open_dir(&self, path: &std::path::Path, mount_id: u64) -> Result<(Option, u64), ()> { + fn open_dir(&self, _path: &std::path::Path, _mount_id: u64) -> Result<(Option, u64), ()> { // TODO Err(()) } } impl file_rpc::Server for Serv { - fn read(&self, fd: u64, pos: u64, len: usize) -> Result, ()> { - let (mount_id, file_offset, size) = self.files.read()[fd as usize]; - let read_len = usize::min(len, size - (pos as usize)); + fn read(&self, fd: u64, len: usize) -> Result, ()> { + let files = self.files.read(); + let file = &files[fd as usize]; + let read_len = usize::min(len, file.len - (file.pos as usize)); if read_len == 0 { return Ok(Vec::new().into()); }; let mounts = self.mounts.read(); - let mount = &mounts[mount_id]; + let mount = &mounts[file.mount_id]; (&mount.0) - .seek(std::io::SeekFrom::Start(file_offset + pos)) + .seek(std::io::SeekFrom::Start(file.file_offset + file.pos)) .unwrap(); let mut buf = vec![0; read_len]; let read_bytes = (&mount.0).read(&mut buf).map_err(|_| ())?; buf.truncate(read_bytes); + std::mem::drop(files); + self.files.write()[fd as usize].pos += read_bytes as u64; Ok(buf.into()) } - fn write(&self, _fd: u64, _pos: u64, _data: &[u8]) -> Result<(), ()> { + fn write(&self, _fd: u64, _data: &[u8]) -> Result<(), ()> { Err(()) } fn close(&self, _fd: u64) {} fn size(&self, fd: u64) -> Option { - let (_mount_id, _file_offset, size) = self.files.read()[fd as usize]; - Some(size as u64) + Some(self.files.read()[fd as usize].len as u64) } 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.len as u64 - (-offset) as u64; + } + }, + file_rpc::SeekFrom::Current(offset) => { + if offset > 0 { + file.pos = u64::min(file.pos + offset as u64, file.len as u64); + } else { + let offset = (-offset) as u64; + if offset > file.pos { + file.pos = 0; + } else { + file.pos -= offset; + } + } + }, + }; + file.pos + } + } fn main() {