RedoxFS 0.5.0

Significant re-design to use copy-on-write and hashes for all data
This commit is contained in:
Jeremy Soller
2021-12-29 16:11:54 -07:00
committed by Jeremy Soller
parent c98e63af87
commit 731b97262b
27 changed files with 3837 additions and 1602 deletions
+12 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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 {