Merge fuse and scheme, add mkfs utility, remove old utility
This commit is contained in:
+3
-14
@@ -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
@@ -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 = "*"
|
||||
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
mkdir -p test
|
||||
|
||||
cargo run --bin redoxfs-fuse test.bin test &
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
+134
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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),
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user