Filesystem information
Windows 93 uses IndexedDB to store files.
There exist two buckets, each with one object store called store. fileindex is first initialized as a dump of /files.cbor.
fs is all .desktop files, etc. Each file is given a unique identifier, and is stored as a File object.
Creating a driver
Driver architecture
The runtime selects a storage backend from mount points and delegates file operations to a driver.
Core flow:
FileSystemresolves a path to a mounted driver name in42/api/fs.js#L76.- Driver is loaded lazily through
42/api/fs/getDriverLazy.js#L5. - Files are represented by inodes in
FileIndex. - Inode format for stored files is
[id, mask, times](written in42/api/fs/class/BrowserDriver.js#L196). maskidentifies which backend owns that file. Cross-driver delegation is handled in42/api/fs/class/BrowserDriver.js#L141and42/api/fs/class/BrowserDriver.js#L247.
mask
A mask is a numeric backend identifier stored in each inode.
Mask mapping is defined in 42/api/fs/FileIndex.js#L7.
Current builtins:
0x10->memory0x12->localstorage0x13->indexeddb0x14->opfs
A new driver should have a unique mask value. Do not follow the sequential order above.
Simple implementation
The simplest path is to extend BrowserDriver in 42/api/fs/class/BrowserDriver.js.
Don't extend Driver.js
You must provide:
mask(number)storeobject with storage primitives compatible withBrowserDriver
Expected store methods:
has(id) -> boolean | Promise<boolean>get(id) -> Blob | File | undefined | Promise<...>set(id, data) -> void | Promise<void>wheredatais usuallyFile/Blobdelete(id) -> void | Promise<void>
BrowserDriver handles:
- inode metadata updates (
b/a/c/mtimes) - symlink and directory checks
- cross-driver delegation by mask
- stream wrappers (
sink/source)
Example
Create a file under 42/api/fs/driver, named using the <name>Driver.js convention.
The lazy loader imports by name pattern in 42/api/fs/getDriverLazy.js#L13, so naming must match.
Example skeleton:
import { BrowserDriver } from "../class/BrowserDriver.js"
class MyBackendDriver extends BrowserDriver {
mask = 0x19
async init() {
// optional: feature detection or fallback
// if unsupported: return this.getDriver("indexeddb")
this.store = {
has: async (id) => {
// return true/false
},
get: async (id) => {
// return File/Blob or undefined
},
set: async (id, data) => {
// persist data
},
delete: async (id) => {
// remove entry
},
}
return super.init()
}
}
export const driver = (...args) => new MyBackendDriver(...args).init()
Driver Registration
Add your new mask entry in 42/api/fs/FileIndex.js#L7.
Example:
0x15: "mybackend",
Rules:
- mask must be unique
- name should match your filename prefix (
mybackendDriver.js)
Eager loading vs lazy loading
Eager loading imports all drivers up front - basically, faster first-use access at the cost of higher startup time/memory. Lazy loading loads driver code only when a mounted path first needs it.
If code paths use eager loading via 42/api/fs/getDriver.js, also:
- import the driver module
- add it to
modules
If your runtime always uses lazy loading, this is optional, but keeping both loaders aligned would be recommended.
Mounting
Mount points are configured in 42/api/fs.js#L15.
Default root mount currently points to IndexedDB in 42/api/fs.js#L17.
Options:
- global mount: set
places: { "/": "mybackend" }in fs.js - scoped mount: call
fs.mount("/some/path", "mybackend")
Longest matching mount path wins (see sort logic in 42/api/fs.js#L104).
For browser-dependent APIs, implement feature detection in init() and fallback to IndexedDB when unavailable.
Reference behavior in 42/api/fs/driver/opfsDriver.js#L8.
misc info
Your backend must follow these expectations:
- IDs are opaque and generated by
uid()inBrowserDriver. - Data written through
write()is aFileobject get()should return an object compatible withBlobAPIs (arrayBuffer(),stream()).- Missing entries should return
undefinedwhere possible. DO NOT THROW!! delete()should be able to tolerate missing keys.
If things go wrong, here's where you messed up probably:
- mask not registered in
42/api/fs/FileIndex.js#L7 - returning non-Blob-compatible objects from
store.get - forgetting
return super.init()after setting upstore
Refer to these files
42/api/fs.js42/api/fs/class/BrowserDriver.js42/api/fs/getDriverLazy.js42/api/fs/getDriver.js42/api/fs/FileIndex.js42/api/fs/driver/indexeddbDriver.js42/api/fs/driver/opfsDriver.js42/api/fs/driver/localstorageDriver.js42/api/fs/driver/memoryDriver.js