Merge branch 'tests' into 'master'
Tests See merge request redox-os/redoxfs!45
This commit is contained in:
+14
-2
@@ -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;
|
||||
|
||||
+32
-6
@@ -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();
|
||||
|
||||
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.
|
||||
let defer_permissions = [
|
||||
OsStr::new("-o"),
|
||||
OsStr::new("defer_permissions"),
|
||||
];
|
||||
|
||||
session.run()
|
||||
let mut session = Session::new(
|
||||
Fuse {
|
||||
fs: filesystem
|
||||
},
|
||||
mountpoint,
|
||||
if cfg!(target_os = "macos") {
|
||||
&defer_permissions
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
)?;
|
||||
|
||||
let res = callback(&mountpoint);
|
||||
|
||||
session.run()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub struct Fuse<D: Disk> {
|
||||
|
||||
+4
-28
@@ -1,35 +1,11 @@
|
||||
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;
|
||||
|
||||
+12
-7
@@ -1,4 +1,3 @@
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
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);
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user