diff --git a/create.sh b/create.sh new file mode 100755 index 0000000000000000000000000000000000000000..a5f28ca7426234da0b4d710206d4c4237746f4ff --- /dev/null +++ b/create.sh @@ -0,0 +1,10 @@ +#!/bin/bash +rm -f ../../filesystem/etc/redoxfs.bin +cargo run ../../filesystem/etc/redoxfs.bin <<-EOF + mk a_file + mkdir a_directory + cd a_directory + mk b_file + mk c_file + exit +EOF diff --git a/scheme/image.rs b/scheme/image.rs new file mode 100644 index 0000000000000000000000000000000000000000..586e9638a3e39e69fcf5a4ef2c1eeb70efd630c9 --- /dev/null +++ b/scheme/image.rs @@ -0,0 +1,48 @@ +use std::fs::File; +use std::io::{Read, Write, Seek, SeekFrom}; + +use redoxfs::Disk; + +use system::error::{Error, Result, EIO}; + +macro_rules! try_disk { + ($expr:expr) => (match $expr { + Ok(val) => val, + Err(err) => { + println!("Disk I/O Error: {}", err); + return Err(Error::new(EIO)); + } + }) +} + +pub struct Image { + file: File +} + +impl Image { + pub fn open(path: &str) -> Result<Image> { + let file = try_disk!(File::open(path)); + Ok(Image { + file: file + }) + } +} + +impl Disk for Image { + fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { + try_disk!(self.file.seek(SeekFrom::Start(block * 512))); + let count = try_disk!(self.file.read(buffer)); + Ok(count) + } + + fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> { + try_disk!(self.file.seek(SeekFrom::Start(block * 512))); + let count = try_disk!(self.file.write(buffer)); + Ok(count) + } + + fn size(&mut self) -> Result<u64> { + let size = try_disk!(self.file.seek(SeekFrom::End(0))); + Ok(size) + } +} diff --git a/scheme/main.rs b/scheme/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..1262285cd95d8afcb00c102dd2bd0137c8eaaf6c --- /dev/null +++ b/scheme/main.rs @@ -0,0 +1,241 @@ +extern crate redoxfs; + +extern crate system; + +use std::cmp::{min, max}; +use std::collections::BTreeMap; +use std::env; +use std::fs::File; +use std::io::{Read, Write}; +use std::mem::size_of; + +use image::Image; + +use redoxfs::FileSystem; + +use system::error::{Error, Result, ENOENT, EBADF, EINVAL}; +use system::scheme::{Packet, Scheme}; +use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END}; + +pub mod image; + +struct FileResource { + path: String, + data: Vec<u8>, + seek: usize, +} + +impl FileResource { + fn new(path: &str) -> FileResource { + FileResource { + path: path.to_string(), + data: Vec::new(), + seek: 0, + } + } + + fn read(&mut self, buf: &mut [u8]) -> Result<usize> { + let mut i = 0; + while i < buf.len() && self.seek < self.data.len() { + buf[i] = self.data[self.seek]; + i += 1; + self.seek += 1; + } + Ok(i) + } + + fn write(&mut self, buf: &[u8]) -> Result<usize> { + let mut i = 0; + while i < buf.len() && self.seek < self.data.len() { + self.data[self.seek] = buf[i]; + i += 1; + self.seek += 1; + } + Ok(i) + } + + fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> { + match whence { + SEEK_SET => { + self.seek = min(0, max(self.data.len() as isize, offset as isize)) as usize; + Ok(self.seek) + }, + SEEK_CUR => { + self.seek = min(0, max(self.data.len() as isize, self.seek as isize + offset as isize)) as usize; + Ok(self.seek) + }, + SEEK_END => { + self.seek = min(0, max(self.data.len() as isize, self.data.len() as isize + offset as isize)) as usize; + Ok(self.seek) + }, + _ => Err(Error::new(EINVAL)) + } + } + + fn path(&self, buf: &mut [u8]) -> Result<usize> { + let mut i = 0; + let path = self.path.as_bytes(); + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } + Ok(i) + } + + fn stat(&self, _stat: &mut Stat) -> Result<usize> { + Ok(0) + } + + fn sync(&mut self) -> Result<usize> { + Ok(0) + } +} + +struct FileScheme { + fs: FileSystem, + next_id: isize, + files: BTreeMap<usize, FileResource> +} + +impl FileScheme { + fn new(fs: FileSystem) -> FileScheme { + FileScheme { + fs: fs, + next_id: 1, + files: BTreeMap::new() + } + } +} + +impl Scheme for FileScheme { + fn open(&mut self, path: &str, flags: usize, mode: usize) -> Result<usize> { + println!("open {:X} = {}, {:X}, {:X}", path.as_ptr() as usize, path, flags, mode); + let id = self.next_id as usize; + self.next_id += 1; + if self.next_id < 0 { + self.next_id = 1; + } + self.files.insert(id, FileResource::new(path)); + Ok(id) + } + + #[allow(unused_variables)] + fn unlink(&mut self, path: &str) -> Result<usize> { + println!("unlink {}", path); + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn mkdir(&mut self, path: &str, mode: usize) -> Result<usize> { + println!("mkdir {}, {:X}", path, mode); + Err(Error::new(ENOENT)) + } + + /* Resource operations */ + #[allow(unused_variables)] + fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> { + println!("read {}, {:X}, {}", id, buf.as_mut_ptr() as usize, buf.len()); + if let Some(mut file) = self.files.get_mut(&id) { + file.read(buf) + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> { + println!("write {}, {:X}, {}", id, buf.as_ptr() as usize, buf.len()); + if let Some(mut file) = self.files.get_mut(&id) { + file.write(buf) + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> { + println!("seek {}, {}, {}", id, pos, whence); + if let Some(mut file) = self.files.get_mut(&id) { + file.seek(pos, whence) + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> { + println!("fpath {}, {:X}, {}", id, buf.as_mut_ptr() as usize, buf.len()); + if let Some(file) = self.files.get(&id) { + file.path(buf) + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> { + println!("fstat {}, {:X}", id, stat as *mut Stat as usize); + if let Some(file) = self.files.get(&id) { + file.stat(stat) + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn fsync(&mut self, id: usize) -> Result<usize> { + println!("fsync {}", id); + if let Some(mut file) = self.files.get_mut(&id) { + file.sync() + } else { + Err(Error::new(EBADF)) + } + } + + #[allow(unused_variables)] + fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> { + println!("ftruncate {}, {}", id, len); + Err(Error::new(EBADF)) + } + + fn close(&mut self, id: usize) -> Result<usize> { + println!("close {}", id); + if self.files.remove(&id).is_some() { + Ok(0) + } else { + Err(Error::new(EBADF)) + } + } +} + +fn scheme(fs: FileSystem) { + //In order to handle example:, we create :example + let mut scheme = FileScheme::new(fs); + let mut socket = File::create(":redoxfs").unwrap(); + loop { + let mut packet = Packet::default(); + while socket.read(&mut packet).unwrap() == size_of::<Packet>() { + scheme.handle(&mut packet); + socket.write(&packet).unwrap(); + } + } +} + +fn main() { + let mut args = env::args(); + if let Some(path) = args.nth(1) { + //Open an existing image + match Image::open(&path) { + Ok(disk) => match FileSystem::open(Box::new(disk)) { + Ok(filesystem) => { + println!("redoxfs: opened filesystem {}", path); + scheme(filesystem); + }, + Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err) + }, + Err(err) => println!("redoxfs: failed to open image {}: {}", path, err) + } + } else { + println!("redoxfs: no disk image provided"); + } +} diff --git a/utility/main.rs b/utility/main.rs index b1924f60cd22d40bf57656998e6d3901739d6ca2..1c2a4143e34a14d569c2cf89ec68e8e1b9ce2ccb 100644 --- a/utility/main.rs +++ b/utility/main.rs @@ -188,8 +188,8 @@ fn main() { Err(err) => println!("redoxfs: failed to open image {}: {}", path, err) } }else{ - //Create a 1 GB disk image - let size = 1024 * 1024 * 1024; + //Create a 4 MB disk image + let size = 4 * 1024 * 1024; match Image::create(&path, size) { Ok(disk) => match FileSystem::create(Box::new(disk)) { Ok(filesystem) => {