Commit 62c0496d0a
Changed files (2)
lib
std
fs
lib/std/fs/Dir.zig
@@ -1069,96 +1069,9 @@ pub const OpenOptions = Io.Dir.OpenOptions;
/// Deprecated in favor of `Io.Dir.openDir`.
pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {
- switch (native_os) {
- .windows => {
- var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
- return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
- },
- .wasi => if (!builtin.link_libc) {
- var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
- return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
- },
- else => {},
- }
- const sub_path_c = try posix.toPosixPath(sub_path);
- return self.openDirZ(&sub_path_c, args);
-}
-
-/// Same as `openDir` except the parameter is null-terminated.
-pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenOptions) OpenError!Dir {
- switch (native_os) {
- .windows => {
- @compileError("use std.Io instead");
- },
- // Use the libc API when libc is linked because it implements things
- // such as opening absolute directory paths.
- .wasi => if (!builtin.link_libc) {
- return openDir(self, mem.sliceTo(sub_path_c, 0), args);
- },
- .haiku => {
- const rc = posix.system._kern_open_dir(self.fd, sub_path_c);
- if (rc >= 0) return .{ .fd = rc };
- switch (@as(posix.E, @enumFromInt(rc))) {
- .FAULT => unreachable,
- .INVAL => unreachable,
- .BADF => unreachable,
- .ACCES => return error.AccessDenied,
- .LOOP => return error.SymLinkLoop,
- .MFILE => return error.ProcessFdQuotaExceeded,
- .NAMETOOLONG => return error.NameTooLong,
- .NFILE => return error.SystemFdQuotaExceeded,
- .NODEV => return error.NoDevice,
- .NOENT => return error.FileNotFound,
- .NOMEM => return error.SystemResources,
- .NOTDIR => return error.NotDir,
- .PERM => return error.PermissionDenied,
- .BUSY => return error.DeviceBusy,
- else => |err| return posix.unexpectedErrno(err),
- }
- },
- else => {},
- }
-
- var symlink_flags: posix.O = switch (native_os) {
- .wasi => .{
- .read = true,
- .NOFOLLOW = !args.follow_symlinks,
- .DIRECTORY = true,
- },
- else => .{
- .ACCMODE = .RDONLY,
- .NOFOLLOW = !args.follow_symlinks,
- .DIRECTORY = true,
- .CLOEXEC = true,
- },
- };
-
- if (@hasField(posix.O, "PATH") and !args.iterate)
- symlink_flags.PATH = true;
-
- return self.openDirFlagsZ(sub_path_c, symlink_flags);
-}
-
-/// Asserts `flags` has `DIRECTORY` set.
-fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: posix.O) OpenError!Dir {
- assert(flags.DIRECTORY);
- const fd = posix.openatZ(self.fd, sub_path_c, flags, 0) catch |err| switch (err) {
- error.FileTooBig => unreachable, // can't happen for directories
- error.IsDir => unreachable, // we're setting DIRECTORY
- error.NoSpaceLeft => unreachable, // not setting CREAT
- error.PathAlreadyExists => unreachable, // not setting CREAT
- error.FileLocksNotSupported => unreachable, // locking folders is not supported
- error.WouldBlock => unreachable, // can't happen for directories
- error.FileBusy => unreachable, // can't happen for directories
- error.SharingViolation => unreachable, // can't happen for directories
- error.PipeBusy => unreachable, // can't happen for directories
- error.AntivirusInterference => unreachable, // can't happen for directories
- error.ProcessNotFound => unreachable, // can't happen for directories
- else => |e| return e,
- };
- return Dir{ .fd = fd };
+ var threaded: Io.Threaded = .init_single_threaded;
+ const io = threaded.io();
+ return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
}
pub const DeleteFileError = posix.UnlinkError;
lib/std/Io/Threaded.zig
@@ -208,6 +208,7 @@ pub fn io(t: *Threaded) Io {
.dirOpenDir = switch (builtin.os.tag) {
.windows => dirOpenDirWindows,
.wasi => dirOpenDirWasi,
+ .haiku => dirOpenDirHaiku,
else => dirOpenDirPosix,
},
.dirClose = dirClose,
@@ -1784,22 +1785,20 @@ fn dirOpenFilePosix(
if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty;
// Use the O locking flags if the os supports them to acquire the lock
- // atomically.
- if (have_flock_open_flags) {
- // Note that the NONBLOCK flag is removed after the openat() call
- // is successful.
- switch (flags.lock) {
- .none => {},
- .shared => {
- os_flags.SHLOCK = true;
- os_flags.NONBLOCK = flags.lock_nonblocking;
- },
- .exclusive => {
- os_flags.EXLOCK = true;
- os_flags.NONBLOCK = flags.lock_nonblocking;
- },
- }
- }
+ // atomically. Note that the NONBLOCK flag is removed after the openat()
+ // call is successful.
+ if (have_flock_open_flags) switch (flags.lock) {
+ .none => {},
+ .shared => {
+ os_flags.SHLOCK = true;
+ os_flags.NONBLOCK = flags.lock_nonblocking;
+ },
+ .exclusive => {
+ os_flags.EXLOCK = true;
+ os_flags.NONBLOCK = flags.lock_nonblocking;
+ },
+ };
+
const fd: posix.fd_t = while (true) {
try t.checkCancel();
const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0));
@@ -2008,11 +2007,92 @@ fn dirOpenDirPosix(
) Io.Dir.OpenError!Io.Dir {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- _ = t;
- _ = dir;
- _ = sub_path;
+ var path_buffer: [posix.PATH_MAX]u8 = undefined;
+ const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
+
+ var flags: posix.O = switch (native_os) {
+ .wasi => .{
+ .read = true,
+ .NOFOLLOW = !options.follow_symlinks,
+ .DIRECTORY = true,
+ },
+ else => .{
+ .ACCMODE = .RDONLY,
+ .NOFOLLOW = !options.follow_symlinks,
+ .DIRECTORY = true,
+ .CLOEXEC = true,
+ },
+ };
+
+ if (@hasField(posix.O, "PATH") and !options.iterate)
+ flags.PATH = true;
+
+ while (true) {
+ try t.checkCancel();
+ const rc = openat_sym(dir.handle, sub_path_posix, flags, @as(usize, 0));
+ switch (posix.errno(rc)) {
+ .SUCCESS => return .{ .handle = @intCast(rc) },
+ .INTR => continue,
+ .CANCELED => return error.Canceled,
+
+ .FAULT => |err| return errnoBug(err),
+ .INVAL => return error.BadPathName,
+ .BADF => |err| return errnoBug(err), // File descriptor used after closed.
+ .ACCES => return error.AccessDenied,
+ .LOOP => return error.SymLinkLoop,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NODEV => return error.NoDevice,
+ .NOENT => return error.FileNotFound,
+ .NOMEM => return error.SystemResources,
+ .NOTDIR => return error.NotDir,
+ .PERM => return error.PermissionDenied,
+ .BUSY => return error.DeviceBusy,
+ .NXIO => return error.NoDevice,
+ .ILSEQ => return error.BadPathName,
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ }
+}
+
+fn dirOpenDirHaiku(
+ userdata: ?*anyopaque,
+ dir: Io.Dir,
+ sub_path: []const u8,
+ options: Io.Dir.OpenOptions,
+) Io.Dir.OpenError!Io.Dir {
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+
+ var path_buffer: [posix.PATH_MAX]u8 = undefined;
+ const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
+
_ = options;
- @panic("TODO");
+
+ while (true) {
+ try t.checkCancel();
+ const rc = posix.system._kern_open_dir(dir.handle, sub_path_posix);
+ if (rc >= 0) return .{ .handle = rc };
+ switch (@as(posix.E, @enumFromInt(rc))) {
+ .INTR => continue,
+ .CANCELED => return error.Canceled,
+ .FAULT => |err| return errnoBug(err),
+ .INVAL => |err| return errnoBug(err),
+ .BADF => |err| return errnoBug(err), // File descriptor used after closed.
+ .ACCES => return error.AccessDenied,
+ .LOOP => return error.SymLinkLoop,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NODEV => return error.NoDevice,
+ .NOENT => return error.FileNotFound,
+ .NOMEM => return error.SystemResources,
+ .NOTDIR => return error.NotDir,
+ .PERM => return error.PermissionDenied,
+ .BUSY => return error.DeviceBusy,
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ }
}
fn dirOpenDirWindows(