File Class
Static methods for file operations: reading, writing, glob patterns, and file metadata.
Filesystem jail and symlink defense
When the application is started with soli serve <dir>, every path passed to slurp / barf / File.* / mkdir_p / file_write_* is resolved relative to <dir> and rejected if it escapes that root (via absolute paths, .. segments, or symlinks pointing outside). A controller calling File.read(req["params"]["path"]) therefore can no longer reach /etc/passwd.
On Unix, every File.* open additionally passes O_NOFOLLOW, and metadata lookups go through symlink_metadata. A path that is a symlink therefore fails to open through File.* even when the target is itself in-jail — this defends against local TOCTOU swaps that would otherwise race a canonicalised path against an attacker-supplied symlink.
CLI invocations (soli run, the REPL, the test runner) do not install a jail, so command-line scripts keep full filesystem access. Code that genuinely needs to step outside the jail or follow symlinks deliberately (log shippers, backup scripts, cron-style maintenance jobs, tailing a symlinked log file) should use the parallel Trusted class — Trusted.read("/var/log/..."), Trusted.write(...), etc. Its API mirrors File exactly but skips both the jail check and the O_NOFOLLOW flag, making the unsafe access explicit at the call site so reviewers and grep can find it.
File.read(path, encoding?)
Read file contents as a string. Pass a charset label ("latin1", "iso-8859-1", …) to decode a non-UTF-8 file. See Encoding.
content = File.read("config.json")
legacy = File.read("clients.csv", "latin1") # Latin-1 -> UTF-8
File.glob_recursive(pattern)
Match files using glob pattern (recursive).
files = File.glob_recursive("docs/**/*.md")
File.is_dir(path)
Check if path is a directory.
File.is_file(path)
Check if path is a file.
File.size(path)
Get file size in bytes.
File.modified(path)
Get file modification timestamp (Unix epoch in seconds).
time = File.modified("config.json")
File.copy(src, dest)
Copy file from source to destination.
File.rename(old, new)
Rename/move a file.
File.append(path, content)
Append content to file.
Trusted.* — unjailed file access
Trusted mirrors the entire File API (Trusted.read, Trusted.write, Trusted.append, Trusted.exists, Trusted.is_dir, Trusted.glob, …) but skips the filesystem jail and the O_NOFOLLOW symlink guard. Reach for it only from server-side code that legitimately must step outside <dir> or follow a symlink — log shippers, backup scripts, cron-style maintenance jobs — and never with a path derived from request input. Calls to Trusted.* from app/controllers/, app/middleware/, or app/views/ are flagged by the smell/dangerous-server-builtin lint.
log = Trusted.read("/var/log/app/today.log") # absolute path, outside the jail
Trusted.append("/var/log/app/audit.log", line) # follows a symlinked logfile