| ... | @@ -377,6 +377,8 @@ pub const Dir = struct { | ... | @@ -377,6 +377,8 @@ pub const Dir = struct { |
| 377 | }; | 377 | }; |
| 378 | }; | 378 | }; |
| 379 | | 379 | |
| | 380 | const IteratorError = error{AccessDenied} || os.UnexpectedError; |
| | 381 | |
| 380 | pub const Iterator = switch (builtin.os) { | 382 | pub const Iterator = switch (builtin.os) { |
| 381 | .macosx, .ios, .freebsd, .netbsd => struct { | 383 | .macosx, .ios, .freebsd, .netbsd => struct { |
| 382 | dir: Dir, | 384 | dir: Dir, |
| ... | @@ -387,9 +389,11 @@ pub const Dir = struct { | ... | @@ -387,9 +389,11 @@ pub const Dir = struct { |
| 387 | | 389 | |
| 388 | const Self = @This(); | 390 | const Self = @This(); |
| 389 | | 391 | |
| | 392 | pub const Error = IteratorError; |
| | 393 | |
| 390 | /// Memory such as file names referenced in this returned entry becomes invalid | 394 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 391 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. | 395 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. |
| 392 | pub fn next(self: *Self) !?Entry { | 396 | pub fn next(self: *Self) Error!?Entry { |
| 393 | switch (builtin.os) { | 397 | switch (builtin.os) { |
| 394 | .macosx, .ios => return self.nextDarwin(), | 398 | .macosx, .ios => return self.nextDarwin(), |
| 395 | .freebsd, .netbsd => return self.nextBsd(), | 399 | .freebsd, .netbsd => return self.nextBsd(), |
| ... | @@ -504,9 +508,11 @@ pub const Dir = struct { | ... | @@ -504,9 +508,11 @@ pub const Dir = struct { |
| 504 | | 508 | |
| 505 | const Self = @This(); | 509 | const Self = @This(); |
| 506 | | 510 | |
| | 511 | pub const Error = IteratorError; |
| | 512 | |
| 507 | /// Memory such as file names referenced in this returned entry becomes invalid | 513 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 508 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. | 514 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. |
| 509 | pub fn next(self: *Self) !?Entry { | 515 | pub fn next(self: *Self) Error!?Entry { |
| 510 | start_over: while (true) { | 516 | start_over: while (true) { |
| 511 | if (self.index >= self.end_index) { | 517 | if (self.index >= self.end_index) { |
| 512 | const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len); | 518 | const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len); |
| ... | @@ -560,17 +566,13 @@ pub const Dir = struct { | ... | @@ -560,17 +566,13 @@ pub const Dir = struct { |
| 560 | | 566 | |
| 561 | const Self = @This(); | 567 | const Self = @This(); |
| 562 | | 568 | |
| 563 | pub fn next(self: *Self) !?Entry { | 569 | pub const Error = IteratorError; |
| | 570 | |
| | 571 | pub fn next(self: *Self) Error!?Entry { |
| 564 | start_over: while (true) { | 572 | start_over: while (true) { |
| 565 | const w = os.windows; | 573 | const w = os.windows; |
| 566 | if (self.index >= self.end_index) { | 574 | if (self.index >= self.end_index) { |
| 567 | var io: w.IO_STATUS_BLOCK = undefined; | 575 | var io: w.IO_STATUS_BLOCK = undefined; |
| 568 | //var mask_buf = [2]u16{ 'a', 0 }; | | |
| 569 | //var mask = w.UNICODE_STRING{ | | |
| 570 | // .Length = 2, | | |
| 571 | // .MaximumLength = 2, | | |
| 572 | // .Buffer = &mask_buf, | | |
| 573 | //}; | | |
| 574 | const rc = w.ntdll.NtQueryDirectoryFile( | 576 | const rc = w.ntdll.NtQueryDirectoryFile( |
| 575 | self.dir.fd, | 577 | self.dir.fd, |
| 576 | null, | 578 | null, |
| ... | @@ -709,7 +711,6 @@ pub const Dir = struct { | ... | @@ -709,7 +711,6 @@ pub const Dir = struct { |
| 709 | | 711 | |
| 710 | /// Call `close` on the result when done. | 712 | /// Call `close` on the result when done. |
| 711 | pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir { | 713 | pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir { |
| 712 | // std.debug.warn("openDir {}\n", sub_path); | | |
| 713 | if (os.windows.is_the_target) { | 714 | if (os.windows.is_the_target) { |
| 714 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 715 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 715 | return self.openDirW(&sub_path_w); | 716 | return self.openDirW(&sub_path_w); |
| ... | @@ -746,39 +747,7 @@ pub const Dir = struct { | ... | @@ -746,39 +747,7 @@ pub const Dir = struct { |
| 746 | .fd = undefined, | 747 | .fd = undefined, |
| 747 | }; | 748 | }; |
| 748 | | 749 | |
| 749 | const desired_access = w.GENERIC_READ | w.SYNCHRONIZE; | | |
| 750 | | | |
| 751 | // if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { | | |
| 752 | // // Windows gives me STATUS_OBJECT_NAME_INVALID with "." as the object name. | | |
| 753 | | | |
| 754 | // if (w.kernel32.DuplicateHandle(w.self_process_handle, self.fd, w.self_process_handle, &result.fd, desired_access, w.TRUE, 0) == 0) { | | |
| 755 | // switch (w.kernel32.GetLastError()) { | | |
| 756 | // else => |err| return w.unexpectedError(err), | | |
| 757 | // } | | |
| 758 | | | |
| 759 | // @panic("handle DuplicateHandle error"); | | |
| 760 | // } | | |
| 761 | // return result; | | |
| 762 | // } | | |
| 763 | | | |
| 764 | //var mask: ?[*]const u16 = undefined; | | |
| 765 | //var nt_name: w.UNICODE_STRING = undefined; | | |
| 766 | //if (w.ntdll.RtlDosPathNameToNtPathName_U(sub_path_w, &nt_name, null, null) == 0) { | | |
| 767 | // return error.FileNotFound; | | |
| 768 | //} | | |
| 769 | //defer w.ntdll.RtlFreeUnicodeString(&nt_name); | | |
| 770 | //if (mask) |m| { | | |
| 771 | // if (m[0] == 0) { | | |
| 772 | // return error.FileNotFound; | | |
| 773 | // } else { | | |
| 774 | // nt_name.Length = @intCast(u16, @ptrToInt(mask) - @ptrToInt(nt_name.Buffer)); | | |
| 775 | // } | | |
| 776 | //} else { | | |
| 777 | // return error.FileNotFound; | | |
| 778 | //} | | |
| 779 | | | |
| 780 | const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2); | 750 | const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2); |
| 781 | // std.debug.warn("path_len_bytes = {}\n", path_len_bytes); | | |
| 782 | var nt_name = w.UNICODE_STRING{ | 751 | var nt_name = w.UNICODE_STRING{ |
| 783 | .Length = path_len_bytes, | 752 | .Length = path_len_bytes, |
| 784 | .MaximumLength = path_len_bytes, | 753 | .MaximumLength = path_len_bytes, |
| ... | @@ -796,19 +765,15 @@ pub const Dir = struct { | ... | @@ -796,19 +765,15 @@ pub const Dir = struct { |
| 796 | // Windows does not recognize this, but it does work with empty string. | 765 | // Windows does not recognize this, but it does work with empty string. |
| 797 | nt_name.Length = 0; | 766 | nt_name.Length = 0; |
| 798 | } | 767 | } |
| 799 | // std.debug.warn("RootDirectory = {}\n", attr.RootDirectory); | 768 | if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { |
| | 769 | // If you're looking to contribute to zig and fix this, see here for an example of how to |
| | 770 | // implement this: https://git.midipix.org/ntapi/tree/src/fs/ntapi_tt_open_physical_parent_directory.c |
| | 771 | @panic("TODO opening '..' with a relative directory handle is not yet implemented on Windows"); |
| | 772 | } |
| 800 | var io: w.IO_STATUS_BLOCK = undefined; | 773 | var io: w.IO_STATUS_BLOCK = undefined; |
| 801 | const wide_slice = nt_name.Buffer[0 .. nt_name.Length / 2]; | | |
| 802 | //const wide_slice2 = std.mem.toSliceConst(u16, mask.?); | | |
| 803 | var buf: [200]u8 = undefined; | | |
| 804 | //var buf2: [200]u8 = undefined; | | |
| 805 | const len = std.unicode.utf16leToUtf8(&buf, wide_slice) catch unreachable; | | |
| 806 | //const len2 = std.unicode.utf16leToUtf8(&buf2, wide_slice2) catch unreachable; | | |
| 807 | // std.debug.warn("path: {}\n", buf[0..len]); | | |
| 808 | //std.debug.warn("path: {}\nmask: {}\n", buf[0..len], buf2[0..len2]); | | |
| 809 | const rc = w.ntdll.NtCreateFile( | 774 | const rc = w.ntdll.NtCreateFile( |
| 810 | &result.fd, | 775 | &result.fd, |
| 811 | desired_access, | 776 | w.GENERIC_READ | w.SYNCHRONIZE, |
| 812 | &attr, | 777 | &attr, |
| 813 | &io, | 778 | &io, |
| 814 | null, | 779 | null, |
| ... | @@ -819,15 +784,12 @@ pub const Dir = struct { | ... | @@ -819,15 +784,12 @@ pub const Dir = struct { |
| 819 | null, | 784 | null, |
| 820 | 0, | 785 | 0, |
| 821 | ); | 786 | ); |
| 822 | // std.debug.warn("result.fd = {}\n", result.fd); | | |
| 823 | switch (rc) { | 787 | switch (rc) { |
| 824 | w.STATUS.SUCCESS => return result, | 788 | w.STATUS.SUCCESS => return result, |
| 825 | w.STATUS.OBJECT_NAME_INVALID => @panic("openDirW invalid object name"), | 789 | w.STATUS.OBJECT_NAME_INVALID => unreachable, |
| 826 | w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound, | 790 | w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound, |
| 827 | w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound, | 791 | w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound, |
| 828 | w.STATUS.INVALID_PARAMETER => { | 792 | w.STATUS.INVALID_PARAMETER => unreachable, |
| 829 | @panic("invalid parameter"); | | |
| 830 | }, | | |
| 831 | else => return w.unexpectedStatus(rc), | 793 | else => return w.unexpectedStatus(rc), |
| 832 | } | 794 | } |
| 833 | } | 795 | } |