Merge pull request #2 from redox-os/new_kernel

New kernel
This commit is contained in:
Jeremy Soller
2016-10-26 13:21:48 -06:00
committed by GitHub
14 changed files with 389 additions and 282 deletions
+8 -1
View File
@@ -11,6 +11,10 @@ authors = ["Jeremy Soller <jackpot51@gmail.com>"]
name = "redoxfs"
path = "src/lib.rs"
[[bin]]
name = "redoxfs"
path = "scheme/main.rs"
[[bin]]
name = "redoxfs-fuse"
path = "fuse/main.rs"
@@ -20,6 +24,9 @@ name = "redoxfs-utility"
path = "utility/main.rs"
[dependencies]
redox-system = {path = "../system/"}
spin = "*"
syscall = {path = "../../syscall/"}
[target.'cfg(unix)'.dependencies]
fuse = "0.2"
time = "*"
+1 -2
View File
@@ -2,8 +2,7 @@ use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use system::error::{Error, Result, EIO};
use syscall::error::{Error, Result, EIO};
macro_rules! try_disk {
($expr:expr) => (match $expr {
+89 -109
View File
@@ -2,7 +2,7 @@
extern crate fuse;
extern crate redoxfs;
extern crate system;
extern crate syscall;
extern crate time;
use image::Image;
@@ -21,30 +21,34 @@ struct RedoxFS {
fs: redoxfs::FileSystem,
}
fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: node.1.mode & redoxfs::Node::MODE_PERM,
nlink: 1,
uid: node.1.uid,
gid: node.1.gid,
rdev: 0,
flags: 0,
}
}
impl Filesystem for RedoxFS {
fn lookup(&mut self, _req: &Request, parent_block: u64, name: &Path, reply: ReplyEntry) {
match self.fs.find_node(name.to_str().unwrap(), parent_block) {
Ok(node) => {
reply.entry(&TTL, &FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: 0o777,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
}, 0);
reply.entry(&TTL, &node_attr(&node), 0);
},
Err(err) => {
reply.error(err.errno as i32);
@@ -55,26 +59,7 @@ impl Filesystem for RedoxFS {
fn getattr(&mut self, _req: &Request, block: u64, reply: ReplyAttr) {
match self.fs.node(block) {
Ok(node) => {
reply.attr(&TTL, &FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: 0o777,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
});
reply.attr(&TTL, &node_attr(&node));
},
Err(err) => {
reply.error(err.errno as i32);
@@ -82,39 +67,70 @@ impl Filesystem for RedoxFS {
}
}
fn setattr(&mut self, _req: &Request, block: u64, _mode: Option<u32>,
_uid: Option<u32>, _gid: Option<u32>, size: Option<u64>,
fn setattr(&mut self, _req: &Request, block: u64, mode: Option<u32>,
uid: Option<u32>, gid: Option<u32>, size: Option<u64>,
_atime: Option<Timespec>, _mtime: Option<Timespec>, _fh: Option<u64>,
_crtime: Option<Timespec>, _chgtime: Option<Timespec>, _bkuptime: Option<Timespec>,
_flags: Option<u32>, reply: ReplyAttr) {
if let Some(truncate_size) = size {
if let Err(err) = self.fs.node_set_len(block, truncate_size) {
if let Some(mode) = mode {
match self.fs.node(block) {
Ok(mut node) => if node.1.mode & redoxfs::Node::MODE_PERM != mode as u16 & redoxfs::Node::MODE_PERM {
// println!("Chmod {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
node.1.mode = (node.1.mode & redoxfs::Node::MODE_TYPE) | (mode as u16 & redoxfs::Node::MODE_PERM);
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(uid) = uid {
match self.fs.node(block) {
Ok(mut node) => if node.1.uid != uid {
node.1.uid = uid;
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(gid) = gid {
match self.fs.node(block) {
Ok(mut node) => if node.1.gid != gid {
node.1.gid = gid;
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
}
},
Err(err) => {
reply.error(err.errno as i32);
return;
}
}
}
if let Some(size) = size {
if let Err(err) = self.fs.node_set_len(block, size) {
reply.error(err.errno as i32);
return;
}
}
match self.fs.node(block) {
Ok(node) => {
reply.attr(&TTL, &FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: 0o777,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
});
reply.attr(&TTL, &node_attr(&node));
},
Err(err) => {
reply.error(err.errno as i32);
@@ -180,29 +196,11 @@ impl Filesystem for RedoxFS {
}
}
fn create(&mut self, _req: &Request, parent_block: u64, name: &Path, _mode: u32, flags: u32, reply: ReplyCreate) {
match self.fs.create_node(redoxfs::Node::MODE_FILE, name.to_str().unwrap(), parent_block) {
fn create(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, flags: u32, reply: ReplyCreate) {
match self.fs.create_node(redoxfs::Node::MODE_FILE | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
Ok(node) => {
reply.created(&TTL, &FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: 0o777,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
}, 0, 0, flags);
// println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.created(&TTL, &node_attr(&node), 0, 0, flags);
},
Err(error) => {
reply.error(error.errno as i32);
@@ -210,29 +208,11 @@ impl Filesystem for RedoxFS {
}
}
fn mkdir(&mut self, _req: &Request, parent_block: u64, name: &Path, _mode: u32, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_DIR, name.to_str().unwrap(), parent_block) {
fn mkdir(&mut self, _req: &Request, parent_block: u64, name: &Path, mode: u32, reply: ReplyEntry) {
match self.fs.create_node(redoxfs::Node::MODE_DIR | (mode as u16 & redoxfs::Node::MODE_PERM), name.to_str().unwrap(), parent_block) {
Ok(node) => {
reply.entry(&TTL, &FileAttr {
ino: node.0,
size: node.1.extents[0].length,
blocks: (node.1.extents[0].length + 511)/512,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: if node.1.is_dir() {
FileType::Directory
} else {
FileType::RegularFile
},
perm: 0o777,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
}, 0);
// println!("Mkdir {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.entry(&TTL, &node_attr(&node), 0);
},
Err(error) => {
reply.error(error.errno as i32);
+1 -1
View File
@@ -2,7 +2,7 @@ use std::{cmp, ptr};
use redoxfs::Disk;
use system::error::Result;
use syscall::error::Result;
use self::lru_cache::LruCache;
+1 -1
View File
@@ -3,7 +3,7 @@ use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use system::error::{Error, Result, EIO};
use syscall::error::{Error, Result, EIO};
macro_rules! try_disk {
($expr:expr) => (match $expr {
+13 -15
View File
@@ -1,16 +1,15 @@
#![deny(warnings)]
extern crate redoxfs;
extern crate system;
extern crate spin;
extern crate syscall;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use spin::Mutex;
use cache::Cache;
use image::Image;
@@ -18,7 +17,7 @@ use scheme::FileScheme;
use redoxfs::FileSystem;
use system::scheme::{Packet, Scheme};
use syscall::{Packet, Scheme};
pub mod cache;
pub mod image;
@@ -43,15 +42,14 @@ fn main() {
Ok(mut socket) => {
println!("redoxfs: mounted filesystem {} on file:", path);
*status_daemon.lock().unwrap() = Status::Running;
*status_daemon.lock() = Status::Running;
let mut scheme = FileScheme::new(fs);
let scheme = FileScheme::new("file", fs);
loop {
let mut packet = Packet::default();
while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
socket.read(&mut packet).unwrap();
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
},
Err(err) => println!("redoxfs: failed to create file scheme: {}", err)
@@ -61,17 +59,17 @@ fn main() {
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
*status_daemon.lock().unwrap() = Status::Stopping;
*status_daemon.lock() = Status::Stopping;
});
'waiting: loop {
match *status_mutex.lock().unwrap() {
match *status_mutex.lock() {
Status::Starting => (),
Status::Running => break 'waiting,
Status::Stopping => break 'waiting,
}
thread::sleep(Duration::new(0, 30000000));
thread::yield_now();
}
} else {
println!("redoxfs: no disk image provided");
+51 -40
View File
@@ -2,30 +2,32 @@ use redoxfs::FileSystem;
use std::cmp::{min, max};
use system::error::{Error, Result, EINVAL};
use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END, MODE_DIR, MODE_FILE};
use syscall::error::{Error, Result, EINVAL};
use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
pub trait Resource {
fn dup(&self) -> Result<Box<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 seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem) -> Result<usize>;
fn path(&self, buf: &mut [u8]) -> Result<usize>;
fn stat(&self, _stat: &mut Stat) -> Result<usize>;
fn stat(&self, _stat: &mut Stat, fs: &mut FileSystem) -> Result<usize>;
fn sync(&mut self) -> Result<usize>;
fn truncate(&mut self, len: usize, fs: &mut FileSystem) -> Result<usize>;
}
pub struct DirResource {
path: String,
block: u64,
data: Vec<u8>,
seek: usize,
}
impl DirResource {
pub fn new(path: &str, data: Vec<u8>) -> DirResource {
pub fn new(path: String, block: u64, data: Vec<u8>) -> DirResource {
DirResource {
path: path.to_string(),
path: path,
block: block,
data: data,
seek: 0,
}
@@ -36,6 +38,7 @@ impl Resource for DirResource {
fn dup(&self) -> Result<Box<Resource>> {
Ok(Box::new(DirResource {
path: self.path.clone(),
block: self.block,
data: self.data.clone(),
seek: self.seek
}))
@@ -55,29 +58,37 @@ impl Resource for DirResource {
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,
fn seek(&mut self, offset: usize, whence: usize, _fs: &mut FileSystem) -> Result<usize> {
self.seek = match whence {
SEEK_SET => min(0, max(self.data.len() as isize, offset as isize)) as usize,
SEEK_CUR => min(0, max(self.data.len() as isize, self.seek as isize + offset as isize)) as usize,
SEEK_END => 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;
let path = self.path.as_bytes();
let mut i = 0;
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_DIR;
stat.st_size = self.data.len() as u32;
fn stat(&self, stat: &mut Stat, fs: &mut FileSystem) -> Result<usize> {
let node = try!(fs.node(self.block));
stat.st_mode = node.1.mode;
stat.st_uid = node.1.uid;
stat.st_gid = node.1.gid;
stat.st_size = try!(fs.node_len(self.block));
Ok(0)
}
@@ -94,16 +105,14 @@ pub struct FileResource {
path: String,
block: u64,
seek: u64,
size: u64,
}
impl FileResource {
pub fn new(path: &str, block: u64, size: u64) -> FileResource {
pub fn new(path: String, block: u64) -> FileResource {
FileResource {
path: path.to_string(),
path: path,
block: block,
seek: 0,
size: size,
}
}
}
@@ -114,7 +123,6 @@ impl Resource for FileResource {
path: self.path.clone(),
block: self.block,
seek: self.seek,
size: self.size
}))
}
@@ -127,36 +135,42 @@ impl Resource for FileResource {
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,
fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem) -> Result<usize> {
let size = try!(fs.node_len(self.block));
self.seek = match whence {
SEEK_SET => min(0, max(size as i64, offset as i64)) as u64,
SEEK_CUR => min(0, max(size as i64, self.seek as i64 + offset as i64)) as u64,
SEEK_END => min(0, max(size as i64, 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();
let mut i = 0;
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 as u32;
fn stat(&self, stat: &mut Stat, fs: &mut FileSystem) -> Result<usize> {
let node = try!(fs.node(self.block));
stat.st_mode = node.1.mode;
stat.st_uid = node.1.uid;
stat.st_gid = node.1.gid;
stat.st_size = try!(fs.node_len(self.block));
Ok(0)
}
@@ -165,11 +179,8 @@ impl Resource for FileResource {
}
fn truncate(&mut self, len: usize, fs: &mut FileSystem) -> Result<usize> {
if let Err(err) = fs.node_set_len(self.block, len as u64) {
Err(err)
} else {
self.size = len as u64;
Ok(0)
}
try!(fs.node_set_len(self.block, len as u64));
Ok(0)
}
}
+184 -88
View File
@@ -1,60 +1,87 @@
use resource::{Resource, DirResource, FileResource};
use redoxfs::{FileSystem, Node};
use spin::Mutex;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use system::error::{Error, Result, EEXIST, EISDIR, ENOTDIR, EPERM, ENOENT, EBADF};
use system::scheme::Scheme;
use system::syscall::{Stat, O_CREAT, O_TRUNC};
use syscall::error::{Error, Result, EACCES, EEXIST, EISDIR, ENOTDIR, EPERM, ENOENT, EBADF};
use syscall::scheme::Scheme;
use syscall::{Stat, O_CREAT, O_TRUNC};
pub struct FileScheme {
fs: FileSystem,
next_id: isize,
files: BTreeMap<usize, Box<Resource>>
name: &'static str,
fs: RefCell<FileSystem>,
next_id: AtomicUsize,
files: Mutex<BTreeMap<usize, Box<Resource>>>
}
impl FileScheme {
pub fn new(fs: FileSystem) -> FileScheme {
pub fn new(name: &'static str, fs: FileSystem) -> FileScheme {
FileScheme {
fs: fs,
next_id: 1,
files: BTreeMap::new()
name: name,
fs: RefCell::new(fs),
next_id: AtomicUsize::new(1),
files: Mutex::new(BTreeMap::new())
}
}
}
fn open_inner(&mut self, url: &str, flags: usize) -> Result<Box<Resource>> {
let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
impl Scheme for FileScheme {
fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
let path = str::from_utf8(url).unwrap_or("").trim_matches('/');
// println!("Open '{}' {:X}", path, flags);
//println!("Open '{}' {:X}", path, flags);
let mut fs = self.fs.borrow_mut();
let mut nodes = Vec::new();
let node_result = self.fs.path_nodes(path, &mut nodes);
let node_result = fs.path_nodes(path, &mut nodes);
for node in nodes.iter() {
if ! node.1.permission(uid, gid, Node::MODE_EXEC) {
// println!("dir not executable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
}
match node_result {
let resource: Box<Resource> = match node_result {
Ok(node) => if node.1.is_dir() {
if ! node.1.permission(uid, gid, Node::MODE_READ) {
// println!("dir not readable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
let mut data = Vec::new();
let mut children = Vec::new();
try!(self.fs.child_nodes(&mut children, node.0));
try!(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(b'\n');
}
data.extend_from_slice(&name.as_bytes());
if child.1.is_dir() {
data.push(b'/');
}
}
}
return Ok(Box::new(DirResource::new(url, data)));
Box::new(DirResource::new(path.to_string(), node.0, data))
} else {
if flags & O_TRUNC == O_TRUNC {
// println!("Truncate {}", path);
try!(self.fs.node_set_len(node.0, 0));
if ! node.1.permission(uid, gid, Node::MODE_READ) {
// println!("file not readable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
let size = try!(self.fs.node_len(node.0));
return Ok(Box::new(FileResource::new(url, node.0, size)));
if flags & O_TRUNC == O_TRUNC {
if ! node.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("file not writable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
try!(fs.node_set_len(node.0, 0));
}
Box::new(FileResource::new(path.to_string(), node.0))
},
Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT {
let mut last_part = String::new();
@@ -65,8 +92,16 @@ impl FileScheme {
}
if ! last_part.is_empty() {
if let Some(parent) = nodes.last() {
let node = try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0));
return Ok(Box::new(FileResource::new(url, node.0, 0)));
if ! parent.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("dir not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
let mut node = try!(fs.create_node(Node::MODE_FILE | (flags as u16 & Node::MODE_PERM), &last_part, parent.0));
node.1.uid = uid;
node.1.gid = gid;
try!(fs.write_at(node.0, &node.1));
Box::new(FileResource::new(path.to_string(), node.0))
} else {
return Err(Error::new(EPERM));
}
@@ -76,32 +111,31 @@ impl FileScheme {
} else {
return Err(err);
}
}
}
}
};
impl Scheme for FileScheme {
fn open(&mut self, url: &str, flags: usize) -> Result<usize> {
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, resource);
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.files.lock().insert(id, resource);
Ok(id)
}
fn mkdir(&mut self, url: &str, _mode: usize) -> Result<usize> {
let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
fn mkdir(&self, url: &[u8], mode: u16, uid: u32, gid: u32) -> Result<usize> {
let path = str::from_utf8(url).unwrap_or("").trim_matches('/');
// println!("Mkdir '{}'", path);
let mut fs = self.fs.borrow_mut();
let mut nodes = Vec::new();
match self.fs.path_nodes(path, &mut nodes) {
let node_result = fs.path_nodes(path, &mut nodes);
for node in nodes.iter() {
if ! node.1.permission(uid, gid, Node::MODE_EXEC) {
// println!("dir not executable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
}
match node_result {
Ok(_node) => Err(Error::new(EEXIST)),
Err(err) => if err.errno == ENOENT {
let mut last_part = String::new();
@@ -112,7 +146,16 @@ impl Scheme for FileScheme {
}
if ! last_part.is_empty() {
if let Some(parent) = nodes.last() {
self.fs.create_node(Node::MODE_DIR, &last_part, parent.0).and(Ok(0))
if ! parent.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("dir not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
let mut node = try!(fs.create_node(Node::MODE_DIR | (mode & Node::MODE_PERM), &last_part, parent.0));
node.1.uid = uid;
node.1.gid = gid;
try!(fs.write_at(node.0, &node.1));
Ok(0)
} else {
Err(Error::new(EPERM))
}
@@ -125,17 +168,36 @@ impl Scheme for FileScheme {
}
}
fn rmdir(&mut self, url: &str) -> Result<usize> {
let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
fn rmdir(&self, url: &[u8], uid: u32, gid: u32) -> Result<usize> {
let path = str::from_utf8(url).unwrap_or("").trim_matches('/');
// println!("Rmdir '{}'", path);
let mut fs = self.fs.borrow_mut();
let mut nodes = Vec::new();
let child = try!(self.fs.path_nodes(path, &mut nodes));
let child = try!(fs.path_nodes(path, &mut nodes));
for node in nodes.iter() {
if ! node.1.permission(uid, gid, Node::MODE_EXEC) {
// println!("dir not executable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
}
if let Some(parent) = nodes.last() {
if ! parent.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("dir not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
if child.1.is_dir() {
if ! child.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("dir not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
if let Ok(child_name) = child.1.name() {
self.fs.remove_node(Node::MODE_DIR, child_name, parent.0).and(Ok(0))
fs.remove_node(Node::MODE_DIR, child_name, parent.0).and(Ok(0))
} else {
Err(Error::new(ENOENT))
}
@@ -147,22 +209,36 @@ impl Scheme for FileScheme {
}
}
fn stat(&mut self, url: &str, stat: &mut Stat) -> Result<usize> {
let resource = try!(self.open_inner(url, 0));
resource.stat(stat)
}
fn unlink(&mut self, url: &str) -> Result<usize> {
let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
fn unlink(&self, url: &[u8], uid: u32, gid: u32) -> Result<usize> {
let path = str::from_utf8(url).unwrap_or("").trim_matches('/');
// println!("Unlink '{}'", path);
let mut fs = self.fs.borrow_mut();
let mut nodes = Vec::new();
let child = try!(self.fs.path_nodes(path, &mut nodes));
let child = try!(fs.path_nodes(path, &mut nodes));
for node in nodes.iter() {
if ! node.1.permission(uid, gid, Node::MODE_EXEC) {
// println!("dir not executable {:o}", node.1.mode);
return Err(Error::new(EACCES));
}
}
if let Some(parent) = nodes.last() {
if ! parent.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("dir not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
if ! child.1.is_dir() {
if ! child.1.permission(uid, gid, Node::MODE_WRITE) {
// println!("file not writable {:o}", parent.1.mode);
return Err(Error::new(EACCES));
}
if let Ok(child_name) = child.1.name() {
self.fs.remove_node(Node::MODE_FILE, child_name, parent.0).and(Ok(0))
fs.remove_node(Node::MODE_FILE, child_name, parent.0).and(Ok(0))
} else {
Err(Error::new(ENOENT))
}
@@ -176,45 +252,48 @@ impl Scheme for FileScheme {
/* Resource operations */
#[allow(unused_variables)]
fn dup(&mut self, old_id: usize) -> Result<usize> {
fn dup(&self, old_id: usize, _buf: &[u8]) -> Result<usize> {
// println!("Dup {}", old_id);
let resource = try!(try!(self.files.get(&old_id).ok_or(Error::new(EBADF))).dup());
let mut files = self.files.lock();
let resource = if let Some(old_resource) = files.get(&old_id) {
try!(old_resource.dup())
} else {
return Err(Error::new(EBADF));
};
let id = self.next_id as usize;
self.next_id += 1;
if self.next_id < 0 {
self.next_id = 1;
}
self.files.insert(id, resource);
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
files.insert(id, resource);
Ok(id)
}
#[allow(unused_variables)]
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
// println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
if let Some(mut file) = self.files.get_mut(&id) {
file.read(buf, &mut self.fs)
let mut files = self.files.lock();
if let Some(mut file) = files.get_mut(&id) {
file.read(buf, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
fn write(&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, &mut self.fs)
let mut files = self.files.lock();
if let Some(mut file) = files.get_mut(&id) {
file.write(buf, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&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)
let mut files = self.files.lock();
if let Some(mut file) = files.get_mut(&id) {
file.seek(pos, whence, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
@@ -222,8 +301,21 @@ impl Scheme for FileScheme {
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
// println!("Fpath {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
if let Some(file) = self.files.get(&id) {
file.path(buf)
let files = self.files.lock();
if let Some(file) = files.get(&id) {
let name = self.name.as_bytes();
let mut i = 0;
while i < buf.len() && i < name.len() {
buf[i] = name[i];
i += 1;
}
if i < buf.len() {
buf[i] = b':';
i += 1;
}
file.path(&mut buf[i..]).map(|count| i + count)
} else {
Err(Error::new(EBADF))
}
@@ -231,34 +323,38 @@ impl Scheme for FileScheme {
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)
let files = self.files.lock();
if let Some(file) = files.get(&id) {
file.stat(stat, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn fsync(&mut self, id: usize) -> Result<usize> {
fn fsync(&self, id: usize) -> Result<usize> {
// println!("Fsync {}", id);
if let Some(mut file) = self.files.get_mut(&id) {
let mut files = self.files.lock();
if let Some(mut file) = files.get_mut(&id) {
file.sync()
} else {
Err(Error::new(EBADF))
}
}
fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
fn ftruncate(&self, id: usize, len: usize) -> Result<usize> {
// println!("Ftruncate {}, {}", id, len);
if let Some(mut file) = self.files.get_mut(&id) {
file.truncate(len, &mut self.fs)
let mut files = self.files.lock();
if let Some(mut file) = files.get_mut(&id) {
file.truncate(len, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn close(&mut self, id: usize) -> Result<usize> {
fn close(&self, id: usize) -> Result<usize> {
// println!("Close {}", id);
if self.files.remove(&id).is_some() {
let mut files = self.files.lock();
if files.remove(&id).is_some() {
Ok(0)
} else {
Err(Error::new(EBADF))
+1 -1
View File
@@ -1,4 +1,4 @@
use system::error::Result;
use syscall::error::Result;
/// A disk
pub trait Disk {
+5 -5
View File
@@ -1,6 +1,6 @@
use std::cmp::min;
use system::error::{Result, Error, EEXIST, EISDIR, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY};
use syscall::error::{Result, Error, EEXIST, EISDIR, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY};
use super::{Disk, ExNode, Extent, Header, Node};
@@ -14,7 +14,7 @@ pub struct FileSystem {
impl FileSystem {
/// Open a file system on a disk
pub fn open(mut disk: Box<Disk>) -> Result<Self> {
for block in 0..8192 {
for block in 0..65536 {
let mut header = (0, Header::default());
try!(disk.read_at(block + header.0, &mut header.1));
@@ -45,7 +45,7 @@ impl FileSystem {
free.1.extents[0] = Extent::new(4, size - 4 * 512);
try!(disk.write_at(free.0, &free.1));
let root = (1, Node::new(Node::MODE_DIR, "root", 0));
let root = (1, Node::new(Node::MODE_DIR | 0o755, "root", 0));
try!(disk.write_at(root.0, &root.1));
let header = (0, Header::new(size, root.0, free.0));
@@ -61,11 +61,11 @@ impl FileSystem {
}
}
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
pub fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
self.disk.read_at(self.block + block, buffer)
}
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
pub fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
self.disk.write_at(self.block + block, buffer)
}
+1 -1
View File
@@ -4,7 +4,7 @@
#![deny(warnings)]
extern crate system;
extern crate syscall;
pub use self::disk::Disk;
pub use self::ex_node::ExNode;
+28 -11
View File
@@ -6,9 +6,9 @@ use super::Extent;
#[repr(packed)]
pub struct Node {
pub mode: u16,
pub user: u16,
pub group: u16,
pub name: [u8; 250],
pub uid: u32,
pub gid: u32,
pub name: [u8; 246],
pub parent: u64,
pub next: u64,
pub extents: [Extent; 15],
@@ -20,13 +20,16 @@ impl Node {
pub const MODE_DIR: u16 = 0x4000;
pub const MODE_PERM: u16 = 0x0FFF;
pub const MODE_EXEC: u16 = 0o1;
pub const MODE_WRITE: u16 = 0o2;
pub const MODE_READ: u16 = 0o4;
pub fn default() -> Node {
Node {
mode: 0,
user: 0,
group: 0,
name: [0; 250],
uid: 0,
gid: 0,
name: [0; 246],
parent: 0,
next: 0,
extents: [Extent::default(); 15],
@@ -34,15 +37,15 @@ impl Node {
}
pub fn new(mode: u16, name: &str, parent: u64) -> Node {
let mut bytes = [0; 250];
let mut bytes = [0; 246];
for (mut b, c) in bytes.iter_mut().zip(name.bytes()) {
*b = c;
}
Node {
mode: mode,
user: 0,
group: 0,
uid: 0,
gid: 0,
name: bytes,
parent: parent,
next: 0,
@@ -71,6 +74,20 @@ impl Node {
self.mode & Node::MODE_TYPE == Node::MODE_FILE
}
pub fn permission(&self, uid: u32, gid: u32, op: u16) -> bool {
let mut perm = self.mode & 0o7;
if self.uid == uid {
perm |= (self.mode >> 6) & 0o7;
}
if self.gid == gid || gid == 0 {
perm |= (self.mode >> 3) & 0o7;
}
if uid == 0 {
perm |= 0o7;
}
perm & op == op
}
pub fn size(&self) -> u64 {
self.extents.iter().fold(0, |size, extent| size + extent.length)
}
@@ -81,8 +98,8 @@ impl fmt::Debug for Node {
let extents: Vec<&Extent> = self.extents.iter().filter(|extent| -> bool { extent.length > 0 }).collect();
f.debug_struct("Node")
.field("mode", &self.mode)
.field("user", &self.user)
.field("group", &self.group)
.field("uid", &self.uid)
.field("gid", &self.gid)
.field("name", &self.name())
.field("next", &self.next)
.field("extents", &extents)
+1 -2
View File
@@ -2,8 +2,7 @@ use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use system::error::{Error, Result, EIO};
use syscall::error::{Error, Result, EIO};
macro_rules! try_disk {
($expr:expr) => (match $expr {
+5 -5
View File
@@ -1,8 +1,7 @@
#![deny(warnings)]
extern crate redoxfs;
extern crate system;
extern crate syscall;
use std::env;
use std::io::{self, Write};
@@ -218,9 +217,8 @@ fn main() {
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
}else{
//Create a 256 MB disk image
let size = 256 * 1024 * 1024;
}else if let Some(size_str) = args.next() {
let size = size_str.parse::<u64>().expect("redoxfs: size is not a valid number") * 1024 * 1024;
match Image::create(&path, size) {
Ok(disk) => match FileSystem::create(Box::new(disk)) {
Ok(filesystem) => {
@@ -231,6 +229,8 @@ fn main() {
},
Err(err) => println!("redoxfs: failed to create image {}: {}", path, err)
}
} else {
println!("redoxfs: no size provided");
}
} else {
println!("redoxfs: no disk image provided");