Guides using bun_sys for system calls and file I/O in Rust. Use when implementing file operations, opening fds, or any syscall path instead of std::fs or libc.
70
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use bun_sys instead of std::fs or raw libc for cross-platform syscalls with proper error handling.
For most file operations, use the bun_sys::File wrapper. It owns the fd and closes on Drop.
use bun_sys::{File, Fd, O};
let file = File::openat(Fd::cwd(), b"path/to/file", O::RDONLY, 0)?;
let mut buf = vec![0u8; 4096];
let n = file.read_all(&mut buf)?; // loops until EOF or full
// `file` closes on Drop.use bun_sys::{File, Fd, O};
pub fn write_file(path: &[u8], data: &[u8]) -> Result<(), bun_sys::Error> {
let file = File::openat(Fd::cwd(), path, O::WRONLY | O::CREAT | O::TRUNC, 0o664)?;
file.write_all(data)?;
Ok(())
}| Aspect | bun_sys | std::fs / libc |
|---|---|---|
| Return Type | Maybe<T> with rich Error | io::Error (lossy) |
| Windows | Full support with libuv fallback | Incomplete/POSIX-ish |
| Error Info | errno, syscall tag, path, fd | errno only |
| EINTR | Automatic retry | Manual handling |
| Paths | &[u8] (WTF-8 safe) | &Path (UTF-8 lossy) |
bun_sys functions return Maybe<T> = Result<T, bun_sys::Error>. Propagate with ?; convert to a JS exception via bun_sys_jsc::ErrorJsc::to_js:
use bun_sys_jsc::ErrorJsc;
use bun_sys::{File, Fd, O};
let file = match File::openat(Fd::cwd(), path, O::RDONLY, 0) {
Ok(f) => f,
Err(err) => return Ok(err.to_js(global)?),
};bun_sys::Error carries errno, syscall: Tag, and path: Box<[u8]>. To branch on errno:
match bun_sys::unlink(path) {
Ok(()) => {}
Err(e) if e.errno() == bun_c::ENOENT => {} // already gone
Err(e) => return Err(e),
}Fd (bun_core::Fd) — cross-platform file descriptor. Fd::cwd(), Fd::stdin()/stdout()/stderr(), fd.close().File::open(path: &ZStr, flags, mode) / File::openat(dir: Fd, path: &[u8], flags, mode) / File::make_open(...) (creates parent dirs) / File::create(dir, path, truncate)file.read(buf) / read_all(buf) / read_to_end() / read_to_end_small() / write(buf) / write_all(buf)bun_sys::open, read, write, pread, pwrite, stat, fstat, lstat, mkdir, unlink, rename, symlink, chmod — free fns over Fdbun_sys::O::RDONLY, O::WRONLY | O::CREAT | O::TRUNC, etc.Use bun_paths for joining/normalization and the path-buffer pool to avoid 64 KB stack allocations on Windows:
use bun_paths::{path_buffer_pool, resolve_path::{self, platform}};
let mut buf = path_buffer_pool::get();
let joined = resolve_path::join_string_buf::<platform::Auto>(&mut *buf, &[dir, name]);
let file = File::openat(Fd::cwd(), joined, O::RDONLY, 0)?;.unwrap() a bun_sys result that user input or the OS can cause to fail at runtime — return the error.std::fs::File — it loses the syscall tag and path needed for Node-compatible error objects.PathBuffer on the stack in hot paths — use path_buffer_pool::get().Drop alone closes a File — never file.fd().close() while the File is still live (double close).See src/CLAUDE.md for the full bun_core/bun_sys reference.
abe2ad4
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.