From f117fecfb884fe9c4a00b61731666a2fe0385729 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 17 Aug 2021 11:32:13 +0200 Subject: [PATCH] !draft --- lib/vfs/src/host_fs.rs | 57 ++++-- lib/vfs/src/lib.rs | 14 ++ lib/vfs/src/mem_fs.rs | 411 ++++++++++++++++++++++++----------------- 3 files changed, 294 insertions(+), 188 deletions(-) diff --git a/lib/vfs/src/host_fs.rs b/lib/vfs/src/host_fs.rs index 9f916855c9c..fa939a8bfce 100644 --- a/lib/vfs/src/host_fs.rs +++ b/lib/vfs/src/host_fs.rs @@ -15,18 +15,6 @@ use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; use tracing::debug; -impl FileDescriptor { - #[cfg(unix)] - fn as_raw(&self) -> Result { - self.0.try_into().map_err(|_| FsError::InvalidFd) - } - - #[cfg(windows)] - fn as_raw(&self) -> Result { - self.0.try_into().map_err(|_| FsError::InvalidFd) - } -} - trait TryIntoFileDescriptor { type Error; @@ -49,6 +37,15 @@ where } } +#[cfg(unix)] +impl TryInto for FileDescriptor { + type Error = FsError; + + fn try_into(self) -> std::result::Result { + self.0.try_into().map_err(|_| FsError::InvalidFd) + } +} + #[cfg(windows)] impl TryIntoFileDescriptor for T where @@ -65,7 +62,16 @@ where } } -#[derive(Debug, Default, Clone)] +#[cfg(windows)] +impl TryInto for FileDescriptor { + type Error = FsError; + + fn try_into(self) -> std::result::Result { + self.0.try_into().map_err(|_| FsError::InvalidFd) + } +} + +#[derive(Clone, Debug, Default)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct FileSystem; @@ -296,15 +302,19 @@ impl File { /// creates a new host file from a `std::fs::File` and a path pub fn new(file: fs::File, host_path: PathBuf, read: bool, write: bool, append: bool) -> Self { let mut flags = 0; + if read { flags |= Self::READ; } + if write { flags |= Self::WRITE; } + if append { flags |= Self::APPEND; } + Self { inner: file, host_path, @@ -321,31 +331,39 @@ impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.inner.read_to_end(buf) } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { self.inner.read_to_string(buf) } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.inner.read_exact(buf) } } + impl Seek for File { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { self.inner.seek(pos) } } + impl Write for File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.inner.write_all(buf) } + fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> { self.inner.write_fmt(fmt) } @@ -391,6 +409,7 @@ impl VirtualFile for File { fn unlink(&mut self) -> Result<()> { fs::remove_file(&self.host_path).map_err(Into::into) } + fn sync_to_disk(&self) -> Result<()> { self.inner.sync_all().map_err(Into::into) } @@ -403,7 +422,7 @@ impl VirtualFile for File { #[cfg(unix)] fn host_file_bytes_available(host_fd: FileDescriptor) -> Result { let mut bytes_found = 0 as libc::c_int; - let result = unsafe { libc::ioctl(host_fd.as_raw()?, libc::FIONREAD, &mut bytes_found) }; + let result = unsafe { libc::ioctl(host_fd.try_into()?, libc::FIONREAD, &mut bytes_found) }; match result { // success @@ -425,6 +444,7 @@ fn host_file_bytes_available(_host_fd: FileDescriptor) -> Result { #[derive(Debug, Default)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Stdout; + impl Read for Stdout { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Err(io::Error::new( @@ -432,18 +452,21 @@ impl Read for Stdout { "can not read from stdout", )) } + fn read_to_end(&mut self, _buf: &mut Vec) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, "can not read from stdout", )) } + fn read_to_string(&mut self, _buf: &mut String) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, "can not read from stdout", )) } + fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, @@ -451,21 +474,26 @@ impl Read for Stdout { )) } } + impl Seek for Stdout { fn seek(&mut self, _pos: io::SeekFrom) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "can not seek stdout")) } } + impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { io::stdout().write(buf) } + fn flush(&mut self) -> io::Result<()> { io::stdout().flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { io::stdout().write_all(buf) } + fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> { io::stdout().write_fmt(fmt) } @@ -512,6 +540,7 @@ impl VirtualFile for Stdout { #[derive(Debug, Default)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub struct Stderr; + impl Read for Stderr { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Err(io::Error::new( diff --git a/lib/vfs/src/lib.rs b/lib/vfs/src/lib.rs index c5b64753cc0..a5e38655721 100644 --- a/lib/vfs/src/lib.rs +++ b/lib/vfs/src/lib.rs @@ -14,18 +14,32 @@ pub mod mem_fs; pub struct FileDescriptor(usize); pub trait FileSystem: fmt::Debug + Send + Sync + 'static { + /// Read a directory. fn read_dir(&self, path: &Path) -> Result; + + /// Create a directory. fn create_dir(&self, path: &Path) -> Result<()>; + + /// Delete a directory. fn remove_dir(&self, path: &Path) -> Result<()>; + + /// Rename a file. fn rename(&self, from: &Path, to: &Path) -> Result<()>; + + /// Fetch the metadata of a file. fn metadata(&self, path: &Path) -> Result; + /// This method gets metadata without following symlinks in the path. /// Currently identical to `metadata` because symlinks aren't implemented /// yet. fn symlink_metadata(&self, path: &Path) -> Result { self.metadata(path) } + + /// Delete a file. fn remove_file(&self, path: &Path) -> Result<()>; + + /// Create `OpenOptions`. fn new_open_options(&self) -> OpenOptions; } diff --git a/lib/vfs/src/mem_fs.rs b/lib/vfs/src/mem_fs.rs index addc97440d6..646a173b8d4 100644 --- a/lib/vfs/src/mem_fs.rs +++ b/lib/vfs/src/mem_fs.rs @@ -1,156 +1,185 @@ -use crate::*; +use crate::{ + FileDescriptor, FileType, FsError, Metadata, OpenOptions, OpenOptionsConfig, ReadDir, Result, + VirtualFile, +}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use std::io::{Read, Seek, Write}; +use std::io::{self, Read, Seek, Write}; use std::path::Path; use std::sync::{Arc, Mutex}; +use tracing::debug; + +pub type Inode = u64; #[derive(Debug, Clone)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -enum MemKind { +enum Node { File { name: String, - inode: u64, + inode: Inode, }, Directory { name: String, - contents: HashMap, + children: HashMap, }, } -impl Default for MemKind { +impl Default for Node { fn default() -> Self { - MemKind::Directory { + Node::Directory { name: "/".to_string(), - contents: Default::default(), + children: Default::default(), } } } #[derive(Clone, Debug, Default)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MemFileSystem { - inner: Arc>, +pub struct FileSystem { + inner: Arc>, } #[derive(Default, Debug)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MemFileSystemInner { - // done for recursion purposes - fs: MemKind, - inodes: HashMap>, - next_inode: u64, +struct FileSystemInner { + fs: Node, + inodes: HashMap>, + next_inode: Inode, } -impl MemFileSystemInner { +impl FileSystemInner { /// Removes a file, returning the `inode` number - fn remove_file_inner(&mut self, path: &Path) -> Result { + fn remove_file_inner(&mut self, path: &Path) -> Result { let parent = path.parent().unwrap(); let file = path.file_name().unwrap(); - let memkind = self.get_memkind_at_mut(parent).unwrap(); - let inode: u64 = match memkind { - MemKind::Directory { contents, .. } => { - let name = file.to_str().unwrap().to_string(); - let inode: u64 = match contents.get(&name).unwrap() { - MemKind::File { inode, .. } => *inode, + + let parent_node = self.get_node_at_mut(parent).unwrap(); + let inode = match parent_node { + Node::Directory { children, .. } => { + let file_name = file.to_str().unwrap(); + + let inode = match children.get(file_name) { + Some(Node::File { inode, .. }) => *inode, _ => return Err(FsError::NotAFile), }; - contents.remove(&name); + + children.remove(file_name); + inode } + _ => return Err(FsError::NotAFile), }; + Ok(inode) } - #[allow(dead_code)] - fn get_memkind_at(&self, path: &Path) -> Option<&MemKind> { + fn get_node_at(&self, path: &Path) -> Option<&Node> { let mut components = path.components(); + if path.is_absolute() { components.next()?; } - let mut memkind: &MemKind = &self.fs; + let mut node: &Node = &self.fs; for component in components { - match memkind { - MemKind::Directory { contents, .. } => { - memkind = contents.get(component.as_os_str().to_str().unwrap())?; + match node { + Node::Directory { children, .. } => { + node = children.get(component.as_os_str().to_str().unwrap())?; } _ => return None, } } - Some(memkind) + + Some(node) } - fn get_memkind_at_mut(&mut self, path: &Path) -> Option<&mut MemKind> { + + fn get_node_at_mut(&mut self, path: &Path) -> Option<&mut Node> { let mut components = path.components(); + if path.is_absolute() { components.next()?; } - let mut memkind: &mut MemKind = &mut self.fs; + let mut node: &mut Node = &mut self.fs; for component in components { - match memkind { - MemKind::Directory { contents, .. } => { - memkind = contents.get_mut(component.as_os_str().to_str().unwrap())?; + match node { + Node::Directory { children, .. } => { + node = children.get_mut(component.as_os_str().to_str().unwrap())?; } _ => return None, } } - Some(memkind) + + Some(node) } } -impl FileSystem for MemFileSystem { - fn read_dir(&self, _path: &Path) -> Result { +impl crate::FileSystem for FileSystem { + fn read_dir(&self, _path: &Path) -> Result { todo!() } - fn create_dir(&self, path: &Path) -> Result<(), FsError> { + + fn create_dir(&self, path: &Path) -> Result<()> { let parent = path.parent().unwrap(); let file = path.file_name().unwrap(); + let mut inner = self.inner.lock().unwrap(); - let memkind = inner.get_memkind_at_mut(parent).unwrap(); - match memkind { - MemKind::Directory { contents, .. } => { - let name = file.to_str().unwrap().to_string(); - if contents.contains_key(&name) { + let node = inner.get_node_at_mut(parent).unwrap(); + + match node { + Node::Directory { children, .. } => { + let name = file.to_str().unwrap(); + + if children.contains_key(name) { return Err(FsError::AlreadyExists); } - let mk = MemKind::Directory { - name: name.clone(), - contents: Default::default(), + + let directory = Node::Directory { + name: name.to_owned(), + children: Default::default(), }; - contents.insert(name.clone(), mk); + + children.insert(name.to_owned(), directory); } _ => return Err(FsError::BaseNotDirectory), } + Ok(()) } - fn remove_dir(&self, path: &Path) -> Result<(), FsError> { + + fn remove_dir(&self, path: &Path) -> Result<()> { let parent = path.parent().unwrap(); let file = path.file_name().unwrap(); + let mut inner = self.inner.lock().unwrap(); - let memkind = inner.get_memkind_at_mut(parent).unwrap(); - match memkind { - MemKind::Directory { contents, .. } => { - let name = file.to_str().unwrap().to_string(); - match contents.get(&name).unwrap() { - MemKind::Directory { contents, .. } => { - if !contents.is_empty() { + let node = inner.get_node_at_mut(parent).unwrap(); + + match node { + Node::Directory { children, .. } => { + let name = file.to_str().unwrap(); + + match children.get(name).unwrap() { + Node::Directory { children, .. } => { + if !children.is_empty() { return Err(FsError::DirectoryNotEmpty); } } _ => return Err(FsError::BaseNotDirectory), } - contents.remove(&name); + + children.remove(name); } _ => return Err(FsError::BaseNotDirectory), } + Ok(()) } - fn rename(&self, from: &Path, to: &Path) -> Result<(), FsError> { + + fn rename(&self, from: &Path, to: &Path) -> Result<()> { let inner = self.inner.lock().unwrap(); // We assume that we move into a location that has a parent. // Otherwise (the root) should not be replaceable, and we should trigger an @@ -158,97 +187,76 @@ impl FileSystem for MemFileSystem { let parent_to = to.parent().unwrap(); // TODO: return a proper error (not generic unknown) - let memkind_from = inner.get_memkind_at(from).ok_or(FsError::UnknownError)?; + let node_from = inner.get_node_at(from).ok_or(FsError::UnknownError)?; let mut inner = self.inner.lock().unwrap(); - let memkind_to = inner - .get_memkind_at_mut(parent_to) + let node_to = inner + .get_node_at_mut(parent_to) .ok_or(FsError::BaseNotDirectory)?; - // We update the to contents of the new dir, adding the old memkind - match memkind_to { - MemKind::Directory { contents, .. } => { - let name = to.file_name().unwrap().to_str().unwrap().to_string(); - contents.insert(name, memkind_from.clone()); + // We update the to children of the new dir, adding the old node + match node_to { + Node::Directory { children, .. } => { + let name = to.file_name().unwrap().to_str().unwrap(); + children.insert(name.to_owned(), node_from.clone()); } // If we are trying to move from the root `/dir1` to `/file/dir2` _ => return Err(FsError::BaseNotDirectory), } - // We remove the old memkind location - match memkind_from { - MemKind::Directory { .. } => { + // We remove the old node location + match node_from { + Node::Directory { .. } => { self.remove_dir(from)?; } - MemKind::File { .. } => { + Node::File { .. } => { inner.remove_file_inner(from)?; } } + Ok(()) } - fn remove_file(&self, path: &Path) -> Result<(), FsError> { + fn remove_file(&self, path: &Path) -> Result<()> { let mut inner = self.inner.lock().unwrap(); let inode = inner.remove_file_inner(path)?; inner.inodes.remove(&inode).unwrap(); Ok(()) } + fn new_open_options(&self) -> OpenOptions { - OpenOptions::new(Box::new(MemFileOpener(self.clone()))) - } - - fn metadata(&self, _path: &Path) -> Result { - // let inner = self.inner.lock().unwrap(); - // let memkind = inner.get_memkind_at(path) - Ok(Metadata { - ft: FileType { - dir: false, - file: true, - symlink: false, - char_device: false, - block_device: false, - socket: false, - fifo: false, - }, - accessed: 0 as u64, - created: 0 as u64, - modified: 0 as u64, - len: 0, - }) + OpenOptions::new(Box::new(FileOpener(self.clone()))) + } + + fn metadata(&self, _path: &Path) -> Result { + unimplemented!() } } #[derive(Clone)] -pub struct MemFileOpener(MemFileSystem); - -impl FileOpener for MemFileOpener { - fn open( - &mut self, - path: &Path, - conf: &OpenOptionsConfig, - ) -> Result, FsError> { +pub struct FileOpener(FileSystem); + +impl crate::FileOpener for FileOpener { + fn open(&mut self, path: &Path, conf: &OpenOptionsConfig) -> Result> { // TODO: handle create implying write, etc. let read = conf.read(); let write = conf.write(); let append = conf.append(); - let virtual_file = - Box::new(MemFile::new(vec![], read, write, append)) as Box; + let virtual_file = Box::new(File::new(vec![], read, write, append)) as Box; let mut inner = self.0.inner.lock().unwrap(); let inode = inner.next_inode; let parent_path = path.parent().unwrap(); let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); // TODO: replace with an actual missing directory error - let parent_memkind = inner - .get_memkind_at_mut(parent_path) - .ok_or(FsError::IOError)?; - match parent_memkind { - MemKind::Directory { contents, .. } => { - if contents.contains_key(&file_name) { + let parent_node = inner.get_node_at_mut(parent_path).ok_or(FsError::IOError)?; + match parent_node { + Node::Directory { children, .. } => { + if children.contains_key(&file_name) { return Err(FsError::AlreadyExists); } - contents.insert( + children.insert( file_name.clone(), - MemKind::File { + Node::File { name: file_name, inode, }, @@ -263,7 +271,7 @@ impl FileOpener for MemFileOpener { inner.next_inode += 1; inner.inodes.insert(inode, virtual_file); - Ok(Box::new(MemFileHandle { + Ok(Box::new(FileHandle { fs: self.0.clone(), inode, }) as Box) @@ -272,7 +280,7 @@ impl FileOpener for MemFileOpener { #[derive(Debug)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MemFile { +pub struct File { buffer: Vec, cursor: usize, flags: u16, @@ -281,7 +289,7 @@ pub struct MemFile { created_time: u64, } -impl MemFile { +impl File { const READ: u16 = 1; const WRITE: u16 = 2; const APPEND: u16 = 4; @@ -289,15 +297,19 @@ impl MemFile { /// creates a new host file from a `std::fs::File` and a path pub fn new(buffer: Vec, read: bool, write: bool, append: bool) -> Self { let mut flags = 0; + if read { flags |= Self::READ; } + if write { flags |= Self::WRITE; } + if append { flags |= Self::APPEND; } + Self { buffer, cursor: 0, @@ -309,31 +321,40 @@ impl MemFile { } } -impl Read for MemFile { +impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { let upper_limit = std::cmp::min(self.buffer.len() - self.cursor, buf.len()); + for i in 0..upper_limit { buf[i] = self.buffer[self.cursor + i]; } + self.cursor += upper_limit; + Ok(upper_limit) } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let data_to_copy = self.buffer.len() - self.cursor; buf.reserve(data_to_copy); + for i in self.cursor..self.buffer.len() { buf.push(self.buffer[i]); } + Ok(data_to_copy) } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { let s = std::str::from_utf8(&self.buffer[self.cursor..]) .map_err(|_e| io::ErrorKind::InvalidInput)?; buf.push_str(s); let amount_read = self.buffer.len() - self.cursor; self.cursor = self.buffer.len(); + Ok(amount_read) } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() < (self.buffer.len() - self.cursor) { return Err(std::io::Error::new( @@ -341,14 +362,18 @@ impl Read for MemFile { "Not enough bytes available", )); } + for i in 0..buf.len() { buf[i] = self.buffer[self.cursor + i]; } + self.cursor += buf.len(); + Ok(()) } } -impl Seek for MemFile { + +impl Seek for File { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { match pos { io::SeekFrom::Start(s) => self.cursor = s as usize, @@ -356,82 +381,95 @@ impl Seek for MemFile { io::SeekFrom::End(s) => self.cursor = (self.buffer.len() as i64 + s) as usize, io::SeekFrom::Current(s) => self.cursor = (self.cursor as i64 + s) as usize, } + Ok(self.cursor as u64) } } -impl Write for MemFile { + +impl Write for File { fn write(&mut self, buf: &[u8]) -> io::Result { self.buffer.write(buf) } + fn flush(&mut self) -> io::Result<()> { self.buffer.flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.buffer.write_all(buf) } + fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> { self.buffer.write_fmt(fmt) } } #[cfg_attr(feature = "enable-serde", typetag::serde)] -impl VirtualFile for MemFile { +impl VirtualFile for File { fn last_accessed(&self) -> u64 { self.last_accessed } + fn last_modified(&self) -> u64 { self.last_modified } + fn created_time(&self) -> u64 { self.created_time } + fn size(&self) -> u64 { self.buffer.len() as u64 } - fn set_len(&mut self, new_size: u64) -> Result<(), FsError> { + + fn set_len(&mut self, new_size: u64) -> Result<()> { self.buffer.resize(new_size as usize, 0); Ok(()) } - fn unlink(&mut self) -> Result<(), FsError> { + + fn unlink(&mut self) -> Result<()> { self.buffer.clear(); self.cursor = 0; Ok(()) } - fn sync_to_disk(&self) -> Result<(), FsError> { + + fn sync_to_disk(&self) -> Result<()> { Ok(()) } - fn bytes_available(&self) -> Result { + + fn bytes_available(&self) -> Result { Ok(self.buffer.len() - self.cursor) } - fn get_raw_fd(&self) -> Option { + + fn get_fd(&self) -> Option { None } } #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct MemFileHandle { +pub struct FileHandle { // hack, just skip it // #[serde(skip)] - fs: MemFileSystem, - inode: u64, + fs: FileSystem, + inode: Inode, } -impl MemFileHandle { +impl FileHandle { // not optimal,but good enough for now fn no_file_err() -> std::io::Error { std::io::Error::new(std::io::ErrorKind::NotFound, "File was closed") } } -impl std::fmt::Debug for MemFileHandle { +impl std::fmt::Debug for FileHandle { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("MemFileHandle") + f.debug_struct("FileHandle") .field("inode", &self.inode) .finish() } } -impl Read for MemFileHandle { +impl Read for FileHandle { fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -441,6 +479,7 @@ impl Read for MemFileHandle { file.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -450,6 +489,7 @@ impl Read for MemFileHandle { file.read_to_end(buf) } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -459,6 +499,7 @@ impl Read for MemFileHandle { file.read_to_string(buf) } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -469,7 +510,8 @@ impl Read for MemFileHandle { file.read_exact(buf) } } -impl Seek for MemFileHandle { + +impl Seek for FileHandle { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -480,7 +522,8 @@ impl Seek for MemFileHandle { file.seek(pos) } } -impl Write for MemFileHandle { + +impl Write for FileHandle { fn write(&mut self, buf: &[u8]) -> io::Result { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -490,6 +533,7 @@ impl Write for MemFileHandle { file.write(buf) } + fn flush(&mut self) -> io::Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -499,6 +543,7 @@ impl Write for MemFileHandle { file.flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -508,6 +553,7 @@ impl Write for MemFileHandle { file.write_all(buf) } + fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner @@ -520,7 +566,7 @@ impl Write for MemFileHandle { } #[cfg_attr(feature = "enable-serde", typetag::serde)] -impl VirtualFile for MemFileHandle { +impl VirtualFile for FileHandle { fn last_accessed(&self) -> u64 { let inner = self.fs.inner.lock().unwrap(); inner @@ -561,7 +607,7 @@ impl VirtualFile for MemFileHandle { .unwrap_or_default() } - fn set_len(&mut self, new_size: u64) -> Result<(), FsError> { + fn set_len(&mut self, new_size: u64) -> Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner .inodes @@ -571,7 +617,7 @@ impl VirtualFile for MemFileHandle { file.set_len(new_size) } - fn unlink(&mut self) -> Result<(), FsError> { + fn unlink(&mut self) -> Result<()> { let mut inner = self.fs.inner.lock().unwrap(); let file = inner .inodes @@ -581,7 +627,7 @@ impl VirtualFile for MemFileHandle { file.unlink() } - fn sync_to_disk(&self) -> Result<(), FsError> { + fn sync_to_disk(&self) -> Result<()> { let inner = self.fs.inner.lock().unwrap(); let file = inner .inodes @@ -591,7 +637,7 @@ impl VirtualFile for MemFileHandle { file.sync_to_disk() } - fn bytes_available(&self) -> Result { + fn bytes_available(&self) -> Result { let inner = self.fs.inner.lock().unwrap(); let file = inner .inodes @@ -601,16 +647,14 @@ impl VirtualFile for MemFileHandle { file.bytes_available() } - fn get_raw_fd(&self) -> Option { + fn get_fd(&self) -> Option { let inner = self.fs.inner.lock().unwrap(); let file = inner.inodes.get(&self.inode)?; - file.get_raw_fd() + file.get_fd() } } -// Stdin / Stdout / Stderr definitions - /// A wrapper type around Stdout that implements `VirtualFile` #[derive(Debug, Default)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] @@ -625,18 +669,21 @@ impl Read for Stdout { "can not read from stdout", )) } + fn read_to_end(&mut self, _buf: &mut Vec) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, "can not read from stdout", )) } + fn read_to_string(&mut self, _buf: &mut String) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, "can not read from stdout", )) } + fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, @@ -644,26 +691,31 @@ impl Read for Stdout { )) } } + impl Seek for Stdout { fn seek(&mut self, _pos: io::SeekFrom) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "can not seek stdout")) } } + impl Write for Stdout { fn write(&mut self, _buf: &[u8]) -> io::Result { // io::stdout().write(buf) unimplemented!(); } + fn flush(&mut self) -> io::Result<()> { // io::stdout().flush() // unimplemented!(); Ok(()) } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { // io::stdout().write_all(buf) self.buf.extend_from_slice(&buf); Ok(()) } + fn write_fmt(&mut self, _fmt: ::std::fmt::Arguments) -> io::Result<()> { // io::stdout().write_fmt(fmt) unimplemented!(); @@ -675,35 +727,35 @@ impl VirtualFile for Stdout { fn last_accessed(&self) -> u64 { 0 } + fn last_modified(&self) -> u64 { 0 } + fn created_time(&self) -> u64 { 0 } + fn size(&self) -> u64 { 0 } - fn set_len(&mut self, _new_size: u64) -> Result<(), FsError> { + + fn set_len(&mut self, _new_size: u64) -> Result<()> { debug!("Calling VirtualFile::set_len on stdout; this is probably a bug"); Err(FsError::PermissionDenied) } - fn unlink(&mut self) -> Result<(), FsError> { + + fn unlink(&mut self) -> Result<()> { Ok(()) } - fn bytes_available(&self) -> Result { - // unwrap is safe because of get_raw_fd implementation - unimplemented!(); - } - #[cfg(unix)] - fn get_raw_fd(&self) -> Option { + fn bytes_available(&self) -> Result { + // unwrap is safe because of get_raw_fd implementation unimplemented!(); } - #[cfg(not(unix))] - fn get_raw_fd(&self) -> Option { - unimplemented!(); + fn get_fd(&self) -> Option { + None } } @@ -714,6 +766,7 @@ impl VirtualFile for Stdout { pub struct Stderr { pub buf: Vec, } + impl Read for Stderr { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Err(io::Error::new( @@ -740,11 +793,13 @@ impl Read for Stderr { )) } } + impl Seek for Stderr { fn seek(&mut self, _pos: io::SeekFrom) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "can not seek stderr")) } } + impl Write for Stderr { fn write(&mut self, _buf: &[u8]) -> io::Result { // io::stderr().write(buf) @@ -772,35 +827,35 @@ impl VirtualFile for Stderr { fn last_accessed(&self) -> u64 { 0 } + fn last_modified(&self) -> u64 { 0 } + fn created_time(&self) -> u64 { 0 } + fn size(&self) -> u64 { 0 } - fn set_len(&mut self, _new_size: u64) -> Result<(), FsError> { + + fn set_len(&mut self, _new_size: u64) -> Result<()> { debug!("Calling VirtualFile::set_len on stderr; this is probably a bug"); Err(FsError::PermissionDenied) } - fn unlink(&mut self) -> Result<(), FsError> { + + fn unlink(&mut self) -> Result<()> { Ok(()) } - fn bytes_available(&self) -> Result { + + fn bytes_available(&self) -> Result { unimplemented!(); } - #[cfg(unix)] - fn get_raw_fd(&self) -> Option { + + fn get_fd(&self) -> Option { unimplemented!(); } - #[cfg(not(unix))] - fn get_raw_fd(&self) -> Option { - unimplemented!( - "Stderr::get_raw_fd in VirtualFile is not implemented for non-Unix-like targets yet" - ); - } } /// A wrapper type around Stdin that implements `VirtualFile` and @@ -820,24 +875,29 @@ impl Read for Stdin { Ok(len) // unimplemented!(); } + fn read_to_end(&mut self, _buf: &mut Vec) -> io::Result { // io::stdin().read_to_end(buf) unimplemented!(); } + fn read_to_string(&mut self, _buf: &mut String) -> io::Result { // io::stdin().read_to_string(buf) unimplemented!(); } + fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> { // io::stdin().read_exact(buf) unimplemented!(); } } + impl Seek for Stdin { fn seek(&mut self, _pos: io::SeekFrom) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "can not seek stdin")) } } + impl Write for Stdin { fn write(&mut self, _buf: &[u8]) -> io::Result { Err(io::Error::new( @@ -845,18 +905,21 @@ impl Write for Stdin { "can not write to stdin", )) } + fn flush(&mut self) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "can not write to stdin", )) } + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "can not write to stdin", )) } + fn write_fmt(&mut self, _fmt: ::std::fmt::Arguments) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, @@ -870,35 +933,35 @@ impl VirtualFile for Stdin { fn last_accessed(&self) -> u64 { 0 } + fn last_modified(&self) -> u64 { 0 } + fn created_time(&self) -> u64 { 0 } + fn size(&self) -> u64 { 0 } - fn set_len(&mut self, _new_size: u64) -> Result<(), FsError> { + + fn set_len(&mut self, _new_size: u64) -> Result<()> { debug!("Calling VirtualFile::set_len on stdin; this is probably a bug"); Err(FsError::PermissionDenied) } - fn unlink(&mut self) -> Result<(), FsError> { + + fn unlink(&mut self) -> Result<()> { Ok(()) } - fn bytes_available(&self) -> Result { + + fn bytes_available(&self) -> Result { unimplemented!(); } - #[cfg(unix)] - fn get_raw_fd(&self) -> Option { + + fn get_fd(&self) -> Option { // use std::os::unix::io::AsRawFd; // Some(io::stdin().as_raw_fd()) unimplemented!(); } - #[cfg(not(unix))] - fn get_raw_fd(&self) -> Option { - unimplemented!( - "Stdin::get_raw_fd in VirtualFile is not implemented for non-Unix-like targets yet" - ); - } }