Zig System Calls
Cross-platform system calls and file I/O with Bun's enhanced error handling
✨ The solution you've been looking for
Guides using bun.sys for system calls and file I/O in Zig. Use when implementing file operations instead of std.fs or std.posix.
See It In Action
Interactive preview & real-world examples
AI Conversation Simulator
See how users interact with this skill
User Prompt
I need to write a file utility in Zig that handles errors gracefully and works on both Windows and Linux. Show me how to read and write files using bun.sys.
Skill Processing
Analyzing request...
Agent Response
Complete file I/O implementation using bun.sys.File with proper error handling and cross-platform compatibility
Quick Start (3 Steps)
Get up and running in minutes
Install
claude-code skill install zig-system-calls
claude-code skill install zig-system-callsConfig
First Trigger
@zig-system-calls helpCommands
| Command | Description | Required Args |
|---|---|---|
| @zig-system-calls cross-platform-file-operations | Implement robust file reading/writing that works consistently across Windows and Unix-like systems | None |
| @zig-system-calls advanced-error-handling | Handle system call errors with detailed context including errno, syscall information, and automatic EINTR retry | None |
| @zig-system-calls directory-operations-and-iteration | Perform directory traversal and manipulation with proper cross-platform abstractions | None |
Typical Use Cases
Cross-platform File Operations
Implement robust file reading/writing that works consistently across Windows and Unix-like systems
Advanced Error Handling
Handle system call errors with detailed context including errno, syscall information, and automatic EINTR retry
Directory Operations and Iteration
Perform directory traversal and manipulation with proper cross-platform abstractions
Overview
System Calls & File I/O in Zig
Use bun.sys instead of std.fs or std.posix for cross-platform syscalls with proper error handling.
bun.sys.File (Preferred)
For most file operations, use the bun.sys.File wrapper:
1const File = bun.sys.File;
2
3const file = switch (File.open(path, bun.O.RDWR, 0o644)) {
4 .result => |f| f,
5 .err => |err| return .{ .err = err },
6};
7defer file.close();
8
9// Read/write
10_ = try file.read(buffer).unwrap();
11_ = try file.writeAll(data).unwrap();
12
13// Get file info
14const stat = try file.stat().unwrap();
15const size = try file.getEndPos().unwrap();
16
17// std.io compatible
18const reader = file.reader();
19const writer = file.writer();
Complete Example
1const File = bun.sys.File;
2
3pub fn writeFile(path: [:0]const u8, data: []const u8) File.WriteError!void {
4 const file = switch (File.open(path, bun.O.WRONLY | bun.O.CREAT | bun.O.TRUNC, 0o664)) {
5 .result => |f| f,
6 .err => |err| return err.toError(),
7 };
8 defer file.close();
9
10 _ = switch (file.writeAll(data)) {
11 .result => {},
12 .err => |err| return err.toError(),
13 };
14}
Why bun.sys?
| Aspect | bun.sys | std.fs/std.posix |
|---|---|---|
| Return Type | Maybe(T) with detailed Error | Generic error union |
| Windows | Full support with libuv fallback | Limited/POSIX-only |
| Error Info | errno, syscall tag, path, fd | errno only |
| EINTR | Automatic retry | Manual handling |
Error Handling with Maybe(T)
bun.sys functions return Maybe(T) - a tagged union:
1const sys = bun.sys;
2
3// Pattern 1: Switch on result/error
4switch (sys.read(fd, buffer)) {
5 .result => |bytes_read| {
6 // use bytes_read
7 },
8 .err => |err| {
9 // err.errno, err.syscall, err.fd, err.path
10 if (err.getErrno() == .AGAIN) {
11 // handle EAGAIN
12 }
13 },
14}
15
16// Pattern 2: Unwrap with try (converts to Zig error)
17const bytes = try sys.read(fd, buffer).unwrap();
18
19// Pattern 3: Unwrap with default
20const value = sys.stat(path).unwrapOr(default_stat);
Low-Level File Operations
Only use these when bun.sys.File doesn’t meet your needs.
Opening Files
1const sys = bun.sys;
2
3// Use bun.O flags (cross-platform normalized)
4const fd = switch (sys.open(path, bun.O.RDONLY, 0)) {
5 .result => |fd| fd,
6 .err => |err| return .{ .err = err },
7};
8defer fd.close();
9
10// Common flags
11bun.O.RDONLY, bun.O.WRONLY, bun.O.RDWR
12bun.O.CREAT, bun.O.TRUNC, bun.O.APPEND
13bun.O.NONBLOCK, bun.O.DIRECTORY
Reading & Writing
1// Single read (may return less than buffer size)
2switch (sys.read(fd, buffer)) {
3 .result => |n| { /* n bytes read */ },
4 .err => |err| { /* handle error */ },
5}
6
7// Read until EOF or buffer full
8const total = try sys.readAll(fd, buffer).unwrap();
9
10// Position-based read/write
11sys.pread(fd, buffer, offset)
12sys.pwrite(fd, data, offset)
13
14// Vector I/O
15sys.readv(fd, iovecs)
16sys.writev(fd, iovecs)
File Info
1sys.stat(path) // Follow symlinks
2sys.lstat(path) // Don't follow symlinks
3sys.fstat(fd) // From file descriptor
4sys.fstatat(fd, path)
5
6// Linux-only: faster selective stat
7sys.statx(path, &.{ .size, .mtime })
Path Operations
1sys.unlink(path)
2sys.unlinkat(dir_fd, path)
3sys.rename(from, to)
4sys.renameat(from_dir, from, to_dir, to)
5sys.readlink(path, buf)
6sys.readlinkat(fd, path, buf)
7sys.link(T, src, dest)
8sys.linkat(src_fd, src, dest_fd, dest)
9sys.symlink(target, dest)
10sys.symlinkat(target, dirfd, dest)
11sys.mkdir(path, mode)
12sys.mkdirat(dir_fd, path, mode)
13sys.rmdir(path)
Permissions
1sys.chmod(path, mode)
2sys.fchmod(fd, mode)
3sys.fchmodat(fd, path, mode, flags)
4sys.chown(path, uid, gid)
5sys.fchown(fd, uid, gid)
Closing File Descriptors
Close is on bun.FD:
1fd.close(); // Asserts on error (use in defer)
2
3// Or if you need error info:
4if (fd.closeAllowingBadFileDescriptor(null)) |err| {
5 // handle error
6}
Directory Operations
1var buf: bun.PathBuffer = undefined;
2const cwd = try sys.getcwd(&buf).unwrap();
3const cwdZ = try sys.getcwdZ(&buf).unwrap(); // Zero-terminated
4sys.chdir(path, destination)
Directory Iteration
Use bun.DirIterator instead of std.fs.Dir.Iterator:
1var iter = bun.iterateDir(dir_fd);
2while (true) {
3 switch (iter.next()) {
4 .result => |entry| {
5 if (entry) |e| {
6 const name = e.name.slice();
7 const kind = e.kind; // .file, .directory, .sym_link, etc.
8 } else {
9 break; // End of directory
10 }
11 },
12 .err => |err| return .{ .err = err },
13 }
14}
Socket Operations
Important: bun.sys has limited socket support. For network I/O:
- Non-blocking sockets: Use
uws.Socket(libuwebsockets) exclusively - Pipes/blocking I/O: Use
PipeReader.zigandPipeWriter.zig
Available in bun.sys:
1sys.setsockopt(fd, level, optname, value)
2sys.socketpair(domain, socktype, protocol, nonblocking_status)
Do NOT use bun.sys for socket read/write - use uws.Socket instead.
Other Operations
1sys.ftruncate(fd, size)
2sys.lseek(fd, offset, whence)
3sys.dup(fd)
4sys.dupWithFlags(fd, flags)
5sys.fcntl(fd, cmd, arg)
6sys.pipe()
7sys.mmap(...)
8sys.munmap(memory)
9sys.access(path, mode)
10sys.futimens(fd, atime, mtime)
11sys.utimens(path, atime, mtime)
Error Type
1const err: bun.sys.Error = ...;
2err.errno // Raw errno value
3err.getErrno() // As std.posix.E enum
4err.syscall // Which syscall failed (Tag enum)
5err.fd // Optional: file descriptor
6err.path // Optional: path string
Key Points
- Prefer
bun.sys.Filewrapper for most file operations - Use low-level
bun.sysfunctions only when needed - Use
bun.O.*flags instead ofstd.os.O.* - Handle
Maybe(T)with switch or.unwrap() - Use
defer fd.close()for cleanup - EINTR is handled automatically in most functions
- For sockets, use
uws.Socketnotbun.sys
What Users Are Saying
Real feedback from the community
Environment Matrix
Dependencies
Framework Support
Context Window
Security & Privacy
Information
- Author
- oven-sh
- Updated
- 2026-01-30
- Category
- scripting
Related Skills
Zig System Calls
Guides using bun.sys for system calls and file I/O in Zig. Use when implementing file operations …
View Details →Api Integration Specialist
Expert in integrating third-party APIs with proper authentication, error handling, rate limiting, …
View Details →Api Integration Specialist
Expert in integrating third-party APIs with proper authentication, error handling, rate limiting, …
View Details →