diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-06-27 20:05:22 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-07-07 22:43:51 -0700 |
| commit | 0e37ff0d591dd75ceec9208196bec29efaec607a (patch) | |
| tree | c126fa823a1f3864e9c363aac70e3a3db0219957 /lib/std/os/linux.zig | |
| parent | 0b3f0124dc33403d329fb8ee63a93215d9af1f1e (diff) | |
| download | zig-0e37ff0d591dd75ceec9208196bec29efaec607a.tar.gz zig-0e37ff0d591dd75ceec9208196bec29efaec607a.zip | |
std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API
make std.testing.expectFmt work at compile-time
std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.
Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
- anytype -> *std.io.Writer
- inferred error set -> error{WriteFailed}
- options -> (deleted)
* std.fmt.Formatted
- now takes context type explicitly
- no fmt string
Diffstat (limited to 'lib/std/os/linux.zig')
| -rw-r--r-- | lib/std/os/linux.zig | 130 |
1 files changed, 129 insertions, 1 deletions
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 3b2f51464e..75494145b9 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -9420,4 +9420,132 @@ pub const msghdr_const = extern struct { control: ?*const anyopaque, controllen: usize, flags: u32, -};
\ No newline at end of file +}; + +/// The syscalls, but with Zig error sets, going through libc if linking libc, +/// and with some footguns eliminated. +pub const wrapped = struct { + pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); + const system = if (builtin.link_libc) std.c else std.os.linux; + + pub const SendfileError = std.posix.UnexpectedError || error{ + /// `out_fd` is an unconnected socket, or out_fd closed its read end. + BrokenPipe, + /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd. + UnsupportedOperation, + /// Nonblocking I/O has been selected but the write would block. + WouldBlock, + /// Unspecified error while reading from in_fd. + InputOutput, + /// Insufficient kernel memory to read from in_fd. + SystemResources, + /// `offset` is not `null` but the input file is not seekable. + Unseekable, + }; + + pub fn sendfile( + out_fd: fd_t, + in_fd: fd_t, + in_offset: ?*off_t, + in_len: usize, + ) SendfileError!usize { + const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW. + const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile; + const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len); + switch (errno(rc)) { + .SUCCESS => return @intCast(rc), + .BADF => return invalidApiUsage(), // Always a race condition. + .FAULT => return invalidApiUsage(), // Segmentation fault. + .OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`. + .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket + .INVAL => return error.UnsupportedOperation, + .AGAIN => return error.WouldBlock, + .IO => return error.InputOutput, + .PIPE => return error.BrokenPipe, + .NOMEM => return error.SystemResources, + .NXIO => return error.Unseekable, + .SPIPE => return error.Unseekable, + else => |err| return unexpectedErrno(err), + } + } + + pub const CopyFileRangeError = std.posix.UnexpectedError || error{ + /// One of: + /// * One or more file descriptors are not valid. + /// * fd_in is not open for reading; or fd_out is not open for writing. + /// * The O_APPEND flag is set for the open file description referred + /// to by the file descriptor fd_out. + BadFileFlags, + /// One of: + /// * An attempt was made to write at a position past the maximum file + /// offset the kernel supports. + /// * An attempt was made to write a range that exceeds the allowed + /// maximum file size. The maximum file size differs between + /// filesystem implementations and can be different from the maximum + /// allowed file offset. + /// * An attempt was made to write beyond the process's file size + /// resource limit. This may also result in the process receiving a + /// SIGXFSZ signal. + FileTooBig, + /// One of: + /// * either fd_in or fd_out is not a regular file + /// * flags argument is not zero + /// * fd_in and fd_out refer to the same file and the source and target ranges overlap. + InvalidArguments, + /// A low-level I/O error occurred while copying. + InputOutput, + /// Either fd_in or fd_out refers to a directory. + IsDir, + OutOfMemory, + /// There is not enough space on the target filesystem to complete the copy. + NoSpaceLeft, + /// (since Linux 5.19) the filesystem does not support this operation. + OperationNotSupported, + /// The requested source or destination range is too large to represent + /// in the specified data types. + Overflow, + /// fd_out refers to an immutable file. + PermissionDenied, + /// Either fd_in or fd_out refers to an active swap file. + SwapFile, + /// The files referred to by fd_in and fd_out are not on the same + /// filesystem, and the source and target filesystems are not of the + /// same type, or do not support cross-filesystem copy. + NotSameFileSystem, + }; + + pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize { + const rc = system.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); + switch (errno(rc)) { + .SUCCESS => return @intCast(rc), + .BADF => return error.BadFileFlags, + .FBIG => return error.FileTooBig, + .INVAL => return error.InvalidArguments, + .IO => return error.InputOutput, + .ISDIR => return error.IsDir, + .NOMEM => return error.OutOfMemory, + .NOSPC => return error.NoSpaceLeft, + .OPNOTSUPP => return error.OperationNotSupported, + .OVERFLOW => return error.Overflow, + .PERM => return error.PermissionDenied, + .TXTBSY => return error.SwapFile, + .XDEV => return error.NotSameFileSystem, + else => |err| return unexpectedErrno(err), + } + } + + const unexpectedErrno = std.posix.unexpectedErrno; + + fn invalidApiUsage() error{Unexpected} { + if (builtin.mode == .Debug) @panic("invalid API usage"); + return error.Unexpected; + } + + fn errno(rc: anytype) E { + if (builtin.link_libc) { + return if (rc == -1) @enumFromInt(std.c._errno().*) else .SUCCESS; + } else { + return errnoFromSyscall(rc); + } + } +}; |
