feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.dirCreateDirPathOpenWindows
fn dirCreateDirPathOpenWindows(
userdata: ?*anyopaque,
dir: Dir,
sub_path: []const u8,
permissions: Dir.Permissions,
options: Dir.OpenOptions,
) Dir.CreateDirPathOpenError!Dir
File
Code
fn dirCreateDirPathOpenWindows(
userdata: ?*anyopaque,
dir: Dir,
sub_path: []const u8,
permissions: Dir.Permissions,
options: Dir.OpenOptions,
) Dir.CreateDirPathOpenError!Dir {
const t: *Threaded = @ptrCast(@alignCast(userdata));
const w = windows;
_ = permissions;
var it = Dir.path.componentIterator(sub_path);
var component: Dir.path.NativeComponentIterator.Component = it.last() orelse .{
.name = "",
.path = sub_path,
};
components: while (true) {
const sub_path_w = try sliceToPrefixedFileW(dir.handle, component.path, .{});
const attr: windows.OBJECT.ATTRIBUTES = .{
.RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(sub_path_w.span())) null else dir.handle,
.ObjectName = @constCast(&sub_path_w.string()),
};
const is_last = it.peekNext() == null;
var result: Dir = .{ .handle = undefined };
var iosb: w.IO_STATUS_BLOCK = undefined;
const syscall: Syscall = try .start();
while (true) switch (w.ntdll.NtCreateFile(
&result.handle,
.{
.SPECIFIC = .{ .FILE_DIRECTORY = .{
.LIST = options.iterate,
.READ_EA = true,
.READ_ATTRIBUTES = true,
.TRAVERSE = true,
} },
.STANDARD = .{
.RIGHTS = .READ,
.SYNCHRONIZE = true,
},
},
&attr,
&iosb,
null,
.{ .NORMAL = true },
.VALID_FLAGS,
if (is_last) .OPEN_IF else .CREATE,
.{
.DIRECTORY_FILE = true,
.IO = .SYNCHRONOUS_NONALERT,
.OPEN_FOR_BACKUP_INTENT = true,
.OPEN_REPARSE_POINT = !options.follow_symlinks,
},
null,
0,
)) {
.SUCCESS => {
syscall.finish();
component = it.next() orelse return result;
w.CloseHandle(result.handle);
continue :components;
},
.CANCELLED => {
try syscall.checkCancel();
continue;
},
.OBJECT_NAME_INVALID => return syscall.fail(error.BadPathName),
.OBJECT_NAME_COLLISION => {
syscall.finish();
assert(!is_last);
// this is important because otherwise a dangling symlink
// could cause an infinite loop
const fstat = try dirStatFileWindows(t, dir, component.path, .{
.follow_symlinks = options.follow_symlinks,
});
if (fstat.kind != .directory) return error.NotDir;
component = it.next().?;
continue :components;
},
.OBJECT_NAME_NOT_FOUND,
.OBJECT_PATH_NOT_FOUND,
=> {
syscall.finish();
component = it.previous() orelse return error.FileNotFound;
continue :components;
},
.NOT_A_DIRECTORY => return syscall.fail(error.NotDir),
// and the directory is trying to be opened for iteration.
.ACCESS_DENIED => return syscall.fail(error.AccessDenied),
.DISK_FULL => return syscall.fail(error.NoSpaceLeft),
.INVALID_PARAMETER => |s| return syscall.ntstatusBug(s),
else => |s| return syscall.unexpectedNtstatus(s),
};
}
}