Build Runner: Initial Implementation for File System Watching on Windows
Closes #20598.
This initial implementation has the limit of 64 directories due to the usage of WaitForMultipleObjects. If merged, a follow up issue should be created to track overcoming that limitation.
BTW First time contributing, not very experienced with contributing on GitHub in general, but I love Zig. And I saw this issue and thought it would be a good learning opportunity for me.
windows.kernel32.ReadDirectoryChangesW is recently removed in #19641
Thoughts on where or how I can reintroduce it? Or if there is an Nt way it can be replicated?
I added an error return to readChanges and some accountability for resources.
I still need to deal with this point though:
Note, though, that it also may be true that the
dh_gop.found_existingcase is impossible. Opening the same directory twice does not result in the sameHANDLE:const std = @import("std"); pub fn main() !void { var dir1 = try std.fs.cwd().openDir(".", .{}); defer dir1.close(); var dir2 = try std.fs.cwd().openDir(".", .{}); defer dir2.close(); std.debug.print("1: {}\n2: {}\n", .{ dir1.fd, dir2.fd }); }results in
1: anyopaque@9c 2: anyopaque@98
Instead of keying on the file handle itself, which is determined to be different each NtCreateFile call, would it be best to key on a FILE_ID_INFORMATION structure returned by NtQueryInformationFile? I believe that it is unique per file and volume. If it already exists, I would just close that handle and keep the existing one open.
edit: Further reading I found that FileId is not supported on Fat32. To determine that, you check if the FileId is zero and if so, the file system doesn’t support it. So, I could hash on the VolumeSerialNumber and, the FileId when non-zero, or a number based on I’m guessing an all lowercase full path?
I think the way to go might be:
- Open a handle to the dir as you are currently
- Call
NtQueryInformationFilewithFILE_INTERNAL_INFORMATIONto get theIndexNumber - Call
NtQueryVolumeInformationFilewithFILE_FS_VOLUME_INFORMATIONto get theVolumeSerialNumber
Then hash the combination of those.
Some examples of calling NtQueryInformationFile/NtQueryVolumeInformationFile can be found here:
- https://github.com/ziglang/zig/blob/ff02bf403b546ffc91158e976a4e9567ab02582d/lib/std/fs/File.zig#L211-L217
- https://github.com/ziglang/zig/blob/ff02bf403b546ffc91158e976a4e9567ab02582d/lib/std/fs/File.zig#L457-L469
(I'd recommend using that BUFFER_OVERFLOW handling for the NtQueryVolumeInformationFile since we don't care about the volume name)
Forgot that I had to add FILE_FS_VOLUME_INFORMATION in windows.zig, will fix later today.
Nice work!