zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 2d3694ab42b73ba09124d5f1ddbfd9adaea79c47 (tree)
parent 1f79a9e4e300affd111b51ec172bbeff42ca755a
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 27 Mar 2026 12:24:09 +0100

Merge pull request 'std.Io.Dir: add resolve_beneath flag and implement for freebsd,macos' (#31684) from resolve_beneath into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31684

Diffstat:
Mlib/std/Io.zig | 6+++---
Mlib/std/Io/Dir.zig | 129++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mlib/std/Io/File.zig | 124++++---------------------------------------------------------------------------
Mlib/std/Io/Threaded.zig | 94++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mlib/std/c.zig | 3++-
5 files changed, 181 insertions(+), 175 deletions(-)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig @@ -160,9 +160,9 @@ pub const VTable = struct { dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, dirStatFile: *const fn (?*anyopaque, Dir, []const u8, Dir.StatFileOptions) Dir.StatFileError!File.Stat, dirAccess: *const fn (?*anyopaque, Dir, []const u8, Dir.AccessOptions) Dir.AccessError!void, - dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, File.CreateFlags) File.OpenError!File, + dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, Dir.CreateFileOptions) File.OpenError!File, dirCreateFileAtomic: *const fn (?*anyopaque, Dir, []const u8, Dir.CreateFileAtomicOptions) Dir.CreateFileAtomicError!File.Atomic, - dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, File.OpenFlags) File.OpenError!File, + dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenFileOptions) File.OpenError!File, dirClose: *const fn (?*anyopaque, []const Dir) void, dirRead: *const fn (?*anyopaque, *Dir.Reader, []Dir.Entry) Dir.Reader.Error!usize, dirRealPath: *const fn (?*anyopaque, Dir, out_buffer: []u8) Dir.RealPathError!usize, @@ -211,7 +211,7 @@ pub const VTable = struct { fileMemoryMapRead: *const fn (?*anyopaque, *File.MemoryMap) File.ReadPositionalError!void, fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap) File.WritePositionalError!void, - processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File, + processExecutableOpen: *const fn (?*anyopaque, Dir.OpenFileOptions) std.process.OpenExecutableError!File, processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize, lockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!LockedStderr, tryLockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!?LockedStderr, diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig @@ -495,6 +495,76 @@ pub fn closeMany(io: Io, dirs: []const Dir) void { return io.vtable.dirClose(io.userdata, dirs); } +pub const OpenFileOptions = struct { + mode: Mode = .read_only, + /// Determines the behavior when opening a path that refers to a directory. + /// + /// If set to true, directories may be opened, but `error.IsDir` is still + /// possible in certain scenarios, e.g. attempting to open a directory with + /// write permissions. + /// + /// If set to false, `error.IsDir` will always be returned when opening a directory. + /// + /// When set to false: + /// * On Windows, the behavior is implemented without any extra syscalls. + /// * On other operating systems, the behavior is implemented with an additional + /// `fstat` syscall. + allow_directory: bool = true, + /// Indicates intent for only some operations to be performed on this + /// opened file: + /// * `close` + /// * `stat` + /// On Linux and FreeBSD, this corresponds to `std.posix.O.PATH`. + path_only: bool = false, + /// Open the file with an advisory lock to coordinate with other processes + /// accessing it at the same time. An exclusive lock will prevent other + /// processes from acquiring a lock. A shared lock will prevent other + /// processes from acquiring a exclusive lock, but does not prevent + /// other process from getting their own shared locks. + /// + /// The lock is advisory, except on Linux in very specific circumstances[1]. + /// This means that a process that does not respect the locking API can still get access + /// to the file, despite the lock. + /// + /// On these operating systems, the lock is acquired atomically with + /// opening the file: + /// * Darwin + /// * DragonFlyBSD + /// * FreeBSD + /// * Haiku + /// * NetBSD + /// * OpenBSD + /// On these operating systems, the lock is acquired via a separate syscall + /// after opening the file: + /// * Linux + /// * Windows + /// + /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt + lock: File.Lock = .none, + /// Sets whether or not to wait until the file is locked to return. If set to true, + /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file + /// is available to proceed. + lock_nonblocking: bool = false, + /// Set this to allow the opened file to automatically become the + /// controlling TTY for the current process. + allow_ctty: bool = false, + follow_symlinks: bool = true, + /// If supported by the operating system, attempted path resolution that + /// would escape the directory instead returns `error.AccessDenied`. If + /// unsupported, this option is ignored. + resolve_beneath: bool = false, + + pub const Mode = enum { read_only, write_only, read_write }; + + pub fn isRead(self: OpenFileOptions) bool { + return self.mode != .write_only; + } + + pub fn isWrite(self: OpenFileOptions) bool { + return self.mode != .read_only; + } +}; + /// Opens a file for reading or writing, without attempting to create a new file. /// /// To create a new file, see `createFile`. @@ -504,15 +574,60 @@ pub fn closeMany(io: Io, dirs: []const Dir) void { /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). /// On WASI, `sub_path` should be encoded as valid UTF-8. /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { - return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags); +pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, options: OpenFileOptions) File.OpenError!File { + return io.vtable.dirOpenFile(io.userdata, dir, sub_path, options); } -pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File { +pub fn openFileAbsolute(io: Io, absolute_path: []const u8, options: OpenFileOptions) File.OpenError!File { assert(path.isAbsolute(absolute_path)); - return openFile(.cwd(), io, absolute_path, flags); + return openFile(.cwd(), io, absolute_path, options); } +pub const CreateFileOptions = struct { + /// Whether the file will be created with read access. + read: bool = false, + /// If the file already exists, and is a regular file, and the access + /// mode allows writing, it will be truncated to length 0. + truncate: bool = true, + /// Ensures that this open call creates the file, otherwise causes + /// `error.PathAlreadyExists` to be returned. + exclusive: bool = false, + /// Open the file with an advisory lock to coordinate with other processes + /// accessing it at the same time. An exclusive lock will prevent other + /// processes from acquiring a lock. A shared lock will prevent other + /// processes from acquiring a exclusive lock, but does not prevent + /// other process from getting their own shared locks. + /// + /// The lock is advisory, except on Linux in very specific circumstances[1]. + /// This means that a process that does not respect the locking API can still get access + /// to the file, despite the lock. + /// + /// On these operating systems, the lock is acquired atomically with + /// opening the file: + /// * Darwin + /// * DragonFlyBSD + /// * FreeBSD + /// * Haiku + /// * NetBSD + /// * OpenBSD + /// On these operating systems, the lock is acquired via a separate syscall + /// after opening the file: + /// * Linux + /// * Windows + /// + /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt + lock: File.Lock = .none, + /// Sets whether or not to wait until the file is locked to return. If set to true, + /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file + /// is available to proceed. + lock_nonblocking: bool = false, + permissions: Permissions = .default_file, + /// If supported by the operating system, attempted path resolution that + /// would escape the directory instead returns `error.AccessDenied`. If + /// unsupported, this option is ignored. + resolve_beneath: bool = false, +}; + /// Creates, opens, or overwrites a file with write access. /// /// Allocates a resource to be dellocated with `File.close`. @@ -520,11 +635,11 @@ pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). /// On WASI, `sub_path` should be encoded as valid UTF-8. /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { +pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: CreateFileOptions) File.OpenError!File { return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags); } -pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File { +pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: CreateFileOptions) File.OpenError!File { return createFile(.cwd(), io, absolute_path, flags); } @@ -534,7 +649,7 @@ pub const WriteFileOptions = struct { /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. sub_path: []const u8, data: []const u8, - flags: File.CreateFlags = .{}, + flags: CreateFileOptions = .{}, }; pub const WriteFileError = File.Writer.Error || File.OpenError; diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig @@ -142,11 +142,8 @@ pub fn stat(file: File, io: Io) StatError!Stat { return io.vtable.fileStat(io.userdata, file); } -pub const OpenMode = enum { - read_only, - write_only, - read_write, -}; +/// Deprecated, renamed to `Dir.OpenFileOptions.Mode`. +pub const OpenMode = Dir.OpenFileOptions.Mode; pub const Lock = enum { none, @@ -154,120 +151,11 @@ pub const Lock = enum { exclusive, }; -pub const OpenFlags = struct { - mode: OpenMode = .read_only, - - /// Determines the behavior when opening a path that refers to a directory. - /// - /// If set to true, directories may be opened, but `error.IsDir` is still - /// possible in certain scenarios, e.g. attempting to open a directory with - /// write permissions. - /// - /// If set to false, `error.IsDir` will always be returned when opening a directory. - /// - /// When set to false: - /// * On Windows, the behavior is implemented without any extra syscalls. - /// * On other operating systems, the behavior is implemented with an additional - /// `fstat` syscall. - allow_directory: bool = true, - /// Indicates intent for only some operations to be performed on this - /// opened file: - /// * `close` - /// * `stat` - /// On Linux and FreeBSD, this corresponds to `std.posix.O.PATH`. - path_only: bool = false, - - /// Open the file with an advisory lock to coordinate with other processes - /// accessing it at the same time. An exclusive lock will prevent other - /// processes from acquiring a lock. A shared lock will prevent other - /// processes from acquiring a exclusive lock, but does not prevent - /// other process from getting their own shared locks. - /// - /// The lock is advisory, except on Linux in very specific circumstances[1]. - /// This means that a process that does not respect the locking API can still get access - /// to the file, despite the lock. - /// - /// On these operating systems, the lock is acquired atomically with - /// opening the file: - /// * Darwin - /// * DragonFlyBSD - /// * FreeBSD - /// * Haiku - /// * NetBSD - /// * OpenBSD - /// On these operating systems, the lock is acquired via a separate syscall - /// after opening the file: - /// * Linux - /// * Windows - /// - /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt - lock: Lock = .none, - - /// Sets whether or not to wait until the file is locked to return. If set to true, - /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file - /// is available to proceed. - lock_nonblocking: bool = false, - - /// Set this to allow the opened file to automatically become the - /// controlling TTY for the current process. - allow_ctty: bool = false, - - follow_symlinks: bool = true, - - pub fn isRead(self: OpenFlags) bool { - return self.mode != .write_only; - } +/// Deprecated, renamed to `Dir.OpenFileOptions` +pub const OpenFlags = Dir.OpenFileOptions; - pub fn isWrite(self: OpenFlags) bool { - return self.mode != .read_only; - } -}; - -pub const CreateFlags = struct { - /// Whether the file will be created with read access. - read: bool = false, - - /// If the file already exists, and is a regular file, and the access - /// mode allows writing, it will be truncated to length 0. - truncate: bool = true, - - /// Ensures that this open call creates the file, otherwise causes - /// `error.PathAlreadyExists` to be returned. - exclusive: bool = false, - - /// Open the file with an advisory lock to coordinate with other processes - /// accessing it at the same time. An exclusive lock will prevent other - /// processes from acquiring a lock. A shared lock will prevent other - /// processes from acquiring a exclusive lock, but does not prevent - /// other process from getting their own shared locks. - /// - /// The lock is advisory, except on Linux in very specific circumstances[1]. - /// This means that a process that does not respect the locking API can still get access - /// to the file, despite the lock. - /// - /// On these operating systems, the lock is acquired atomically with - /// opening the file: - /// * Darwin - /// * DragonFlyBSD - /// * FreeBSD - /// * Haiku - /// * NetBSD - /// * OpenBSD - /// On these operating systems, the lock is acquired via a separate syscall - /// after opening the file: - /// * Linux - /// * Windows - /// - /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt - lock: Lock = .none, - - /// Sets whether or not to wait until the file is locked to return. If set to true, - /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file - /// is available to proceed. - lock_nonblocking: bool = false, - - permissions: Permissions = .default_file, -}; +/// Deprecated, renamed to `Dir.CreateFileOptions`. +pub const CreateFlags = Dir.CreateFileOptions; pub const OpenError = error{ PipeBusy, diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig @@ -4217,7 +4217,7 @@ fn dirCreateFilePosix( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.CreateFlags, + options: Dir.CreateFileOptions, ) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; @@ -4225,34 +4225,35 @@ fn dirCreateFilePosix( var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var os_flags: posix.O = .{ - .ACCMODE = if (flags.read) .RDWR else .WRONLY, + var flags: posix.O = .{ + .ACCMODE = if (options.read) .RDWR else .WRONLY, .CREAT = true, - .TRUNC = flags.truncate, - .EXCL = flags.exclusive, + .TRUNC = options.truncate, + .EXCL = options.exclusive, }; - if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; - if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; + if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true; + if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; + if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath; // Use the O locking flags if the os supports them to acquire the lock // atomically. Note that the NONBLOCK flag is removed after the openat() // call is successful. - if (have_flock_open_flags) switch (flags.lock) { + if (have_flock_open_flags) switch (options.lock) { .none => {}, .shared => { - os_flags.SHLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; + flags.SHLOCK = true; + flags.NONBLOCK = options.lock_nonblocking; }, .exclusive => { - os_flags.EXLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; + flags.EXLOCK = true; + flags.NONBLOCK = options.lock_nonblocking; }, }; const fd: posix.fd_t = fd: { const syscall: Syscall = try .start(); while (true) { - const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.permissions.toMode()); + const rc = openat_sym(dir.handle, sub_path_posix, flags, options.permissions.toMode()); switch (posix.errno(rc)) { .SUCCESS => { syscall.finish(); @@ -4298,9 +4299,9 @@ fn dirCreateFilePosix( }; errdefer closeFd(fd); - if (have_flock and !have_flock_open_flags and flags.lock != .none) { - const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; - const lock_flags = switch (flags.lock) { + if (have_flock and !have_flock_open_flags and options.lock != .none) { + const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0; + const lock_flags = switch (options.lock) { .none => unreachable, .shared => posix.LOCK.SH | lock_nonblocking, .exclusive => posix.LOCK.EX | lock_nonblocking, @@ -4332,7 +4333,7 @@ fn dirCreateFilePosix( } } - if (have_flock_open_flags and flags.lock_nonblocking) { + if (have_flock_open_flags and options.lock_nonblocking) { var fl_flags: usize = fl: { const syscall: Syscall = try .start(); while (true) { @@ -4385,7 +4386,7 @@ fn dirCreateFileWindows( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.CreateFlags, + flags: Dir.CreateFileOptions, ) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; @@ -4535,7 +4536,7 @@ fn dirCreateFileWasi( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.CreateFlags, + flags: Dir.CreateFileOptions, ) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; @@ -4785,45 +4786,46 @@ fn dirOpenFilePosix( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.OpenFlags, + options: Dir.OpenFileOptions, ) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); var path_buffer: [posix.PATH_MAX]u8 = undefined; const sub_path_posix = try pathToPosix(sub_path, &path_buffer); - var os_flags: posix.O = switch (native_os) { + var flags: posix.O = switch (native_os) { .wasi => .{ - .read = flags.mode != .write_only, - .write = flags.mode != .read_only, - .NOFOLLOW = !flags.follow_symlinks, + .read = options.mode != .write_only, + .write = options.mode != .read_only, + .NOFOLLOW = !options.follow_symlinks, }, else => .{ - .ACCMODE = switch (flags.mode) { + .ACCMODE = switch (options.mode) { .read_only => .RDONLY, .write_only => .WRONLY, .read_write => .RDWR, }, - .NOFOLLOW = !flags.follow_symlinks, + .NOFOLLOW = !options.follow_symlinks, }, }; - if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; - if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; - if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; - if (@hasField(posix.O, "PATH") and flags.path_only) os_flags.PATH = true; + if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; + if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true; + if (@hasField(posix.O, "NOCTTY")) flags.NOCTTY = !options.allow_ctty; + if (@hasField(posix.O, "PATH")) flags.PATH = options.path_only; + if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath; - // Use the O locking flags if the os supports them to acquire the lock + // Use the O locking options if the os supports them to acquire the lock // atomically. Note that the NONBLOCK flag is removed after the openat() // call is successful. - if (have_flock_open_flags) switch (flags.lock) { + if (have_flock_open_flags) switch (options.lock) { .none => {}, .shared => { - os_flags.SHLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; + flags.SHLOCK = true; + flags.NONBLOCK = options.lock_nonblocking; }, .exclusive => { - os_flags.EXLOCK = true; - os_flags.NONBLOCK = flags.lock_nonblocking; + flags.EXLOCK = true; + flags.NONBLOCK = options.lock_nonblocking; }, }; @@ -4832,7 +4834,7 @@ fn dirOpenFilePosix( const fd: posix.fd_t = fd: { const syscall: Syscall = try .start(); while (true) { - const rc = openat_sym(dir.handle, sub_path_posix, os_flags, mode); + const rc = openat_sym(dir.handle, sub_path_posix, flags, mode); switch (posix.errno(rc)) { .SUCCESS => { syscall.finish(); @@ -4878,7 +4880,7 @@ fn dirOpenFilePosix( }; errdefer closeFd(fd); - if (!flags.allow_directory) { + if (!options.allow_directory) { const is_dir = is_dir: { const stat = fileStat(t, .{ .handle = fd, @@ -4893,9 +4895,9 @@ fn dirOpenFilePosix( if (is_dir) return error.IsDir; } - if (have_flock and !have_flock_open_flags and flags.lock != .none) { - const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; - const lock_flags = switch (flags.lock) { + if (have_flock and !have_flock_open_flags and options.lock != .none) { + const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0; + const lock_flags = switch (options.lock) { .none => unreachable, .shared => posix.LOCK.SH | lock_nonblocking, .exclusive => posix.LOCK.EX | lock_nonblocking, @@ -4926,7 +4928,7 @@ fn dirOpenFilePosix( } } - if (have_flock_open_flags and flags.lock_nonblocking) { + if (have_flock_open_flags and options.lock_nonblocking) { var fl_flags: usize = fl: { const syscall: Syscall = try .start(); while (true) { @@ -4979,7 +4981,7 @@ fn dirOpenFileWindows( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.OpenFlags, + flags: Dir.OpenFileOptions, ) File.OpenError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; @@ -4992,7 +4994,7 @@ fn dirOpenFileWindows( pub fn dirOpenFileWtf16( dir_handle: ?windows.HANDLE, sub_path_w: []const u16, - flags: File.OpenFlags, + flags: Dir.OpenFileOptions, ) File.OpenError!File { const allow_directory = flags.allow_directory and !flags.isWrite(); if (!allow_directory and std.mem.eql(u16, sub_path_w, &.{'.'})) return error.IsDir; @@ -5129,7 +5131,7 @@ fn dirOpenFileWasi( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - flags: File.OpenFlags, + flags: Dir.OpenFileOptions, ) File.OpenError!File { if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags); const t: *Threaded = @ptrCast(@alignCast(userdata)); @@ -10193,7 +10195,7 @@ fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void { } } -fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) process.OpenExecutableError!File { +fn processExecutableOpen(userdata: ?*anyopaque, flags: Dir.OpenFileOptions) process.OpenExecutableError!File { const t: *Threaded = @ptrCast(@alignCast(userdata)); switch (native_os) { .wasi => return error.OperationUnsupported, diff --git a/lib/std/c.zig b/lib/std/c.zig @@ -8535,7 +8535,8 @@ pub const O = switch (native_os) { CREAT: bool = false, TRUNC: bool = false, EXCL: bool = false, - _12: u3 = 0, + RESOLVE_BENEATH: bool = false, + _13: u2 = 0, EVTONLY: bool = false, _16: u1 = 0, NOCTTY: bool = false,