Merge fuse and scheme, add mkfs utility, remove old utility

This commit is contained in:
Jeremy Soller
2016-12-13 18:05:03 -07:00
parent f1073d0c48
commit 9c2864e130
20 changed files with 241 additions and 500 deletions
+3 -14
View File
@@ -1,15 +1,4 @@
# Compiled files
*.o
*.so
*.rlib
*.dll
# Executables
*.exe
# Generated by Cargo
Cargo.lock
/target/
# Images
*.bin
target
image.bin
image
+4 -8
View File
@@ -2,7 +2,7 @@
name = "redoxfs"
description = "The Redox Filesystem"
repository = "https://github.com/redox-os/redoxfs"
version = "0.1.0"
version = "0.1.1"
license-file = "LICENSE"
readme = "README.md"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
@@ -13,15 +13,11 @@ path = "src/lib.rs"
[[bin]]
name = "redoxfs"
path = "scheme/main.rs"
path = "mount/main.rs"
[[bin]]
name = "redoxfs-fuse"
path = "fuse/main.rs"
[[bin]]
name = "redoxfs-utility"
path = "utility/main.rs"
name = "redoxfs-mkfs"
path = "mkfs/main.rs"
[dependencies]
spin = "*"
+22
View File
@@ -0,0 +1,22 @@
image.bin:
dd if=/dev/zero of=image.bin bs=1M count=1024
cargo build --release --bin redoxfs-mkfs
target/release/redoxfs-mkfs image.bin
mount: image.bin FORCE
mkdir -p image
cargo build --release --bin redoxfs
target/release/redoxfs image.bin image
unmount: FORCE
sync
-fusermount -u image
rm -rf image
clean: FORCE
sync
-fusermount -u image
rm -rf image image.bin
cargo clean
FORCE:
-26
View File
@@ -1,26 +0,0 @@
#!/bin/bash
rm -f test.bin
cargo run --bin redoxfs-utility test.bin << "EOF"
mk a_file
mkdir a_directory
cd a_directory
ed b_file
B FILE
.
cat b_file
ed c_file
C FILE
.
cat c_file
ls
exit
EOF
+2 -4
View File
@@ -1,8 +1,7 @@
use std::fs::File;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use syscall::error::{Error, Result, EIO};
macro_rules! try_disk {
@@ -21,7 +20,7 @@ pub struct Image {
impl Image {
pub fn open(path: &str) -> Result<Image> {
let file = try_disk!(File::open(path));
let file = try_disk!(OpenOptions::new().read(true).write(true).open(path));
Ok(Image {
file: file
})
@@ -30,7 +29,6 @@ impl Image {
impl Disk for Image {
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
// println!("Image read at {}", block);
try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
let count = try_disk!(self.file.read(buffer));
Ok(count)
+31
View File
@@ -0,0 +1,31 @@
#![deny(warnings)]
extern crate redoxfs;
extern crate syscall;
use std::env;
use std::str;
use redoxfs::FileSystem;
use image::Image;
pub mod image;
fn main() {
let mut args = env::args();
if let Some(path) = args.nth(1) {
//Open an existing image
match Image::open(&path) {
Ok(disk) => match FileSystem::create(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: created filesystem on {}, size {} MB", path, filesystem.header.1.size/1024/1024);
},
Err(err) => println!("redoxfs: failed to create filesystem on {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
} else {
println!("redoxfs: no disk image provided");
}
}
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
mkdir -p test
cargo run --bin redoxfs-fuse test.bin test &
View File
+8 -73
View File
@@ -1,24 +1,20 @@
#![deny(warnings)]
extern crate fuse;
extern crate redoxfs;
extern crate syscall;
extern crate time;
use image::Image;
use std::env;
use redoxfs;
use std::path::Path;
use time::Timespec;
use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyCreate, ReplyDirectory, ReplyEmpty, ReplyStatfs, ReplyWrite};
pub mod image;
use self::fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyCreate, ReplyDirectory, ReplyEmpty, ReplyStatfs, ReplyWrite};
use self::time::Timespec;
pub use self::fuse::mount;
const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second
const CREATE_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
struct RedoxFS {
fs: redoxfs::FileSystem,
pub struct Fuse {
pub fs: redoxfs::FileSystem,
}
fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
@@ -44,7 +40,7 @@ fn node_attr(node: &(u64, redoxfs::Node)) -> FileAttr {
}
}
impl Filesystem for RedoxFS {
impl Filesystem for Fuse {
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) => {
@@ -257,64 +253,3 @@ impl Filesystem for RedoxFS {
}
}
}
#[cfg(target_os = "macos")]
fn main() {
use std::ffi::OsStr;
if let Some(path) = env::args().nth(1) {
//Open an existing image
match Image::open(&path) {
Ok(disk) => match redoxfs::FileSystem::open(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
if let Some(mountpoint) = env::args_os().nth(2) {
fuse::mount(RedoxFS {
fs: filesystem
}, &mountpoint, &[
// One of the uses of this redoxfs fuse wrapper is to populate a filesystem
// while building the Redox OS kernel. This means that we need to write on
// a filesystem that belongs to `root`, which in turn means that we need to
// be `root`, thus that we need to allow `root` to have access.
OsStr::new("-o"),
OsStr::new("defer_permissions"),
]);
} else {
println!("redoxfs: no mount point provided");
}
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
} else {
println!("redoxfs: no disk image provided");
}
}
#[cfg(not(target_os = "macos"))]
fn main() {
if let Some(path) = env::args().nth(1) {
//Open an existing image
match Image::open(&path) {
Ok(disk) => match redoxfs::FileSystem::open(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
if let Some(mountpoint) = env::args_os().nth(2) {
fuse::mount(RedoxFS {
fs: filesystem
}, &mountpoint, &[]);
} else {
println!("redoxfs: no mount point provided");
}
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
} else {
println!("redoxfs: no disk image provided");
}
}
View File
+134
View File
@@ -0,0 +1,134 @@
#![deny(warnings)]
#![cfg_attr(unix, feature(libc))]
#[cfg(unix)]
extern crate libc;
extern crate redoxfs;
extern crate syscall;
use std::env;
use std::fs::File;
use std::os::unix::io::FromRawFd;
use std::path::Path;
use std::process;
use cache::Cache;
use image::Image;
pub mod cache;
pub mod image;
#[cfg(unix)]
pub mod fuse;
#[cfg(target_os = "redox")]
pub mod redox;
#[cfg(unix)]
fn fork() -> isize {
unsafe { libc::fork() as isize }
}
#[cfg(unix)]
fn pipe(pipes: &mut [i32; 2]) -> isize {
unsafe { libc::pipe2(pipes.as_mut_ptr(), 0) as isize }
}
#[cfg(all(unix, target_os = "macos"))]
fn mount<P: AsRef<Path>>(filesystem: redoxfs::FileSystem, mountpoint: &P, mut write: File) {
use std::io::Write;
let _ = write.write(&[0]);
drop(write);
fuse::mount(fuse::Fuse {
fs: filesystem
}, mountpoint, &[
// One of the uses of this redoxfs fuse wrapper is to populate a filesystem
// while building the Redox OS kernel. This means that we need to write on
// a filesystem that belongs to `root`, which in turn means that we need to
// be `root`, thus that we need to allow `root` to have access.
OsStr::new("-o"),
OsStr::new("defer_permissions"),
]);
}
#[cfg(all(unix, not(target_os = "macos")))]
fn mount<P: AsRef<Path>>(filesystem: redoxfs::FileSystem, mountpoint: &P, mut write: File) {
use std::io::Write;
let _ = write.write(&[0]);
drop(write);
fuse::mount(fuse::Fuse {
fs: filesystem
}, mountpoint, &[]);
}
#[cfg(target_os = "redox")]
fn fork() -> isize {
unsafe { syscall::Error::mux(syscall::clone(0)) as isize }
}
#[cfg(target_os = "redox")]
fn pipe(pipes: &mut [usize; 2]) -> isize {
syscall::Error::mux(syscall::pipe2(pipes, 0)) as isize
}
#[cfg(target_os = "redox")]
fn mount<P: AsRef<Path>>(filesystem: redoxfs::FileSystem, mountpoint: &P, write: File) {
redox::mount(filesystem, mountpoint, write);
}
fn main() {
use std::io::{Read, Write};
let mut pipes = [0; 2];
if pipe(&mut pipes) == 0 {
let mut read = unsafe { File::from_raw_fd(pipes[0]) };
let mut write = unsafe { File::from_raw_fd(pipes[1]) };
let pid = fork();
if pid == 0 {
drop(read);
if let Some(path) = env::args().nth(1) {
//Open an existing image
match Image::open(&path).map(|image| Cache::new(image)) {
Ok(disk) => match redoxfs::FileSystem::open(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
if let Some(mountpoint) = env::args_os().nth(2) {
mount(filesystem, &mountpoint, write);
process::exit(0);
} else {
println!("redoxfs: no mount point provided");
}
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
let _ = write.write(&[1]);
drop(write);
process::exit(1);
} else {
println!("redoxfs: no disk image provided");
}
} else if pid > 0 {
drop(write);
let mut res = [0];
read.read(&mut res).unwrap();
process::exit(res[0] as i32);
} else {
panic!("redoxfs: failed to fork");
}
} else {
panic!("redoxfs: failed to create pipe");
}
}
+33
View File
@@ -0,0 +1,33 @@
extern crate spin;
use redoxfs;
use syscall::{Packet, Scheme};
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use self::scheme::FileScheme;
pub mod resource;
pub mod scheme;
pub fn mount<P: AsRef<Path>>(filesystem: redoxfs::FileSystem, mountpoint: &P, mut write: File) {
let mountpoint = mountpoint.as_ref();
match File::create(format!(":{}", mountpoint.display())) {
Ok(mut socket) => {
println!("redoxfs: mounted filesystem on {}:", mountpoint.display());
let _ = write.write(&[0]);
drop(write);
let scheme = FileScheme::new(format!("{}", mountpoint.display()), filesystem);
loop {
let mut packet = Packet::default();
socket.read(&mut packet).unwrap();
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
},
Err(err) => println!("redoxfs: failed to create {} scheme: {}", mountpoint.display(), err)
}
}
+4 -4
View File
@@ -1,7 +1,7 @@
use resource::{Resource, DirResource, FileResource};
use redox::resource::{Resource, DirResource, FileResource};
use redox::spin::Mutex;
use redoxfs::{FileSystem, Node};
use spin::Mutex;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::str;
@@ -13,14 +13,14 @@ use syscall::flag::{O_CREAT, O_DIRECTORY, O_STAT, O_EXCL, O_TRUNC, O_ACCMODE, O_
use syscall::scheme::Scheme;
pub struct FileScheme {
name: &'static str,
name: String,
fs: RefCell<FileSystem>,
next_id: AtomicUsize,
files: Mutex<BTreeMap<usize, Box<Resource>>>
}
impl FileScheme {
pub fn new(name: &'static str, fs: FileSystem) -> FileScheme {
pub fn new(name: String, fs: FileSystem) -> FileScheme {
FileScheme {
name: name,
fs: RefCell::new(fs),
-72
View File
@@ -1,72 +0,0 @@
#![deny(warnings)]
extern crate redoxfs;
extern crate spin;
extern crate syscall;
use std::{env, process};
use std::fs::File;
use std::io::{Read, Write};
use cache::Cache;
use image::Image;
use scheme::FileScheme;
use redoxfs::FileSystem;
use syscall::{Packet, Scheme};
pub mod cache;
pub mod image;
pub mod resource;
pub mod scheme;
fn main() {
if let Some(path) = env::args().nth(1) {
let mut pipes = [0; 2];
syscall::pipe2(&mut pipes, 0).unwrap();
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
let _ = syscall::close(pipes[0]);
match Image::open(&path).map(|image| Cache::new(image)) {
Ok(disk) => match FileSystem::open(Box::new(disk)) {
Ok(fs) => match File::create(":file") {
Ok(mut socket) => {
println!("redoxfs: mounted filesystem {} on file:", path);
let _ = syscall::write(pipes[1], &[1]);
let scheme = FileScheme::new("file", fs);
loop {
let mut packet = Packet::default();
socket.read(&mut packet).unwrap();
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
},
Err(err) => println!("redoxfs: failed to create file scheme: {}", err)
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
let _ = syscall::write(pipes[1], &[0]);
let _ = syscall::close(pipes[1]);
} else {
let _ = syscall::close(pipes[1]);
let mut res = [0];
syscall::read(pipes[0], &mut res).unwrap();
let _ = syscall::close(pipes[0]);
process::exit(res[0] as i32);
}
} else {
println!("redoxfs: no disk image provided");
}
}
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
fusermount -u test
-55
View File
@@ -1,55 +0,0 @@
use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use syscall::error::{Error, Result, EIO};
macro_rules! try_disk {
($expr:expr) => (match $expr {
Ok(val) => val,
Err(err) => {
println!("Disk I/O Error: {}", err);
return Err(Error::new(EIO));
}
})
}
pub struct Image {
file: File
}
impl Image {
pub fn open(path: &str) -> Result<Image> {
let file = try_disk!(OpenOptions::new().read(true).write(true).open(path));
Ok(Image {
file: file
})
}
pub fn create(path: &str, size: u64) -> Result<Image> {
let file = try_disk!(OpenOptions::new().read(true).write(true).create(true).open(path));
try_disk!(file.set_len(size));
Ok(Image {
file: file
})
}
}
impl Disk for Image {
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
let count = try_disk!(self.file.read(buffer));
Ok(count)
}
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
let count = try_disk!(self.file.write(buffer));
Ok(count)
}
fn size(&mut self) -> Result<u64> {
let size = try_disk!(self.file.seek(SeekFrom::End(0)));
Ok(size)
}
}
-238
View File
@@ -1,238 +0,0 @@
#![deny(warnings)]
extern crate redoxfs;
extern crate syscall;
use std::env;
use std::io::{self, Write};
use std::path::Path;
use std::str;
use redoxfs::{FileSystem, Node};
use image::Image;
pub mod image;
fn shell(mut fs: FileSystem){
let mut block = fs.header.1.root;
let mut stdout = io::stdout();
let stdin = io::stdin();
loop {
stdout.write(b"redoxfs# ").unwrap();
stdout.flush().unwrap();
let mut line = String::new();
stdin.read_line(&mut line).unwrap();
let mut args = line.trim().split(' ');
if let Some(command) = args.next() {
match command {
"" => (),
"exit" => break,
"header" => println!("{:#?}", fs.header),
"node" => {
if let Some(arg) = args.next() {
match arg.parse::<u64>() {
Ok(block) => match fs.node(block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("node: failed to read {}: {}", block, err)
},
Err(err) => println!("node: invalid block {}: {}", arg, err)
}
} else {
println!("node <block>");
}
},
"root" => {
let block = fs.header.1.root;
match fs.node(block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("node: failed to read {}: {}", block, err)
}
},
"free" => {
let block = fs.header.1.free;
match fs.node(block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("node: failed to read {}: {}", block, err)
}
},
"cat" => {
if let Some(arg) = args.next() {
match fs.find_node(arg, block) {
Ok(node) => {
println!("{}: {:#?}", node.0, node.1);
let mut data = [0; 512];
match fs.read_node(node.0, 0, &mut data) {
Ok(count) => println!("cat: read {} bytes\n{}", count, unsafe { str::from_utf8_unchecked(&data) }),
Err(err) => println!("cat: failed to read {}: {}", node.0, err)
}
}
Err(err) => println!("cat: failed to create {}: {}", arg, err)
}
} else {
println!("cat <path>");
}
},
"cd" => {
if let Some(arg) = args.next() {
if arg == "." {
} else if arg == ".." {
match fs.node(block) {
Ok(node) => if node.1.parent > 0 {
block = node.1.parent;
println!("cd: {}", block);
} else {
println!("cd: no parent directory {}", block);
},
Err(err) => println!("cd: failed to read {}: {}", block, err)
}
} else {
match fs.find_node(arg, block) {
Ok(node) => if node.1.is_dir() {
block = node.0;
println!("cd: {}", block);
} else {
println!("cd: not a dir {}", arg);
},
Err(err) => println!("cd: failed to read {}: {}", arg, err)
}
}
} else {
println!("cd <path>");
}
},
"ed" => {
if let Some(arg) = args.next() {
match fs.create_node(Node::MODE_FILE, arg, block) {
Ok(node) => {
println!("{}: {:#?}", node.0, node.1);
let mut data = String::new();
loop {
let mut line = String::new();
stdin.read_line(&mut line).unwrap();
if line.is_empty() || line == ".\n" {
break;
} else {
data.push_str(&line);
}
}
println!("{}:\n{}", arg, data);
match fs.write_node(node.0, 0, &data.as_bytes()) {
Ok(count) => println!("ed: wrote {} bytes", count),
Err(err) => println!("ed: failed to write {}: {}", node.0, err)
}
}
Err(err) => println!("ed: failed to create {}: {}", arg, err)
}
} else {
println!("ed <path>");
}
},
"find" => {
if let Some(arg) = args.next() {
match fs.find_node(arg, block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("find: failed to read {}: {}", arg, err)
}
} else {
println!("find <path>");
}
},
"ls" => {
let mut children = Vec::new();
match fs.child_nodes(&mut children, block) {
Ok(()) => for node in children.iter() {
println!("{}: {:#?}", node.0, node.1);
},
Err(err) => println!("ls: failed to read {}: {}", block, err)
}
},
"mk" => {
if let Some(arg) = args.next() {
match fs.create_node(Node::MODE_FILE, arg, block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("mk: failed to create {}: {}", arg, err)
}
} else {
println!("mk <file>");
}
},
"mkdir" => {
if let Some(arg) = args.next() {
match fs.create_node(Node::MODE_DIR, arg, block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("mkdir: failed to create {}: {}", arg, err)
}
} else {
println!("mkdir <dir>");
}
},
"rm" => {
if let Some(arg) = args.next() {
match fs.remove_node(Node::MODE_FILE, arg, block) {
Ok(()) => println!("rm {}", arg),
Err(err) => println!("rm: failed to remove {}: {}", arg, err)
}
} else {
println!("rm <file>");
}
},
"rmdir" => {
if let Some(arg) = args.next() {
match fs.remove_node(Node::MODE_DIR, arg, block) {
Ok(()) => println!("rmdir {}", arg),
Err(err) => println!("rmdir: failed to remove {}: {}", arg, err)
}
} else {
println!("rmdir <dir>");
}
},
_ => println!("commands: exit header node root free cat ed find ls mk mkdir rm rmdir")
}
}
}
}
fn main() {
let mut args = env::args();
if let Some(path) = args.nth(1) {
if Path::new(&path).exists() {
//Open an existing image
match Image::open(&path) {
Ok(disk) => match FileSystem::open(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
shell(filesystem);
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
}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) => {
println!("redoxfs: created filesystem {}", path);
shell(filesystem);
},
Err(err) => println!("redoxfs: failed to create filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to create image {}: {}", path, err)
}
} else {
println!("redoxfs: no size provided");
}
} else {
println!("redoxfs: no disk image provided");
}
}