feat(users): per-user sealed folders users/<id>/{home,apps,data,permissions}; storage SET_USER/LOCK/PURGE; init sign-in/sign-out loop (purge fresh/removed/guest, seed from factory, session start/stop); shell logout; pm user+system app shelves; terminal SIGNED_OUT; per-program stack (gatekeeper 12p); 128K load scratch
This commit is contained in:
@@ -78,12 +78,55 @@ pub trait FileSystem {
|
||||
fn seek(&mut self, handle: FileHandle, offset: usize) -> bool;
|
||||
/// Removes the directory at `path`, which must be empty.
|
||||
fn rmdir(&mut self, path: &[u8]) -> bool;
|
||||
/// The master key and a fresh random seed, once the owner is in; only
|
||||
/// an encrypting file system has a use for them.
|
||||
fn unlock(&mut self, _master: &[u8; 32], _seed: &[u8; 32]) {}
|
||||
/// The signed-in user's master key, a fresh random seed, and the name
|
||||
/// of their folder; only an encrypting file system has a use for them.
|
||||
fn unlock(&mut self, _master: &[u8; 32], _seed: &[u8; 32], _user: &[u8]) {}
|
||||
/// The user signed out: their key is forgotten.
|
||||
fn lock(&mut self) {}
|
||||
/// Removes the tree at `path`, whatever is in it.
|
||||
fn purge(&mut self, path: &[u8]) -> bool {
|
||||
remove_tree(self, path)
|
||||
}
|
||||
/// Whether anything can be written at all; the server refuses
|
||||
/// writing requests up front when not.
|
||||
fn writable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes everything under `path` and `path` itself, a directory or a
|
||||
/// file; true if nothing is left there.
|
||||
pub fn remove_tree<F: FileSystem + ?Sized>(fs: &mut F, path: &[u8]) -> bool {
|
||||
if fs.delete(path) {
|
||||
return true;
|
||||
}
|
||||
const BATCH: usize = 16;
|
||||
const LONGEST: usize = 255;
|
||||
loop {
|
||||
let mut entries = [DirEntry::empty(); BATCH];
|
||||
let Some(n) = fs.list_dir(path, &mut entries) else {
|
||||
// Neither a file nor a directory: nothing there.
|
||||
return true;
|
||||
};
|
||||
let children = entries[..n].iter().filter(|e| e.name.as_bytes() != b"." && e.name.as_bytes() != b"..");
|
||||
let mut any = false;
|
||||
for e in children {
|
||||
any = true;
|
||||
let mut child = [0u8; LONGEST];
|
||||
let name = e.name.as_bytes();
|
||||
let len = path.len() + 1 + name.len();
|
||||
if len > LONGEST {
|
||||
return false;
|
||||
}
|
||||
child[..path.len()].copy_from_slice(path);
|
||||
child[path.len()] = b'/';
|
||||
child[path.len() + 1..len].copy_from_slice(name);
|
||||
if !remove_tree(fs, &child[..len]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if !any {
|
||||
return fs.rmdir(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user