Fixes for dirs and files so they do not have to read all contents at once
This commit is contained in:
+1
-1
@@ -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
@@ -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
@@ -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))
|
||||
}
|
||||
|
||||
+12
-8
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user