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:
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,