diff --git a/scheme/image.rs b/scheme/image.rs index b17b91408baa33a9584736ffddcc2dc1df962fbf..37444584898948d2baa31a0883c86cb3d749ad95 100644 --- a/scheme/image.rs +++ b/scheme/image.rs @@ -31,7 +31,7 @@ impl Image { impl Disk for Image { fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { - println!("Image read at {}", block); + // println!("Image read at {}", block); try_disk!(self.file.seek(SeekFrom::Start(block * 512))); let count = try_disk!(self.file.read(buffer)); Ok(count) diff --git a/scheme/resource.rs b/scheme/resource.rs index a72eebdf9a8708747e78237092bb11765d12223a..52e907ec3787d67fadb4934eb5ff6162b282ef6d 100644 --- a/scheme/resource.rs +++ b/scheme/resource.rs @@ -1,24 +1,44 @@ +use redoxfs::FileSystem; + use std::cmp::{min, max}; use system::error::{Error, Result, EINVAL}; -use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END}; +use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END, MODE_DIR, MODE_FILE}; -pub struct FileResource { +pub trait Resource { + fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result<usize>; + + fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result<usize>; + + fn seek(&mut self, offset: usize, whence: usize) -> Result<usize>; + + fn path(&self, buf: &mut [u8]) -> Result<usize>; + + fn stat(&self, _stat: &mut Stat) -> Result<usize>; + + fn sync(&mut self) -> Result<usize>; + + fn truncate(&mut self, len: usize) -> Result<usize>; +} + +pub struct DirResource { path: String, data: Vec<u8>, seek: usize, } -impl FileResource { - pub fn new(path: &str, data: Vec<u8>) -> FileResource { - FileResource { +impl DirResource { + pub fn new(path: &str, data: Vec<u8>) -> DirResource { + DirResource { path: path.to_string(), data: data, seek: 0, } } +} - pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> { +impl Resource for DirResource { + fn read(&mut self, buf: &mut [u8], _fs: &mut FileSystem) -> Result<usize> { let mut i = 0; while i < buf.len() && self.seek < self.data.len() { buf[i] = self.data[self.seek]; @@ -28,39 +48,91 @@ impl FileResource { Ok(i) } - pub fn write(&mut self, buf: &[u8]) -> Result<usize> { + fn write(&mut self, _buf: &[u8], _fs: &mut FileSystem) -> Result<usize> { + Err(Error::new(EINVAL)) + } + + 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, + SEEK_CUR => self.seek = min(0, max(self.data.len() as isize, self.seek as isize + offset as isize)) as usize, + SEEK_END => self.seek = min(0, max(self.data.len() as isize, self.data.len() as isize + offset as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + } + Ok(self.seek) + } + + fn path(&self, buf: &mut [u8]) -> Result<usize> { let mut i = 0; - while i < buf.len() { - if self.seek < self.data.len() { - self.data[self.seek] = buf[i]; - } else { - self.data.push(buf[i]); - } + let path = self.path.as_bytes(); + while i < buf.len() && i < path.len() { + buf[i] = path[i]; i += 1; - self.seek += 1; } Ok(i) } - pub fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> { + fn stat(&self, stat: &mut Stat) -> Result<usize> { + stat.st_mode = MODE_DIR; + stat.st_size = self.data.len() as u64; + Ok(0) + } + + fn sync(&mut self) -> Result<usize> { + Err(Error::new(EINVAL)) + } + + fn truncate(&mut self, _len: usize) -> Result<usize> { + Err(Error::new(EINVAL)) + } +} + +pub struct FileResource { + path: String, + block: u64, + seek: u64, + size: u64, +} + +impl FileResource { + pub fn new(path: &str, block: u64, size: u64) -> FileResource { + FileResource { + path: path.to_string(), + block: block, + seek: 0, + size: size, + } + } +} + +impl Resource for FileResource { + fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result<usize> { + let count = try!(fs.read_node(self.block, self.seek, buf)); + self.seek += count as u64; + Ok(count) + } + + fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result<usize> { + let count = try!(fs.write_node(self.block, self.seek, buf)); + self.seek += count as u64; + if self.seek > self.size { + self.size = self.seek; + } + Ok(count) + } + + 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)) + SEEK_SET => self.seek = min(0, max(self.size as i64, offset as i64)) as u64, + SEEK_CUR => self.seek = min(0, max(self.size as i64, self.seek as i64 + offset as i64)) as u64, + SEEK_END => self.seek = min(0, max(self.size as i64, self.size as i64 + offset as i64)) as u64, + _ => return Err(Error::new(EINVAL)) } + + Ok(self.seek as usize) } - pub fn path(&self, buf: &mut [u8]) -> Result<usize> { + 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() { @@ -70,15 +142,17 @@ impl FileResource { Ok(i) } - pub fn stat(&self, _stat: &mut Stat) -> Result<usize> { + fn stat(&self, stat: &mut Stat) -> Result<usize> { + stat.st_mode = MODE_FILE; + stat.st_size = self.size; Ok(0) } - pub fn sync(&mut self) -> Result<usize> { + fn sync(&mut self) -> Result<usize> { Ok(0) } - pub fn truncate(&mut self, len: usize) -> Result<usize> { + fn truncate(&mut self, len: usize) -> Result<usize> { Ok(0) } } diff --git a/scheme/scheme.rs b/scheme/scheme.rs index d0ba94369b77d37a274a0a804bff9d6b8168f721..410699e722127f9387814432bb4fbf45fb584540 100644 --- a/scheme/scheme.rs +++ b/scheme/scheme.rs @@ -1,4 +1,4 @@ -use resource::FileResource; +use resource::{Resource, DirResource, FileResource}; use redoxfs::{FileSystem, Node}; @@ -11,7 +11,7 @@ use system::syscall::{Stat, O_CREAT}; pub struct FileScheme { fs: FileSystem, next_id: isize, - files: BTreeMap<usize, FileResource> + files: BTreeMap<usize, Box<Resource>> } impl FileScheme { @@ -22,26 +22,22 @@ impl FileScheme { files: BTreeMap::new() } } -} -impl Scheme for FileScheme { - fn open(&mut self, url: &str, flags: usize, _mode: usize) -> Result<usize> { + fn open_inner(&mut self, url: &str, flags: usize) -> Result<Box<Resource>> { let path = url.split(':').nth(1).unwrap_or("").trim_matches('/'); - // println!("Open '{}' {:X}", path, flags); - let mut nodes = Vec::new(); let node_result = self.fs.path_nodes(path, &mut nodes); - let mut data = Vec::new(); match node_result { Ok(node) => if node.1.is_dir() { + let mut data = Vec::new(); let mut children = Vec::new(); try!(self.fs.child_nodes(&mut children, node.0)); for child in children.iter() { if let Ok(name) = child.1.name() { if ! data.is_empty() { - data.push('\n' as u8); + data.push(b'\n'); } data.extend_from_slice(&name.as_bytes()); if child.1.is_dir() { @@ -49,12 +45,10 @@ impl Scheme for FileScheme { } } } + return Ok(Box::new(DirResource::new(url, data))); } else { - for i in 0..(try!(self.fs.node_len(node.0)) + 511)/512 { - let mut sector = [0; 512]; - try!(self.fs.read_node(node.0, i as u64 * 512, &mut sector)); - data.extend_from_slice(§or); - } + let size = try!(self.fs.node_len(node.0)); + return Ok(Box::new(FileResource::new(url, node.0, size))); }, Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT { let mut last_part = String::new(); @@ -65,7 +59,8 @@ impl Scheme for FileScheme { } if ! last_part.is_empty() { if let Some(parent) = nodes.last() { - try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0)); + let node = try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0)); + return Ok(Box::new(FileResource::new(url, node.0, 0))); } else { return Err(Error::new(EPERM)); } @@ -76,23 +71,23 @@ impl Scheme for FileScheme { return Err(err); } } - /* - if let Some(arg) = args.next() { - match { - Ok(node) => println!("{}: {:#?}", node.0, node.1), - Err(err) => println!("mk: failed to create {}: {}", arg, err) - } - } else { - println!("mk <file>"); - } - */ + } +} + +impl Scheme for FileScheme { + fn open(&mut self, url: &str, flags: usize, _mode: usize) -> Result<usize> { + // println!("Open '{}' {:X}", path, flags); + + let resource = try!(self.open_inner(url, flags)); 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(url, data)); + + self.files.insert(id, resource); + Ok(id) } @@ -176,7 +171,7 @@ impl Scheme for FileScheme { // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); if let Some(mut file) = self.files.get_mut(&id) { - file.read(buf) + file.read(buf, &mut self.fs) } else { Err(Error::new(EBADF)) } @@ -185,7 +180,7 @@ impl Scheme for FileScheme { 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) + file.write(buf, &mut self.fs) } else { Err(Error::new(EBADF)) } diff --git a/src/filesystem.rs b/src/filesystem.rs index 4552a8cf34bedccb4e46632dd7d769dd387cb5e1..4252eebaa4170459db6b7215ade080395470a4a9 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -378,9 +378,11 @@ impl FileSystem { let mut sector = [0; 512]; try!(self.read_at(block, &mut sector)); - for (s_b, mut b) in sector[byte_offset..size].iter().zip(buf[i..].iter_mut()) { - *b = *s_b; - i += 1; + if byte_offset < size && i < buf.len() { + for (s_b, mut b) in sector[byte_offset..size].iter().zip(buf[i..].iter_mut()) { + *b = *s_b; + i += 1; + } } byte_offset = 0; @@ -404,12 +406,14 @@ impl FileSystem { for (block, size) in extent.blocks() { let mut sector = [0; 512]; - for (mut s_b, b) in sector[byte_offset..size].iter_mut().zip(buf[i..].iter()) { - *s_b = *b; - i += 1; - } + if byte_offset < size && i < buf.len() { + for (mut s_b, b) in sector[byte_offset..size].iter_mut().zip(buf[i..].iter()) { + *s_b = *b; + i += 1; + } - try!(self.write_at(block, §or)); + try!(self.write_at(block, §or)); + } byte_offset = 0; }