Commit 4578a222 authored by Jeremy Soller's avatar Jeremy Soller

Tests

parent 5e5656f1
......@@ -56,6 +56,11 @@ fn pipe(pipes: &mut [i32; 2]) -> isize {
unsafe { libc::pipe(pipes.as_mut_ptr()) as isize }
}
#[cfg(not(target_os = "redox"))]
fn capability_mode() {
()
}
#[cfg(target_os = "redox")]
fn fork() -> isize {
unsafe { syscall::Error::mux(syscall::clone(0)) as isize }
......@@ -66,6 +71,11 @@ fn pipe(pipes: &mut [usize; 2]) -> isize {
syscall::Error::mux(syscall::pipe2(pipes, 0)) as isize
}
#[cfg(target_os = "redox")]
fn capability_mode() {
syscall::setrens(0, 0).expect("redoxfs: failed to enter null namespace");
}
fn usage() {
println!("redoxfs [--uuid] [disk or uuid] [mountpoint]");
}
......@@ -154,8 +164,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, mut write: File) -> ! {
};
if matches {
match mount(filesystem, &mountpoint, || {
println!("redoxfs: mounted filesystem on {} to {}", path, mountpoint);
match mount(filesystem, &mountpoint, |mounted_path| {
capability_mode();
println!("redoxfs: mounted filesystem on {} to {}", path, mounted_path.display());
let _ = write.write(&[0]);
}) {
Ok(()) => {
......
......@@ -28,3 +28,6 @@ mod filesystem;
mod header;
mod mount;
mod node;
#[cfg(test)]
mod tests;
......@@ -20,14 +20,40 @@ const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second
const NULL_TIME: Timespec = Timespec { sec: 0, nsec: 0 };
pub fn mount<D: Disk, P: AsRef<Path>, F: FnMut()>(filesystem: filesystem::FileSystem<D>, mountpoint: P, mut callback: F, options: &[&OsStr]) -> io::Result<()> {
let mut session = Session::new(Fuse {
fs: filesystem
}, mountpoint.as_ref(), options)?;
pub fn mount<D, P, T, F>(filesystem: filesystem::FileSystem<D>, mountpoint: P, mut callback: F)
-> io::Result<T> where
D: Disk,
P: AsRef<Path>,
F: FnMut(&Path) -> T
{
let mountpoint = mountpoint.as_ref();
// 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.
let defer_permissions = [
OsStr::new("-o"),
OsStr::new("defer_permissions"),
];
let mut session = Session::new(
Fuse {
fs: filesystem
},
mountpoint,
if cfg!(target_os = "macos") {
&defer_permissions
} else {
&[]
}
)?;
let res = callback(&mountpoint);
callback();
session.run()?;
session.run()
Ok(res)
}
pub struct Fuse<D: Disk> {
......
use std::io;
use std::path::Path;
use disk::Disk;
use filesystem::FileSystem;
#[cfg(not(target_os = "redox"))]
mod fuse;
#[cfg(not(target_os = "redox"))]
pub use self::fuse::mount;
#[cfg(target_os = "redox")]
mod redox;
#[cfg(target_os = "macos")]
pub fn mount<D: Disk, P: AsRef<Path>, F: FnMut()>(filesystem: FileSystem<D>, mountpoint: P, callback: F) -> io::Result<()> {
use std::ffi::OsStr;
fuse::mount(filesystem, mountpoint, callback, &[
// 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(not(target_os = "macos"), not(target_os = "redox")))]
pub fn mount<D: Disk, P: AsRef<Path>, F: FnMut()>(filesystem: FileSystem<D>, mountpoint: P, callback: F) -> io::Result<()> {
fuse::mount(filesystem, mountpoint, callback, &[])
}
#[cfg(target_os = "redox")]
pub fn mount<D: Disk, P: AsRef<Path>, F: FnMut()>(filesystem: FileSystem<D>, mountpoint: P, callback: F) -> io::Result<()> {
redox::mount(filesystem, mountpoint, callback)
}
pub use self::redox::mount;
use syscall;
use syscall::{Packet, Scheme};
use std::fs::File;
use std::io::{self, Read, Write};
......@@ -14,22 +13,28 @@ use self::scheme::FileScheme;
pub mod resource;
pub mod scheme;
pub fn mount<D: Disk, P: AsRef<Path>, F: FnMut()>(filesystem: FileSystem<D>, mountpoint: P, mut callback: F) -> io::Result<()> {
pub fn mount<D, P, T, F>(filesystem: FileSystem<D>, mountpoint: P, mut callback: F)
-> io::Result<T> where
D: Disk,
P: AsRef<Path>,
F: FnMut(&Path) -> T
{
let mountpoint = mountpoint.as_ref();
let mut socket = File::create(format!(":{}", mountpoint.display()))?;
let socket_path = format!(":{}", mountpoint.display());
let mut socket = File::create(&socket_path)?;
callback();
syscall::setrens(0, 0).expect("redoxfs: failed to enter null namespace");
let mounted_path = format!("{}:", mountpoint.display());
let res = callback(Path::new(&mounted_path));
let scheme = FileScheme::new(format!("{}", mountpoint.display()), filesystem);
loop {
if IS_UMT.load(Ordering::SeqCst) > 0 {
break Ok(());
break Ok(res);
}
let mut packet = Packet::default();
match socket.read(&mut packet) {
Ok(0) => break Ok(res),
Ok(_ok) => (),
Err(err) => if err.kind() == io::ErrorKind::Interrupted {
continue;
......
......@@ -221,7 +221,7 @@ impl Fmap {
block,
offset: map.offset,
flags: map.flags,
data: &mut buf[..count],
data: buf,
})
}
......
use std::{fs, sync, thread, time};
use std::ops::DerefMut;
use std::path::Path;
use std::process::Command;
use crate::{DiskSparse, FileSystem};
fn with_redoxfs<T, F>(callback: F)
-> T where
T: Send + Sync + 'static,
F: FnMut(&Path) -> T + Send + Sync + 'static
{
let disk_path = "image.bin";
let mount_path = "image";
let res = {
let disk = DiskSparse::create(dbg!(disk_path)).unwrap();
if cfg!(not(target_os = "redox")) {
if ! Path::new(mount_path).exists() {
dbg!(fs::create_dir(dbg!(mount_path))).unwrap();
}
}
let ctime = dbg!(time::SystemTime::now().duration_since(time::UNIX_EPOCH)).unwrap();
let fs = FileSystem::create_reserved(disk, &[], ctime.as_secs(), ctime.subsec_nanos()).unwrap();
let callback_mutex = sync::Arc::new(sync::Mutex::new(callback));
let join_handle = crate::mount(fs, dbg!(mount_path), move |real_path| {
let callback_mutex = callback_mutex.clone();
let real_path = real_path.to_owned();
thread::spawn(move || {
let res = {
let mut callback_guard = callback_mutex.lock().unwrap();
let callback = callback_guard.deref_mut();
callback(&real_path)
};
if cfg!(target_os = "redox") {
dbg!(fs::remove_file(dbg!(format!(":{}", mount_path)))).unwrap();
} else {
let status_res = if cfg!(target_os = "linux") {
Command::new("fusermount")
.arg("-u")
.arg(mount_path)
.status()
} else {
Command::new("umount")
.arg(mount_path)
.status()
};
let status = dbg!(status_res).unwrap();
if ! status.success() {
panic!("umount failed");
}
}
res
})
}).unwrap();
join_handle.join().unwrap()
};
dbg!(fs::remove_file(dbg!(disk_path))).unwrap();
if cfg!(not(target_os = "redox")) {
dbg!(fs::remove_dir(dbg!(mount_path))).unwrap();
}
res
}
#[test]
fn simple() {
with_redoxfs(|path| {
dbg!(fs::create_dir(&path.join("test"))).unwrap();
})
}
#[cfg(target_os = "redox")]
#[test]
fn mmap() {
use std::os::unix::ffi::OsStrExt;
use syscall;
//TODO
with_redoxfs(|path| {
use std::slice;
let path = dbg!(path.join("test"));
let mmap_inner = |write: bool| {
let fd = dbg!(
syscall::open(
path.as_os_str().as_bytes(),
syscall::O_CREAT | syscall::O_RDWR | syscall::O_CLOEXEC
)
).unwrap();
let map = unsafe {
slice::from_raw_parts_mut(
dbg!(
syscall::fmap(fd, &syscall::Map {
offset: 0,
size: 128,
flags: syscall::PROT_READ | syscall::PROT_WRITE
})
).unwrap() as *mut u8,
128
)
};
// Maps should be available after closing
assert_eq!(dbg!(syscall::close(fd)), Ok(0));
for i in 0..128 {
if write {
map[i as usize] = i;
}
assert_eq!(map[i as usize], i);
}
//TODO: add msync
unsafe {
assert_eq!(dbg!(
syscall::funmap(map.as_mut_ptr() as usize)
), Ok(0));
}
};
mmap_inner(true);
mmap_inner(false);
})
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment