RedoxFS 0.5.0
Significant re-design to use copy-on-write and hashes for all data
This commit is contained in:
committed by
Jeremy Soller
parent
c98e63af87
commit
731b97262b
+12
-4
@@ -10,6 +10,8 @@ use redoxfs::{archive, DiskSparse, FileSystem};
|
||||
use uuid::Uuid;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
|
||||
let disk_path = if let Some(path) = args.next() {
|
||||
@@ -30,7 +32,7 @@ fn main() {
|
||||
|
||||
let bootloader_path_opt = args.next();
|
||||
|
||||
let disk = match DiskSparse::create(&disk_path) {
|
||||
let disk = match DiskSparse::create(&disk_path, 1024 * 1024 * 1024 /*TODO: make argument*/) {
|
||||
Ok(disk) => disk,
|
||||
Err(err) => {
|
||||
println!("redoxfs-ar: failed to open image {}: {}", disk_path, err);
|
||||
@@ -62,7 +64,13 @@ fn main() {
|
||||
};
|
||||
|
||||
let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||
match FileSystem::create_reserved(disk, &bootloader, ctime.as_secs(), ctime.subsec_nanos()) {
|
||||
match FileSystem::create_reserved(
|
||||
disk,
|
||||
None,
|
||||
&bootloader,
|
||||
ctime.as_secs(),
|
||||
ctime.subsec_nanos(),
|
||||
) {
|
||||
Ok(mut fs) => {
|
||||
let size = match archive(&mut fs, &folder_path) {
|
||||
Ok(ok) => ok,
|
||||
@@ -80,12 +88,12 @@ fn main() {
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let uuid = Uuid::from_bytes(&fs.header.1.uuid).unwrap();
|
||||
let uuid = Uuid::from_bytes(&fs.header.uuid()).unwrap();
|
||||
println!(
|
||||
"redoxfs-ar: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}",
|
||||
disk_path,
|
||||
fs.block,
|
||||
fs.header.1.size / 1000 / 1000,
|
||||
fs.header.size() / 1000 / 1000,
|
||||
uuid.hyphenated()
|
||||
);
|
||||
}
|
||||
|
||||
+62
-17
@@ -2,28 +2,47 @@ extern crate redoxfs;
|
||||
extern crate uuid;
|
||||
|
||||
use std::io::Read;
|
||||
use std::{env, fs, process, time};
|
||||
use std::{env, fs, io, process, time};
|
||||
|
||||
use redoxfs::{DiskFile, FileSystem};
|
||||
use termion::input::TermRead;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args().skip(1);
|
||||
fn usage() -> ! {
|
||||
eprintln!("redoxfs-mkfs [--encrypt] DISK [BOOTLOADER]");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let disk_path = if let Some(path) = args.next() {
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let mut encrypt = false;
|
||||
let mut disk_path_opt = None;
|
||||
let mut bootloader_path_opt = None;
|
||||
for arg in env::args().skip(1) {
|
||||
if arg == "--encrypt" {
|
||||
encrypt = true;
|
||||
} else if disk_path_opt.is_none() {
|
||||
disk_path_opt = Some(arg);
|
||||
} else if bootloader_path_opt.is_none() {
|
||||
bootloader_path_opt = Some(arg);
|
||||
} else {
|
||||
eprintln!("redoxfs-mkfs: too many arguments provided");
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
let disk_path = if let Some(path) = disk_path_opt {
|
||||
path
|
||||
} else {
|
||||
println!("redoxfs-mkfs: no disk image provided");
|
||||
println!("redoxfs-mkfs DISK [BOOTLOADER]");
|
||||
process::exit(1);
|
||||
eprintln!("redoxfs-mkfs: no disk image provided");
|
||||
usage();
|
||||
};
|
||||
|
||||
let bootloader_path_opt = args.next();
|
||||
|
||||
let disk = match DiskFile::open(&disk_path) {
|
||||
Ok(disk) => disk,
|
||||
Err(err) => {
|
||||
println!("redoxfs-mkfs: failed to open image {}: {}", disk_path, err);
|
||||
eprintln!("redoxfs-mkfs: failed to open image {}: {}", disk_path, err);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
@@ -34,7 +53,7 @@ fn main() {
|
||||
Ok(mut file) => match file.read_to_end(&mut bootloader) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"redoxfs-mkfs: failed to read bootloader {}: {}",
|
||||
bootloader_path, err
|
||||
);
|
||||
@@ -42,7 +61,7 @@ fn main() {
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"redoxfs-mkfs: failed to open bootloader {}: {}",
|
||||
bootloader_path, err
|
||||
);
|
||||
@@ -51,22 +70,48 @@ fn main() {
|
||||
}
|
||||
};
|
||||
|
||||
let password_opt = if encrypt {
|
||||
eprint!("redoxfs-mkfs: password: ");
|
||||
|
||||
let password = io::stdin()
|
||||
.read_passwd(&mut io::stderr())
|
||||
.unwrap()
|
||||
.unwrap_or(String::new());
|
||||
|
||||
eprintln!();
|
||||
|
||||
if password.is_empty() {
|
||||
eprintln!("redoxfs-mkfs: empty password, giving up");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
Some(password)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let ctime = time::SystemTime::now()
|
||||
.duration_since(time::UNIX_EPOCH)
|
||||
.unwrap();
|
||||
match FileSystem::create_reserved(disk, &bootloader, ctime.as_secs(), ctime.subsec_nanos()) {
|
||||
match FileSystem::create_reserved(
|
||||
disk,
|
||||
password_opt.as_ref().map(|x| x.as_bytes()),
|
||||
&bootloader,
|
||||
ctime.as_secs(),
|
||||
ctime.subsec_nanos(),
|
||||
) {
|
||||
Ok(filesystem) => {
|
||||
let uuid = Uuid::from_bytes(&filesystem.header.1.uuid).unwrap();
|
||||
println!(
|
||||
let uuid = Uuid::from_bytes(&filesystem.header.uuid()).unwrap();
|
||||
eprintln!(
|
||||
"redoxfs-mkfs: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}",
|
||||
disk_path,
|
||||
filesystem.block,
|
||||
filesystem.header.1.size / 1000 / 1000,
|
||||
filesystem.header.size() / 1000 / 1000,
|
||||
uuid.hyphenated()
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"redoxfs-mkfs: failed to create filesystem on {}: {}",
|
||||
disk_path, err
|
||||
);
|
||||
|
||||
+122
-63
@@ -11,11 +11,12 @@ extern crate uuid;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::process;
|
||||
|
||||
use redoxfs::{mount, DiskCache, DiskFile, FileSystem};
|
||||
use termion::input::TermRead;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
@@ -42,9 +43,7 @@ fn setsig() {
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
// on linux, this is implemented properly, so no need for this unscrupulous nonsense!
|
||||
fn setsig() {
|
||||
()
|
||||
}
|
||||
fn setsig() {}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn fork() -> isize {
|
||||
@@ -57,8 +56,11 @@ fn pipe(pipes: &mut [i32; 2]) -> isize {
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn capability_mode() {
|
||||
()
|
||||
fn capability_mode() {}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn bootloader_password() -> Option<Vec<u8>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
@@ -76,6 +78,37 @@ fn capability_mode() {
|
||||
syscall::setrens(0, 0).expect("redoxfs: failed to enter null namespace");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
fn bootloader_password() -> Option<Vec<u8>> {
|
||||
let addr_env = env::var_os("REDOXFS_PASSWORD_ADDR")?;
|
||||
let size_env = env::var_os("REDOXFS_PASSWORD_SIZE")?;
|
||||
|
||||
let addr = usize::from_str_radix(
|
||||
addr_env.to_str().expect("REDOXFS_PASSWORD_ADDR not valid"),
|
||||
16,
|
||||
)
|
||||
.expect("failed to parse REDOXFS_PASSWORD_ADDR");
|
||||
|
||||
let size = usize::from_str_radix(
|
||||
size_env.to_str().expect("REDOXFS_PASSWORD_SIZE not valid"),
|
||||
16,
|
||||
)
|
||||
.expect("failed to parse REDOXFS_PASSWORD_SIZE");
|
||||
|
||||
let mut password = Vec::with_capacity(size);
|
||||
unsafe {
|
||||
let password_map = syscall::physmap(addr, size, syscall::PhysmapFlags::empty())
|
||||
.expect("failed to map REDOXFS_PASSWORD");
|
||||
|
||||
for i in 0..size {
|
||||
password.push(*((password_map + i) as *const u8));
|
||||
}
|
||||
|
||||
let _ = syscall::physunmap(password_map);
|
||||
}
|
||||
Some(password)
|
||||
}
|
||||
|
||||
fn usage() {
|
||||
println!("redoxfs [--uuid] [disk or uuid] [mountpoint] [block in hex]");
|
||||
}
|
||||
@@ -85,35 +118,87 @@ enum DiskId {
|
||||
Uuid(Uuid),
|
||||
}
|
||||
|
||||
fn filesystem_by_path(path: &str, block_opt: Option<u64>) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
fn filesystem_by_path(
|
||||
path: &str,
|
||||
block_opt: Option<u64>,
|
||||
) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
println!("redoxfs: opening {}", path);
|
||||
match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
|
||||
Ok(disk) => match redoxfs::FileSystem::open(disk, block_opt) {
|
||||
Ok(filesystem) => {
|
||||
println!(
|
||||
"redoxfs: opened filesystem on {} with uuid {}",
|
||||
path,
|
||||
Uuid::from_bytes(&filesystem.header.1.uuid)
|
||||
.unwrap()
|
||||
.hyphenated()
|
||||
);
|
||||
let attempts = 10;
|
||||
for attempt in 0..=attempts {
|
||||
let password_opt = if attempt > 0 {
|
||||
eprint!("redoxfs: password: ");
|
||||
|
||||
return Some((path.to_string(), filesystem));
|
||||
let password = io::stdin()
|
||||
.read_passwd(&mut io::stderr())
|
||||
.unwrap()
|
||||
.unwrap_or(String::new());
|
||||
|
||||
eprintln!();
|
||||
|
||||
if password.is_empty() {
|
||||
eprintln!("redoxfs: empty password, giving up");
|
||||
|
||||
// Password is empty, exit loop
|
||||
break;
|
||||
}
|
||||
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err),
|
||||
},
|
||||
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err),
|
||||
|
||||
Some(password.into_bytes())
|
||||
} else {
|
||||
bootloader_password()
|
||||
};
|
||||
|
||||
match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
|
||||
Ok(disk) => match redoxfs::FileSystem::open(
|
||||
disk,
|
||||
password_opt.as_ref().map(|x| x.as_slice()),
|
||||
block_opt,
|
||||
true,
|
||||
) {
|
||||
Ok(filesystem) => {
|
||||
println!(
|
||||
"redoxfs: opened filesystem on {} with uuid {}",
|
||||
path,
|
||||
Uuid::from_bytes(&filesystem.header.uuid())
|
||||
.unwrap()
|
||||
.hyphenated()
|
||||
);
|
||||
|
||||
return Some((path.to_string(), filesystem));
|
||||
}
|
||||
Err(err) => match err.errno {
|
||||
syscall::ENOKEY => {
|
||||
if password_opt.is_some() {
|
||||
println!("redoxfs: incorrect password ({}/{})", attempt, attempts);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("redoxfs: failed to open filesystem {}: {}", path, err);
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
Err(err) => {
|
||||
println!("redoxfs: failed to open image {}: {}", path, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn filesystem_by_uuid(_uuid: &Uuid, _block_opt: Option<u64>) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
fn filesystem_by_uuid(
|
||||
_uuid: &Uuid,
|
||||
_block_opt: Option<u64>,
|
||||
) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
fn filesystem_by_uuid(uuid: &Uuid, block_opt: Option<u64>) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
fn filesystem_by_uuid(
|
||||
uuid: &Uuid,
|
||||
block_opt: Option<u64>,
|
||||
) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
|
||||
use std::fs;
|
||||
|
||||
match fs::read_dir(":") {
|
||||
@@ -128,16 +213,21 @@ fn filesystem_by_uuid(uuid: &Uuid, block_opt: Option<u64>) -> Option<(String, Fi
|
||||
Ok(entries) => {
|
||||
for entry_res in entries {
|
||||
if let Ok(entry) = entry_res {
|
||||
if let Ok(path) = entry.path().into_os_string().into_string() {
|
||||
if let Ok(path) =
|
||||
entry.path().into_os_string().into_string()
|
||||
{
|
||||
println!("redoxfs: found path {}", path);
|
||||
if let Some((path, filesystem)) = filesystem_by_path(&path, block_opt) {
|
||||
if &filesystem.header.1.uuid == uuid.as_bytes() {
|
||||
if let Some((path, filesystem)) =
|
||||
filesystem_by_path(&path, block_opt)
|
||||
{
|
||||
if &filesystem.header.uuid() == uuid.as_bytes()
|
||||
{
|
||||
println!(
|
||||
"redoxfs: filesystem on {} matches uuid {}",
|
||||
path,
|
||||
uuid.hyphenated()
|
||||
);
|
||||
return Some((path, filesystem))
|
||||
return Some((path, filesystem));
|
||||
} else {
|
||||
println!(
|
||||
"redoxfs: filesystem on {} does not match uuid {}",
|
||||
@@ -171,12 +261,8 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
|
||||
setsig();
|
||||
|
||||
let filesystem_opt = match *disk_id {
|
||||
DiskId::Path(ref path) => {
|
||||
filesystem_by_path(path, block_opt)
|
||||
}
|
||||
DiskId::Uuid(ref uuid) => {
|
||||
filesystem_by_uuid(uuid, block_opt)
|
||||
}
|
||||
DiskId::Path(ref path) => filesystem_by_path(path, block_opt),
|
||||
DiskId::Uuid(ref uuid) => filesystem_by_uuid(uuid, block_opt),
|
||||
};
|
||||
|
||||
if let Some((path, filesystem)) = filesystem_opt {
|
||||
@@ -215,24 +301,9 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
fn print_uuid(path: &str) {
|
||||
match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
|
||||
Ok(disk) => match redoxfs::FileSystem::open(disk, None) {
|
||||
Ok(filesystem) => {
|
||||
println!(
|
||||
"{}",
|
||||
Uuid::from_bytes(&filesystem.header.1.uuid)
|
||||
.unwrap()
|
||||
.hyphenated()
|
||||
);
|
||||
}
|
||||
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err),
|
||||
},
|
||||
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
|
||||
let disk_id = match args.next() {
|
||||
@@ -255,18 +326,6 @@ fn main() {
|
||||
};
|
||||
|
||||
DiskId::Uuid(uuid)
|
||||
} else if arg == "--get-uuid" {
|
||||
match args.next() {
|
||||
Some(arg) => {
|
||||
print_uuid(&arg);
|
||||
process::exit(1);
|
||||
}
|
||||
None => {
|
||||
println!("redoxfs: no disk provided");
|
||||
usage();
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
DiskId::Path(arg)
|
||||
}
|
||||
@@ -313,7 +372,7 @@ fn main() {
|
||||
drop(write);
|
||||
|
||||
let mut res = [0];
|
||||
read.read(&mut res).unwrap();
|
||||
read.read_exact(&mut res).unwrap();
|
||||
|
||||
process::exit(res[0] as i32);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user