+8
-1
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Vendored
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,4 +1,4 @@
|
||||
use system::error::Result;
|
||||
use syscall::error::Result;
|
||||
|
||||
/// A disk
|
||||
pub trait Disk {
|
||||
|
||||
+5
-5
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user