mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std.Io.Threaded: implement dirAccess for Windows
This commit is contained in:
parent
482343f2e2
commit
aa6e8eff40
6 changed files with 66 additions and 14 deletions
|
|
@ -182,7 +182,7 @@ pub fn io(t: *Threaded) Io {
|
|||
else => fileStatPosix,
|
||||
},
|
||||
.dirAccess = switch (builtin.os.tag) {
|
||||
.windows => @panic("TODO"),
|
||||
.windows => dirAccessWindows,
|
||||
.wasi => dirAccessWasi,
|
||||
else => dirAccessPosix,
|
||||
},
|
||||
|
|
@ -1315,6 +1315,51 @@ fn dirAccessWasi(
|
|||
return error.AccessDenied;
|
||||
}
|
||||
|
||||
fn dirAccessWindows(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Io.Dir,
|
||||
sub_path: []const u8,
|
||||
options: Io.Dir.AccessOptions,
|
||||
) Io.Dir.AccessError!void {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
|
||||
_ = options; // TODO
|
||||
|
||||
const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path);
|
||||
const sub_path_w = sub_path_w_array.span();
|
||||
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) return;
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) return;
|
||||
|
||||
const path_len_bytes = std.math.cast(u16, std.mem.sliceTo(sub_path_w, 0).len * 2) orelse
|
||||
return error.NameTooLong;
|
||||
var nt_name: windows.UNICODE_STRING = .{
|
||||
.Length = path_len_bytes,
|
||||
.MaximumLength = path_len_bytes,
|
||||
.Buffer = @constCast(sub_path_w.ptr),
|
||||
};
|
||||
var attr = windows.OBJECT_ATTRIBUTES{
|
||||
.Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
|
||||
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||
.ObjectName = &nt_name,
|
||||
.SecurityDescriptor = null,
|
||||
.SecurityQualityOfService = null,
|
||||
};
|
||||
var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
|
||||
switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
|
||||
.SUCCESS => return,
|
||||
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_NAME_INVALID => |err| return windows.statusBug(err),
|
||||
.INVALID_PARAMETER => |err| return windows.statusBug(err),
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err),
|
||||
else => |rc| return windows.unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
fn dirCreateFilePosix(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Io.Dir,
|
||||
|
|
@ -1818,7 +1863,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File
|
|||
var n: DWORD = undefined;
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => unreachable,
|
||||
.IO_PENDING => |err| return windows.statusBug(err),
|
||||
.OPERATION_ABORTED => continue,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
|
|
@ -1935,7 +1980,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset
|
|||
} else null;
|
||||
if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, overlapped) == 0) {
|
||||
switch (windows.GetLastError()) {
|
||||
.IO_PENDING => unreachable,
|
||||
.IO_PENDING => |err| return windows.statusBug(err),
|
||||
.OPERATION_ABORTED => continue,
|
||||
.BROKEN_PIPE => return 0,
|
||||
.HANDLE_EOF => return 0,
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.O
|
|||
|
||||
/// Same as `openFileAbsolute` but the path parameter is WTF-16-encoded.
|
||||
pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File {
|
||||
assert(path.isAbsoluteWindowsWTF16(absolute_path_w));
|
||||
assert(path.isAbsoluteWindowsWtf16(absolute_path_w));
|
||||
return cwd().openFileW(absolute_path_w, flags);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ pub fn isAbsoluteWindowsW(path_w: [*:0]const u16) bool {
|
|||
return isAbsoluteWindowsImpl(u16, mem.sliceTo(path_w, 0));
|
||||
}
|
||||
|
||||
pub fn isAbsoluteWindowsWTF16(path: []const u16) bool {
|
||||
pub fn isAbsoluteWindowsWtf16(path: []const u16) bool {
|
||||
return isAbsoluteWindowsImpl(u16, path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
|
|||
};
|
||||
var attr = OBJECT_ATTRIBUTES{
|
||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir,
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
|
||||
.Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||
const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0;
|
||||
break :blk inherit;
|
||||
|
|
@ -847,7 +847,7 @@ pub fn CreateSymbolicLink(
|
|||
// the C:\ drive.
|
||||
.rooted => break :target_path target_path,
|
||||
// Keep relative paths relative, but anything else needs to get NT-prefixed.
|
||||
else => if (!std.fs.path.isAbsoluteWindowsWTF16(target_path))
|
||||
else => if (!std.fs.path.isAbsoluteWindowsWtf16(target_path))
|
||||
break :target_path target_path,
|
||||
},
|
||||
// Already an NT path, no need to do anything to it
|
||||
|
|
@ -856,7 +856,7 @@ pub fn CreateSymbolicLink(
|
|||
}
|
||||
var prefixed_target_path = try wToPrefixedFileW(dir, target_path);
|
||||
// We do this after prefixing to ensure that drive-relative paths are treated as absolute
|
||||
is_target_absolute = std.fs.path.isAbsoluteWindowsWTF16(prefixed_target_path.span());
|
||||
is_target_absolute = std.fs.path.isAbsoluteWindowsWtf16(prefixed_target_path.span());
|
||||
break :target_path prefixed_target_path.span();
|
||||
};
|
||||
|
||||
|
|
@ -864,7 +864,7 @@ pub fn CreateSymbolicLink(
|
|||
var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
|
||||
const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4;
|
||||
const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2;
|
||||
const target_is_absolute = std.fs.path.isAbsoluteWindowsWTF16(final_target_path);
|
||||
const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path);
|
||||
const symlink_data = SYMLINK_DATA{
|
||||
.ReparseTag = IO_REPARSE_TAG_SYMLINK,
|
||||
.ReparseDataLength = @intCast(buf_len - header_len),
|
||||
|
|
@ -905,7 +905,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin
|
|||
};
|
||||
var attr = OBJECT_ATTRIBUTES{
|
||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else dir,
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir,
|
||||
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||
.ObjectName = &nt_name,
|
||||
.SecurityDescriptor = null,
|
||||
|
|
@ -1035,7 +1035,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
|
|||
|
||||
var attr = OBJECT_ATTRIBUTES{
|
||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir,
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
|
||||
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||
.ObjectName = &nt_name,
|
||||
.SecurityDescriptor = null,
|
||||
|
|
@ -2885,6 +2885,13 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError {
|
|||
return error.Unexpected;
|
||||
}
|
||||
|
||||
pub fn statusBug(status: NTSTATUS) UnexpectedError {
|
||||
switch (builtin.mode) {
|
||||
.Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}),
|
||||
else => return error.Unexpected,
|
||||
}
|
||||
}
|
||||
|
||||
pub const Win32Error = @import("windows/win32error.zig").Win32Error;
|
||||
pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
|
||||
pub const LANG = @import("windows/lang.zig");
|
||||
|
|
|
|||
|
|
@ -2617,7 +2617,7 @@ pub fn renameatW(
|
|||
if (ReplaceIfExists == windows.TRUE) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS;
|
||||
rename_info.* = .{
|
||||
.Flags = flags,
|
||||
.RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd,
|
||||
.RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
|
||||
.FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
|
||||
.FileName = undefined,
|
||||
};
|
||||
|
|
@ -2654,7 +2654,7 @@ pub fn renameatW(
|
|||
|
||||
rename_info.* = .{
|
||||
.Flags = ReplaceIfExists,
|
||||
.RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd,
|
||||
.RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
|
||||
.FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
|
||||
.FileName = undefined,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ pub inline fn callMain() u8 {
|
|||
switch (native_os) {
|
||||
.freestanding, .other => {},
|
||||
else => if (@errorReturnTrace()) |trace| {
|
||||
std.debug.dumpStackTrace(trace);
|
||||
std.debug.dumpStackTrace(trace.*);
|
||||
},
|
||||
}
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue