host: process table, shell, coreutils and harness (T8, T9)
T8: sausage:process WIT (spawn, wait, kill), one store per process over the shared root, /proc/processes, /run, pipeline and cancellation groups, Exec. brush and 78 uutils commands; the shared cwd-init object sets the cwd from PWD and keeps numeric exit codes. The corpus matches native bash. T9: V8 (deno_core) runs pi-durable, pi-ai and chord; SQLite storage in <dir>/host/harness.sqlite (WAL, synchronous=FULL); file tools on the VFS, bash through Exec; resumes after SIGKILL.
This commit is contained in:
+33
-5
@@ -3,7 +3,7 @@
|
||||
//! Layout of a world directory:
|
||||
//! - `world/`: the virtual root `/` that every guest sees. Agents change everything in it.
|
||||
//! - `host/`: host state outside the sandbox (harness storage, later the vault). No guest sees it.
|
||||
use sausage_vfs::{Host, Layer, Mounts, Process};
|
||||
use sausage_vfs::{Generated, Host, Layer, Memory, Mounts, Process};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
@@ -15,18 +15,46 @@ pub struct World {
|
||||
pub root: Arc<dyn Layer>,
|
||||
/// The host state folder, `<dir>/host`.
|
||||
pub host_dir: PathBuf,
|
||||
/// Live process metadata shared with the process table.
|
||||
pub processes: crate::process::Processes,
|
||||
}
|
||||
|
||||
impl World {
|
||||
/// Open (and create if missing) the world directory `dir`. The process table adds more mounts
|
||||
/// (`/proc`, `/run`).
|
||||
/// Open (and create if missing) the world directory `dir`, including `/proc` and `/run` mounts.
|
||||
pub fn open(dir: &Path) -> anyhow::Result<Self> {
|
||||
let root_dir = dir.join("world");
|
||||
let host_dir = dir.join("host");
|
||||
std::fs::create_dir_all(&root_dir)?;
|
||||
std::fs::create_dir_all(&host_dir)?;
|
||||
let mut mounts = Mounts::default();
|
||||
mounts.mount("/", Arc::new(Host::new(&root_dir, Process::default())?), false);
|
||||
Ok(World { root: Arc::new(mounts), host_dir })
|
||||
mounts.mount(
|
||||
"/",
|
||||
Arc::new(Host::new(&root_dir, Process::default())?),
|
||||
false,
|
||||
);
|
||||
let processes: crate::process::Processes =
|
||||
Arc::new(std::sync::Mutex::new(Default::default()));
|
||||
let snapshot = processes.clone();
|
||||
let mut proc = Generated::default();
|
||||
proc.insert("/processes", move || {
|
||||
let mut text = String::from("PID\tPPID\tSTATE\tCWD\tARGV\n");
|
||||
for (pid, info) in snapshot.lock().unwrap().iter() {
|
||||
text.push_str(&format!(
|
||||
"{pid}\t{}\t{}\t{}\t{}\n",
|
||||
info.parent,
|
||||
info.state,
|
||||
info.cwd,
|
||||
info.argv.join(" ")
|
||||
));
|
||||
}
|
||||
Ok(text.into_bytes())
|
||||
});
|
||||
mounts.mount("/proc", Arc::new(proc), true);
|
||||
mounts.mount("/run", Arc::new(Memory::default()), false);
|
||||
Ok(World {
|
||||
root: Arc::new(mounts),
|
||||
host_dir,
|
||||
processes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user