sausage-vfs: layers (host, memory, generated, mounts), process guards, wasi:filesystem adapter

Checkpoint. More tests and the review findings follow.
This commit is contained in:
2026-10-23 00:08:02 +01:00
parent 01712e745a
commit 0a479b5800
15 changed files with 1932 additions and 1 deletions
+66
View File
@@ -0,0 +1,66 @@
//! Exercises Rust filesystem clients through the virtual WASI filesystem.
use std::{
fs::{self, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
};
fn main() {
fs::create_dir("/work").unwrap();
fs::write("/work/a", b"hello").unwrap();
let mut f = OpenOptions::new()
.read(true)
.write(true)
.open("/work/a")
.unwrap();
f.seek(SeekFrom::Start(1)).unwrap();
f.write_all(b"A").unwrap();
f.set_len(4).unwrap();
f.sync_all().unwrap();
OpenOptions::new()
.append(true)
.open("/work/a")
.unwrap()
.write_all(b"!")
.unwrap();
assert_eq!(fs::read("/work/a").unwrap(), b"hAll!");
assert_eq!(fs::metadata("/work/a").unwrap().len(), 5);
fs::rename("/work/a", "/work/b").unwrap();
assert_eq!(fs::read("/work/../work/b").unwrap(), b"hAll!");
assert_eq!(fs::read("work/b").unwrap(), b"hAll!");
assert_eq!(fs::read_dir("/work").unwrap().count(), 1);
assert_eq!(
fs::write("/proc/no", b"no").unwrap_err().kind(),
std::io::ErrorKind::ReadOnlyFilesystem
);
assert_eq!(
fs::rename("/work/b", "/run/b").unwrap_err().kind(),
std::io::ErrorKind::CrossesDevices
);
let root = fs::read_dir("/")
.unwrap()
.map(|e| e.unwrap().file_name())
.collect::<Vec<_>>();
for name in ["proc", "run", "self"] {
assert!(root.iter().any(|n| n == name));
}
assert_eq!(fs::read("/proc/value").unwrap(), b"snapshot");
fs::write("/run/test", b"memory").unwrap();
assert_eq!(fs::read("/run/test").unwrap(), b"memory");
fs::remove_file("/work/b").unwrap();
fs::remove_dir("/work").unwrap();
// WASI std does not implement env::temp_dir, so select the folder explicitly.
let mut temp = tempfile::tempfile_in("/tmp").unwrap();
temp.write_all(b"temporary").unwrap();
temp.seek(SeekFrom::Start(0)).unwrap();
let mut text = String::new();
temp.read_to_string(&mut text).unwrap();
assert_eq!(text, "temporary");
let db = rusqlite::Connection::open("/database.sqlite").unwrap();
db.execute_batch("CREATE TABLE data (value TEXT); INSERT INTO data VALUES ('row');")
.unwrap();
drop(db);
let db = rusqlite::Connection::open("/database.sqlite").unwrap();
let row: String = db
.query_row("SELECT value FROM data", [], |r| r.get(0))
.unwrap();
assert_eq!(row, "row");
}