mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std.Io.Threaded: implement dirOpenDir
This commit is contained in:
parent
dc6a4f3bf1
commit
62c0496d0a
2 changed files with 103 additions and 110 deletions
|
|
@ -208,6 +208,7 @@ pub fn io(t: *Threaded) Io {
|
||||||
.dirOpenDir = switch (builtin.os.tag) {
|
.dirOpenDir = switch (builtin.os.tag) {
|
||||||
.windows => dirOpenDirWindows,
|
.windows => dirOpenDirWindows,
|
||||||
.wasi => dirOpenDirWasi,
|
.wasi => dirOpenDirWasi,
|
||||||
|
.haiku => dirOpenDirHaiku,
|
||||||
else => dirOpenDirPosix,
|
else => dirOpenDirPosix,
|
||||||
},
|
},
|
||||||
.dirClose = dirClose,
|
.dirClose = dirClose,
|
||||||
|
|
@ -1784,22 +1785,20 @@ fn dirOpenFilePosix(
|
||||||
if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty;
|
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
|
// Use the O locking flags if the os supports them to acquire the lock
|
||||||
// atomically.
|
// atomically. Note that the NONBLOCK flag is removed after the openat()
|
||||||
if (have_flock_open_flags) {
|
// call is successful.
|
||||||
// Note that the NONBLOCK flag is removed after the openat() call
|
if (have_flock_open_flags) switch (flags.lock) {
|
||||||
// is successful.
|
.none => {},
|
||||||
switch (flags.lock) {
|
.shared => {
|
||||||
.none => {},
|
os_flags.SHLOCK = true;
|
||||||
.shared => {
|
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||||
os_flags.SHLOCK = true;
|
},
|
||||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
.exclusive => {
|
||||||
},
|
os_flags.EXLOCK = true;
|
||||||
.exclusive => {
|
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||||
os_flags.EXLOCK = true;
|
},
|
||||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
};
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const fd: posix.fd_t = while (true) {
|
const fd: posix.fd_t = while (true) {
|
||||||
try t.checkCancel();
|
try t.checkCancel();
|
||||||
const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0));
|
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 {
|
) Io.Dir.OpenError!Io.Dir {
|
||||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||||
|
|
||||||
_ = t;
|
var path_buffer: [posix.PATH_MAX]u8 = undefined;
|
||||||
_ = dir;
|
const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
|
||||||
_ = sub_path;
|
|
||||||
|
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;
|
_ = 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(
|
fn dirOpenDirWindows(
|
||||||
|
|
|
||||||
|
|
@ -1069,96 +1069,9 @@ pub const OpenOptions = Io.Dir.OpenOptions;
|
||||||
|
|
||||||
/// Deprecated in favor of `Io.Dir.openDir`.
|
/// Deprecated in favor of `Io.Dir.openDir`.
|
||||||
pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {
|
pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {
|
||||||
switch (native_os) {
|
var threaded: Io.Threaded = .init_single_threaded;
|
||||||
.windows => {
|
const io = threaded.io();
|
||||||
var threaded: Io.Threaded = .init_single_threaded;
|
return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
|
||||||
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 };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeleteFileError = posix.UnlinkError;
|
pub const DeleteFileError = posix.UnlinkError;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue