Skip to content

Commit 3f384ee

Browse files
committed
Watch.zig: remove realpath call, prefer NtCreateFile over CreateFileW
1 parent 5524342 commit 3f384ee

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

lib/std/Build/Watch.zig

+45-9
Original file line numberDiff line numberDiff line change
@@ -340,19 +340,55 @@ const Os = switch (builtin.os.tag) {
340340
const reaction_set = rs: {
341341
const gop = try w.dir_table.getOrPut(gpa, path);
342342
if (!gop.found_existing) {
343-
var realpath_buf: [std.fs.max_path_bytes]u8 = undefined;
344-
const realpath = try path.root_dir.handle.realpath(path.sub_path, &realpath_buf);
345-
const realpath_w = try windows.sliceToPrefixedFileW(null, realpath);
346-
const dir_handle = windows.kernel32.CreateFileW(
347-
realpath_w.span().ptr,
348-
windows.GENERIC_READ,
349-
windows.FILE_SHARE_DELETE | windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE,
343+
// The following code is a drawn out NtCreateFile call. (mostly adapted from std.fs.Dir.makeOpenDirAccessMaskW)
344+
// It's necessary in order to get the flags are required when calling ReadDirectoryChangesW.
345+
const root_fd = path.root_dir.handle.fd;
346+
const sub_path = path.subPathOrDot();
347+
const sub_path_w = try windows.sliceToPrefixedFileW(root_fd, sub_path);
348+
const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong;
349+
350+
var nt_name = windows.UNICODE_STRING{
351+
.Length = @intCast(path_len_bytes),
352+
.MaximumLength = @intCast(path_len_bytes),
353+
.Buffer = @constCast(sub_path_w.span().ptr),
354+
};
355+
var attr = windows.OBJECT_ATTRIBUTES{
356+
.Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
357+
.RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else root_fd,
358+
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
359+
.ObjectName = &nt_name,
360+
.SecurityDescriptor = null,
361+
.SecurityQualityOfService = null,
362+
};
363+
var io: windows.IO_STATUS_BLOCK = undefined;
364+
var dir_handle: windows.HANDLE = undefined;
365+
const rc = windows.ntdll.NtCreateFile(
366+
&dir_handle,
367+
windows.SYNCHRONIZE | windows.GENERIC_READ | windows.FILE_LIST_DIRECTORY,
368+
&attr,
369+
&io,
350370
null,
351-
windows.OPEN_EXISTING,
352-
windows.FILE_FLAG_BACKUP_SEMANTICS | windows.FILE_FLAG_OVERLAPPED,
371+
0,
372+
windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE,
373+
windows.FILE_OPEN,
374+
windows.FILE_DIRECTORY_FILE | windows.FILE_OPEN_FOR_BACKUP_INTENT,
353375
null,
376+
0,
354377
);
355378

379+
switch (rc) {
380+
.SUCCESS => {},
381+
.OBJECT_NAME_INVALID => return error.BadPathName,
382+
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
383+
.OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
384+
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
385+
.NOT_A_DIRECTORY => return error.NotDir,
386+
// This can happen if the directory has 'List folder contents' permission set to 'Deny'
387+
.ACCESS_DENIED => return error.AccessDenied,
388+
.INVALID_PARAMETER => unreachable,
389+
else => return windows.unexpectedStatus(rc),
390+
}
391+
356392
assert(dir_handle != windows.INVALID_HANDLE_VALUE);
357393

358394
// `dir_handle` may already be present in the table in

0 commit comments

Comments
 (0)