Fixes for dirs and files so they do not have to read all contents at once

This commit is contained in:
Jeremy Soller
2016-04-14 21:06:12 -06:00
parent f509c4b12c
commit e97f126f35
4 changed files with 146 additions and 73 deletions
+1 -1
View File
@@ -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)
+110 -36
View File
@@ -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,21 @@ impl FileResource {
Ok(i)
}
pub fn write(&mut self, buf: &[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]);
}
i += 1;
self.seek += 1;
}
Ok(i)
fn write(&mut self, _buf: &[u8], _fs: &mut FileSystem) -> Result<usize> {
Err(Error::new(EINVAL))
}
pub fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> {
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.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)
}
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 +72,87 @@ 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_DIR;
stat.st_size = self.data.len() as u64;
Ok(0)
}
pub fn sync(&mut self) -> Result<usize> {
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.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)
}
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> {
stat.st_mode = MODE_FILE;
stat.st_size = self.size;
Ok(0)
}
pub fn truncate(&mut self, len: usize) -> Result<usize> {
fn sync(&mut self) -> Result<usize> {
Ok(0)
}
fn truncate(&mut self, len: usize) -> Result<usize> {
Ok(0)
}
}
+23 -28
View File
@@ -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(&sector);
}
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))
}
+12 -8
View File
@@ -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, &sector));
try!(self.write_at(block, &sector));
}
byte_offset = 0;
}