Spaces:
Runtime error
A 9p filesystem is supported by v86, using a virtio transport. There are several ways it can be set up.
Guest mount
In all cases, the filesystem is mounted in the guest system using the 9p
filesystem type and the host9p
device tag. Typically you want to be specific
with the version and transport options:
mount -t 9p -o trans=virtio,version=9p2000.L host9p /mnt/9p/
Here are kernel arguments you can use to boot directly off the 9p filesystem:
rw root=host9p rootfstype=9p rootflags=trans=virtio,version=9p2000.L
The aname
option can be used to pick the directory from 9p to mount. The rw
argument makes this a read-write root filesystem.
JSON/HTTP Filesystem
This is the standard way to setup the 9p filesystem. It loads files over
HTTP on-demand into an in-memory filesystem in JS. This allows files to be
exchanged with the guest OS. See create_file
and read_file
in
starter.js
.
This mode is enabled by passing the following options to V86
:
filesystem: {
basefs: "../9p/fs.json",
baseurl: "../9p/base/",
}
Here, basefs
is a json file created using
fs2json.py and the baseurl
directory is created using
copy-to-sha256.py.
If basefs
and baseurl
are omitted, an empty 9p filesystem is created. Unless
you configure one of the alternative modes.
Function Handler
You can handle 9p messages directly in JavaScript yourself by providing a
function as handle9p
under filesystem
:
filesystem: {
handle9p: async (reqBuf, reply) => {
// reqBuf is a Uint8Array of the entire request frame.
// you can parse these bytes using a library or reading the 9p spec.
// once you formulate a response, you send the reply frame as a
// Uint8Array by passing it to reply: reply(respBuf)
}
}
This allows you to implement a 9p server or custom proxy in JS. However, this
filesystem will not be cached (unless cached in the guest OS), functions like
create_file
and read_file
will not be available, and you will be responsible
for keeping its state in sync with any machine save states.
WebSocket Proxy
You can also back the 9p virtio filesystem with a 9p server over WebSocket by providing a WS proxy URL:
filesystem: {
proxy_url: "ws://localhost:8080/"
}
Simlar to using handle9p
, this filesystem will not be available in JS and
will need to be re-mounted after restoring state.
The WS proxy just needs to hand off messages with a connection to a normal 9p server. Each binary WebSocket message is the full buffer of a request or a reply.
To implement, request message bytes can just be sent directly to the 9p connection, but the 9p reply stream needs to be buffered into a single binary WebSocket message. The proxy must at least parse the first 4 bytes to get the message size and use it to buffer a full message before sending over WebSocket.
The wanix CLI has a serve
command that
not only serves a directory over HTTP, but also over 9P via WebSocket. You can
see how it implements a proxy in Go.