Skip to content

VFS

Do can perform operations indirectly through the dolang-vfs companion program. VFS1 contexts power containers, SSH remoting, libvirt guests, WSL transitions, and privilege elevation.

Architecture

The Do interpreter and program state remain in the original process. dolang-vfs runs on the selected target and performs target-side operations on the interpreter's behalf:

Value or operation Context behavior
fs, proc.run, shell.env, shell.cd, sys, security Follow the active target
VFS-aware extensions Follow the target as documented by the extension
HTTP and ordinary network clients Stay in the interpreter process
Path values Carry a path style, but no target identity
Open files and other handles Remain bound to the target that created them

Contexts may be nested. For example, a local interpreter can enter an SSH host and then connect to a container VFS on that host. Leaving a context restores the complete previous target.

Context Scope

Call Vfs.with with a block to enter its context:

import sys
  fs:
    - Path
  shell:
    - Vfs

let remote = Vfs do run ssh -T -e none server.example.com dolang-vfs --stdio
try
  remote.with do
    echo $sys.os_info().os
    run hostname
    echo $Path(".").canonical()
finally
  remote.stop()

The context is block-scoped. When the block returns or throws, the previous context is restored. A Vfs handle can be entered more than once. Each entry starts at the working directory captured when the handle was created; cd and environment changes made during one entry do not change the starting state of later entries.

The following operations use the active context:

Operation Target behavior
fs Reads and writes the target filesystem
proc.run Resolves and launches programs on the target
shell.env and shell.cd Use target environment and path conventions
sys Reports the target OS and CPU
security Reports and resolves the target identity
VFS-aware extensions Use files or services exposed through the active VFS
Other APIs Remain in the interpreter process unless documented otherwise

Paths, Scopes and Handles

A Path captures its Unix or Windows path style, but not a particular host or VFS context. Each operation interprets the path literally in the current context at the time of use. An absolute path can therefore name a file on any compatible target, while a relative path also depends on that context's current working directory.

Constructing Path from a string uses the current target's path style. UnixPath and WindowsPath select a style explicitly. Moving a Path between contexts does not retain access to its original target.

Open files and other handles behave differently. A handle is bound to the VFS context that created it, so operations on it continue to address that context even when another context is current.

Handles remain valid only while their originating VFS context remains connected. Calling stop(), losing the connection, or leaving a helper that owns a block-scoped connection invalidates its handles. ssh.with, docker.with, podman.with, wsl.with_linux, wsl.with_windows, sudo.with, and admin.with all tear down the context upon leaving the provided block, so any I/O to Files opened in the block must also take place within it.

Manually constructed Vfs instances are not automatically torn down; that is the user's responsibility.

Returning to the Host

shell.with_host temporarily returns to the interpreter's original host context:

remote.with do
  let remote_name = sub do run hostname
  with_host do
    echo "remote: $remote_name"
    echo "local: $(sub do run hostname)"

with_host temporarily reverts the VFS context to the interpreter's startup context, including its original working directory and environment.

Connections

Vfs func connects to any strand which speaks the VFS protocol on its input and output pipe, typically by immediately running dolang-vfs --stdio. Vfs.unix_socket connects to a dolang-vfs --listen <socket_path> instance on Unix, and Vfs.windows_admin performs Windows UAC elevation.

Unix-socket and Windows administrator connections are resolved through the active context. This makes it possible to enter an SSH host and then connect to a container VFS reachable from that host, or to UAC elevate from WSL.

Call stop() when a manually created handle is no longer needed to shut down the VFS process and clean up related local resources. Prefer helpers such as ssh.with, docker.with, podman.with, wsl.with_linux, and admin.with; they clean up their VFS sessions when the block returns or throws.

Errors

Target system errors cross the transport without being converted to the interpreter host's error model. A Windows target returns Windows native error codes even when the interpreter runs on Linux; see System Errors.

Version Compatibility

The VFS protocol does not currently negotiate versions. Use dolang and dolang-vfs from the same build or release. Other combinations are unsupported and may fail with a protocol error. Protocol versioning is planned for a stable release.

Trust Boundary

dolang-vfs executes arbitrary operations with its target identity. Always restrict access to its client endpoint. Do not run the client endpoint on a system you do not trust, as a local administrator could possibly take control of it. The protocol is not encrypted, so always tunnel it over a secure channel such as SSH if traversing a network.

Limitations

Only APIs documented as VFS-aware follow the target. For example, an HTTP client still opens network connections from the interpreter process.


  1. Versatile Familiar Spirit