| author | |
| committer | |
| log | 2b67f56c35d0a61be43f8ca23535096ae3ca4948 |
| tree | 591eea9b6dce8bc4e0a524993da208515b109f92 |
| parent | 577f9fdbae12eabbbf87bd2cc36a1565df3153b2 |
Also adds safety check for attempting to iterate directory not opened with `iterate = true`.10 files changed, 145 insertions(+), 104 deletions(-)
lib/std/build.zig+3-3| ... | @@ -3245,7 +3245,7 @@ pub const LibExeObjStep = struct { | ... | @@ -3245,7 +3245,7 @@ pub const LibExeObjStep = struct { |
| 3245 | const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n"); | 3245 | const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n"); |
| 3246 | 3246 | ||
| 3247 | if (self.output_dir) |output_dir| { | 3247 | if (self.output_dir) |output_dir| { |
| 3248 | var src_dir = try std.fs.cwd().openDir(build_output_dir, .{ .iterate = true }); | 3248 | var src_dir = try std.fs.cwd().openIterableDir(build_output_dir, .{}); |
| 3249 | defer src_dir.close(); | 3249 | defer src_dir.close(); |
| 3250 | 3250 | ||
| 3251 | // Create the output directory if it doesn't exist. | 3251 | // Create the output directory if it doesn't exist. |
| ... | @@ -3265,7 +3265,7 @@ pub const LibExeObjStep = struct { | ... | @@ -3265,7 +3265,7 @@ pub const LibExeObjStep = struct { |
| 3265 | mem.eql(u8, entry.name, "zld.id") or | 3265 | mem.eql(u8, entry.name, "zld.id") or |
| 3266 | mem.eql(u8, entry.name, "lld.id")) continue; | 3266 | mem.eql(u8, entry.name, "lld.id")) continue; |
| 3267 | 3267 | ||
| 3268 | _ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{}); | 3268 | _ = try src_dir.dir.updateFile(entry.name, dest_dir, entry.name, .{}); |
| 3269 | } | 3269 | } |
| 3270 | } else { | 3270 | } else { |
| 3271 | self.output_dir = build_output_dir; | 3271 | self.output_dir = build_output_dir; |
| ... | @@ -3480,7 +3480,7 @@ pub const InstallDirStep = struct { | ... | @@ -3480,7 +3480,7 @@ pub const InstallDirStep = struct { |
| 3480 | const self = @fieldParentPtr(InstallDirStep, "step", step); | 3480 | const self = @fieldParentPtr(InstallDirStep, "step", step); |
| 3481 | const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir); | 3481 | const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir); |
| 3482 | const full_src_dir = self.builder.pathFromRoot(self.options.source_dir); | 3482 | const full_src_dir = self.builder.pathFromRoot(self.options.source_dir); |
| 3483 | var src_dir = try std.fs.cwd().openDir(full_src_dir, .{ .iterate = true }); | 3483 | var src_dir = try std.fs.cwd().openIterableDir(full_src_dir, .{}); |
| 3484 | defer src_dir.close(); | 3484 | defer src_dir.close(); |
| 3485 | var it = try src_dir.walk(self.builder.allocator); | 3485 | var it = try src_dir.walk(self.builder.allocator); |
| 3486 | next_entry: while (try it.next()) |entry| { | 3486 | next_entry: while (try it.next()) |entry| { |
lib/std/fs.zig+96-56| ... | @@ -283,8 +283,10 @@ pub fn renameW(old_dir: Dir, old_sub_path_w: []const u16, new_dir: Dir, new_sub_ | ... | @@ -283,8 +283,10 @@ pub fn renameW(old_dir: Dir, old_sub_path_w: []const u16, new_dir: Dir, new_sub_ |
| 283 | return os.renameatW(old_dir.fd, old_sub_path_w, new_dir.fd, new_sub_path_w); | 283 | return os.renameatW(old_dir.fd, old_sub_path_w, new_dir.fd, new_sub_path_w); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | pub const Dir = struct { | 286 | /// A directory that can be iterated. It is *NOT* legal to initialize this with a regular `Dir` |
| 287 | fd: os.fd_t, | 287 | /// that has been opened without iteration permission. |
| 288 | pub const IterableDir = struct { | ||
| 289 | dir: Dir, | ||
| 288 | 290 | ||
| 289 | pub const Entry = struct { | 291 | pub const Entry = struct { |
| 290 | name: []const u8, | 292 | name: []const u8, |
| ... | @@ -779,7 +781,7 @@ pub const Dir = struct { | ... | @@ -779,7 +781,7 @@ pub const Dir = struct { |
| 779 | else => @compileError("unimplemented"), | 781 | else => @compileError("unimplemented"), |
| 780 | }; | 782 | }; |
| 781 | 783 | ||
| 782 | pub fn iterate(self: Dir) Iterator { | 784 | pub fn iterate(self: IterableDir) Iterator { |
| 783 | switch (builtin.os.tag) { | 785 | switch (builtin.os.tag) { |
| 784 | .macos, | 786 | .macos, |
| 785 | .ios, | 787 | .ios, |
| ... | @@ -789,7 +791,7 @@ pub const Dir = struct { | ... | @@ -789,7 +791,7 @@ pub const Dir = struct { |
| 789 | .openbsd, | 791 | .openbsd, |
| 790 | .solaris, | 792 | .solaris, |
| 791 | => return Iterator{ | 793 | => return Iterator{ |
| 792 | .dir = self, | 794 | .dir = self.dir, |
| 793 | .seek = 0, | 795 | .seek = 0, |
| 794 | .index = 0, | 796 | .index = 0, |
| 795 | .end_index = 0, | 797 | .end_index = 0, |
| ... | @@ -797,14 +799,14 @@ pub const Dir = struct { | ... | @@ -797,14 +799,14 @@ pub const Dir = struct { |
| 797 | .first_iter = true, | 799 | .first_iter = true, |
| 798 | }, | 800 | }, |
| 799 | .linux, .haiku => return Iterator{ | 801 | .linux, .haiku => return Iterator{ |
| 800 | .dir = self, | 802 | .dir = self.dir, |
| 801 | .index = 0, | 803 | .index = 0, |
| 802 | .end_index = 0, | 804 | .end_index = 0, |
| 803 | .buf = undefined, | 805 | .buf = undefined, |
| 804 | .first_iter = true, | 806 | .first_iter = true, |
| 805 | }, | 807 | }, |
| 806 | .windows => return Iterator{ | 808 | .windows => return Iterator{ |
| 807 | .dir = self, | 809 | .dir = self.dir, |
| 808 | .index = 0, | 810 | .index = 0, |
| 809 | .end_index = 0, | 811 | .end_index = 0, |
| 810 | .first_iter = true, | 812 | .first_iter = true, |
| ... | @@ -812,7 +814,7 @@ pub const Dir = struct { | ... | @@ -812,7 +814,7 @@ pub const Dir = struct { |
| 812 | .name_data = undefined, | 814 | .name_data = undefined, |
| 813 | }, | 815 | }, |
| 814 | .wasi => return Iterator{ | 816 | .wasi => return Iterator{ |
| 815 | .dir = self, | 817 | .dir = self.dir, |
| 816 | .cookie = os.wasi.DIRCOOKIE_START, | 818 | .cookie = os.wasi.DIRCOOKIE_START, |
| 817 | .index = 0, | 819 | .index = 0, |
| 818 | .end_index = 0, | 820 | .end_index = 0, |
| ... | @@ -833,11 +835,11 @@ pub const Dir = struct { | ... | @@ -833,11 +835,11 @@ pub const Dir = struct { |
| 833 | dir: Dir, | 835 | dir: Dir, |
| 834 | basename: []const u8, | 836 | basename: []const u8, |
| 835 | path: []const u8, | 837 | path: []const u8, |
| 836 | kind: Dir.Entry.Kind, | 838 | kind: IterableDir.Entry.Kind, |
| 837 | }; | 839 | }; |
| 838 | 840 | ||
| 839 | const StackItem = struct { | 841 | const StackItem = struct { |
| 840 | iter: Dir.Iterator, | 842 | iter: IterableDir.Iterator, |
| 841 | dirname_len: usize, | 843 | dirname_len: usize, |
| 842 | }; | 844 | }; |
| 843 | 845 | ||
| ... | @@ -857,7 +859,7 @@ pub const Dir = struct { | ... | @@ -857,7 +859,7 @@ pub const Dir = struct { |
| 857 | } | 859 | } |
| 858 | try self.name_buffer.appendSlice(base.name); | 860 | try self.name_buffer.appendSlice(base.name); |
| 859 | if (base.kind == .Directory) { | 861 | if (base.kind == .Directory) { |
| 860 | var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) { | 862 | var new_dir = top.iter.dir.openIterableDir(base.name, .{}) catch |err| switch (err) { |
| 861 | error.NameTooLong => unreachable, // no path sep in base.name | 863 | error.NameTooLong => unreachable, // no path sep in base.name |
| 862 | else => |e| return e, | 864 | else => |e| return e, |
| 863 | }; | 865 | }; |
| ... | @@ -896,11 +898,10 @@ pub const Dir = struct { | ... | @@ -896,11 +898,10 @@ pub const Dir = struct { |
| 896 | }; | 898 | }; |
| 897 | 899 | ||
| 898 | /// Recursively iterates over a directory. | 900 | /// Recursively iterates over a directory. |
| 899 | /// `self` must have been opened with `OpenDirOptions{.iterate = true}`. | ||
| 900 | /// Must call `Walker.deinit` when done. | 901 | /// Must call `Walker.deinit` when done. |
| 901 | /// The order of returned file system entries is undefined. | 902 | /// The order of returned file system entries is undefined. |
| 902 | /// `self` will not be closed after walking it. | 903 | /// `self` will not be closed after walking it. |
| 903 | pub fn walk(self: Dir, allocator: Allocator) !Walker { | 904 | pub fn walk(self: IterableDir, allocator: Allocator) !Walker { |
| 904 | var name_buffer = std.ArrayList(u8).init(allocator); | 905 | var name_buffer = std.ArrayList(u8).init(allocator); |
| 905 | errdefer name_buffer.deinit(); | 906 | errdefer name_buffer.deinit(); |
| 906 | 907 | ||
| ... | @@ -918,6 +919,52 @@ pub const Dir = struct { | ... | @@ -918,6 +919,52 @@ pub const Dir = struct { |
| 918 | }; | 919 | }; |
| 919 | } | 920 | } |
| 920 | 921 | ||
| 922 | pub fn close(self: *IterableDir) void { | ||
| 923 | self.dir.close(); | ||
| 924 | self.* = undefined; | ||
| 925 | } | ||
| 926 | |||
| 927 | pub const ChmodError = File.ChmodError; | ||
| 928 | |||
| 929 | /// Changes the mode of the directory. | ||
| 930 | /// The process must have the correct privileges in order to do this | ||
| 931 | /// successfully, or must have the effective user ID matching the owner | ||
| 932 | /// of the directory. | ||
| 933 | pub fn chmod(self: IterableDir, new_mode: File.Mode) ChmodError!void { | ||
| 934 | const file: File = .{ | ||
| 935 | .handle = self.dir.fd, | ||
| 936 | .capable_io_mode = .blocking, | ||
| 937 | }; | ||
| 938 | try file.chmod(new_mode); | ||
| 939 | } | ||
| 940 | |||
| 941 | /// Changes the owner and group of the directory. | ||
| 942 | /// The process must have the correct privileges in order to do this | ||
| 943 | /// successfully. The group may be changed by the owner of the directory to | ||
| 944 | /// any group of which the owner is a member. If the | ||
| 945 | /// owner or group is specified as `null`, the ID is not changed. | ||
| 946 | pub fn chown(self: IterableDir, owner: ?File.Uid, group: ?File.Gid) ChownError!void { | ||
| 947 | const file: File = .{ | ||
| 948 | .handle = self.dir.fd, | ||
| 949 | .capable_io_mode = .blocking, | ||
| 950 | }; | ||
| 951 | try file.chown(owner, group); | ||
| 952 | } | ||
| 953 | |||
| 954 | pub const ChownError = File.ChownError; | ||
| 955 | }; | ||
| 956 | |||
| 957 | pub const Dir = struct { | ||
| 958 | fd: os.fd_t, | ||
| 959 | iterable: @TypeOf(iterable_safety) = iterable_safety, | ||
| 960 | |||
| 961 | const iterable_safety = if (builtin.mode == .Debug) false else {}; | ||
| 962 | |||
| 963 | pub const iterate = @compileError("only 'IterableDir' can be iterated; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'"); | ||
| 964 | pub const walk = @compileError("only 'IterableDir' can be walked; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'"); | ||
| 965 | pub const chmod = @compileError("only 'IterableDir' can have its mode changed; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'"); | ||
| 966 | pub const chown = @compileError("only 'IterableDir' can have its owner changed; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'"); | ||
| 967 | |||
| 921 | pub const OpenError = error{ | 968 | pub const OpenError = error{ |
| 922 | FileNotFound, | 969 | FileNotFound, |
| 923 | NotDir, | 970 | NotDir, |
| ... | @@ -1507,6 +1554,26 @@ pub const Dir = struct { | ... | @@ -1507,6 +1554,26 @@ pub const Dir = struct { |
| 1507 | } | 1554 | } |
| 1508 | } | 1555 | } |
| 1509 | 1556 | ||
| 1557 | /// Opens an iterable directory at the given path. The directory is a system resource that remains | ||
| 1558 | /// open until `close` is called on the result. | ||
| 1559 | /// | ||
| 1560 | /// Asserts that the path parameter has no null bytes. | ||
| 1561 | pub fn openIterableDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!IterableDir { | ||
| 1562 | var adjusted_args = args; | ||
| 1563 | adjusted_args.iterate = true; | ||
| 1564 | const new_dir = try self.openDir(sub_path, adjusted_args); | ||
| 1565 | return IterableDir{ .dir = new_dir }; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | /// Convert `self` into an iterable directory. | ||
| 1569 | /// Asserts that `self` was opened with `iterate = true`. | ||
| 1570 | pub fn intoIterable(self: Dir) IterableDir { | ||
| 1571 | if (builtin.mode == .Debug) { | ||
| 1572 | assert(self.iterable); | ||
| 1573 | } | ||
| 1574 | return .{ .dir = self }; | ||
| 1575 | } | ||
| 1576 | |||
| 1510 | /// Same as `openDir` except only WASI. | 1577 | /// Same as `openDir` except only WASI. |
| 1511 | pub fn openDirWasi(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { | 1578 | pub fn openDirWasi(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { |
| 1512 | const w = os.wasi; | 1579 | const w = os.wasi; |
| ... | @@ -1552,7 +1619,7 @@ pub const Dir = struct { | ... | @@ -1552,7 +1619,7 @@ pub const Dir = struct { |
| 1552 | error.FileBusy => unreachable, // can't happen for directories | 1619 | error.FileBusy => unreachable, // can't happen for directories |
| 1553 | else => |e| return e, | 1620 | else => |e| return e, |
| 1554 | }; | 1621 | }; |
| 1555 | return Dir{ .fd = fd }; | 1622 | return Dir{ .fd = fd, .iterable = if (builtin.mode == .Debug) args.iterate else {} }; |
| 1556 | } | 1623 | } |
| 1557 | 1624 | ||
| 1558 | /// Same as `openDir` except the parameter is null-terminated. | 1625 | /// Same as `openDir` except the parameter is null-terminated. |
| ... | @@ -1566,7 +1633,9 @@ pub const Dir = struct { | ... | @@ -1566,7 +1633,9 @@ pub const Dir = struct { |
| 1566 | const O_PATH = if (@hasDecl(os.O, "PATH")) os.O.PATH else 0; | 1633 | const O_PATH = if (@hasDecl(os.O, "PATH")) os.O.PATH else 0; |
| 1567 | return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | O_PATH | symlink_flags); | 1634 | return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | O_PATH | symlink_flags); |
| 1568 | } else { | 1635 | } else { |
| 1569 | return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | symlink_flags); | 1636 | var dir = try self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | symlink_flags); |
| 1637 | if (builtin.mode == .Debug) dir.iterable = true; | ||
| 1638 | return dir; | ||
| 1570 | } | 1639 | } |
| 1571 | } | 1640 | } |
| 1572 | 1641 | ||
| ... | @@ -1578,7 +1647,9 @@ pub const Dir = struct { | ... | @@ -1578,7 +1647,9 @@ pub const Dir = struct { |
| 1578 | const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | | 1647 | const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | |
| 1579 | w.SYNCHRONIZE | w.FILE_TRAVERSE; | 1648 | w.SYNCHRONIZE | w.FILE_TRAVERSE; |
| 1580 | const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags; | 1649 | const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags; |
| 1581 | return self.openDirAccessMaskW(sub_path_w, flags, args.no_follow); | 1650 | var dir = try self.openDirAccessMaskW(sub_path_w, flags, args.no_follow); |
| 1651 | if (builtin.mode == .Debug) dir.iterable = args.iterate; | ||
| 1652 | return dir; | ||
| 1582 | } | 1653 | } |
| 1583 | 1654 | ||
| 1584 | /// `flags` must contain `os.O.DIRECTORY`. | 1655 | /// `flags` must contain `os.O.DIRECTORY`. |
| ... | @@ -1958,7 +2029,7 @@ pub const Dir = struct { | ... | @@ -1958,7 +2029,7 @@ pub const Dir = struct { |
| 1958 | error.Unexpected, | 2029 | error.Unexpected, |
| 1959 | => |e| return e, | 2030 | => |e| return e, |
| 1960 | } | 2031 | } |
| 1961 | var dir = self.openDir(sub_path, .{ .iterate = true, .no_follow = true }) catch |err| switch (err) { | 2032 | var iterable_dir = self.openIterableDir(sub_path, .{ .no_follow = true }) catch |err| switch (err) { |
| 1962 | error.NotDir => { | 2033 | error.NotDir => { |
| 1963 | if (got_access_denied) { | 2034 | if (got_access_denied) { |
| 1964 | return error.AccessDenied; | 2035 | return error.AccessDenied; |
| ... | @@ -1984,11 +2055,11 @@ pub const Dir = struct { | ... | @@ -1984,11 +2055,11 @@ pub const Dir = struct { |
| 1984 | error.DeviceBusy, | 2055 | error.DeviceBusy, |
| 1985 | => |e| return e, | 2056 | => |e| return e, |
| 1986 | }; | 2057 | }; |
| 1987 | var cleanup_dir_parent: ?Dir = null; | 2058 | var cleanup_dir_parent: ?IterableDir = null; |
| 1988 | defer if (cleanup_dir_parent) |*d| d.close(); | 2059 | defer if (cleanup_dir_parent) |*d| d.close(); |
| 1989 | 2060 | ||
| 1990 | var cleanup_dir = true; | 2061 | var cleanup_dir = true; |
| 1991 | defer if (cleanup_dir) dir.close(); | 2062 | defer if (cleanup_dir) iterable_dir.close(); |
| 1992 | 2063 | ||
| 1993 | // Valid use of MAX_PATH_BYTES because dir_name_buf will only | 2064 | // Valid use of MAX_PATH_BYTES because dir_name_buf will only |
| 1994 | // ever store a single path component that was returned from the | 2065 | // ever store a single path component that was returned from the |
| ... | @@ -2001,9 +2072,9 @@ pub const Dir = struct { | ... | @@ -2001,9 +2072,9 @@ pub const Dir = struct { |
| 2001 | // open it, and close the original directory. Repeat. Then start the entire operation over. | 2072 | // open it, and close the original directory. Repeat. Then start the entire operation over. |
| 2002 | 2073 | ||
| 2003 | scan_dir: while (true) { | 2074 | scan_dir: while (true) { |
| 2004 | var dir_it = dir.iterate(); | 2075 | var dir_it = iterable_dir.iterate(); |
| 2005 | while (try dir_it.next()) |entry| { | 2076 | while (try dir_it.next()) |entry| { |
| 2006 | if (dir.deleteFile(entry.name)) { | 2077 | if (iterable_dir.dir.deleteFile(entry.name)) { |
| 2007 | continue; | 2078 | continue; |
| 2008 | } else |err| switch (err) { | 2079 | } else |err| switch (err) { |
| 2009 | error.FileNotFound => continue, | 2080 | error.FileNotFound => continue, |
| ... | @@ -2026,7 +2097,7 @@ pub const Dir = struct { | ... | @@ -2026,7 +2097,7 @@ pub const Dir = struct { |
| 2026 | => |e| return e, | 2097 | => |e| return e, |
| 2027 | } | 2098 | } |
| 2028 | 2099 | ||
| 2029 | const new_dir = dir.openDir(entry.name, .{ .iterate = true, .no_follow = true }) catch |err| switch (err) { | 2100 | const new_dir = iterable_dir.dir.openIterableDir(entry.name, .{ .no_follow = true }) catch |err| switch (err) { |
| 2030 | error.NotDir => { | 2101 | error.NotDir => { |
| 2031 | if (got_access_denied) { | 2102 | if (got_access_denied) { |
| 2032 | return error.AccessDenied; | 2103 | return error.AccessDenied; |
| ... | @@ -2053,19 +2124,19 @@ pub const Dir = struct { | ... | @@ -2053,19 +2124,19 @@ pub const Dir = struct { |
| 2053 | => |e| return e, | 2124 | => |e| return e, |
| 2054 | }; | 2125 | }; |
| 2055 | if (cleanup_dir_parent) |*d| d.close(); | 2126 | if (cleanup_dir_parent) |*d| d.close(); |
| 2056 | cleanup_dir_parent = dir; | 2127 | cleanup_dir_parent = iterable_dir; |
| 2057 | dir = new_dir; | 2128 | iterable_dir = new_dir; |
| 2058 | mem.copy(u8, &dir_name_buf, entry.name); | 2129 | mem.copy(u8, &dir_name_buf, entry.name); |
| 2059 | dir_name = dir_name_buf[0..entry.name.len]; | 2130 | dir_name = dir_name_buf[0..entry.name.len]; |
| 2060 | continue :scan_dir; | 2131 | continue :scan_dir; |
| 2061 | } | 2132 | } |
| 2062 | // Reached the end of the directory entries, which means we successfully deleted all of them. | 2133 | // Reached the end of the directory entries, which means we successfully deleted all of them. |
| 2063 | // Now to remove the directory itself. | 2134 | // Now to remove the directory itself. |
| 2064 | dir.close(); | 2135 | iterable_dir.close(); |
| 2065 | cleanup_dir = false; | 2136 | cleanup_dir = false; |
| 2066 | 2137 | ||
| 2067 | if (cleanup_dir_parent) |d| { | 2138 | if (cleanup_dir_parent) |d| { |
| 2068 | d.deleteDir(dir_name) catch |err| switch (err) { | 2139 | d.dir.deleteDir(dir_name) catch |err| switch (err) { |
| 2069 | // These two things can happen due to file system race conditions. | 2140 | // These two things can happen due to file system race conditions. |
| 2070 | error.FileNotFound, error.DirNotEmpty => continue :start_over, | 2141 | error.FileNotFound, error.DirNotEmpty => continue :start_over, |
| 2071 | else => |e| return e, | 2142 | else => |e| return e, |
| ... | @@ -2246,37 +2317,6 @@ pub const Dir = struct { | ... | @@ -2246,37 +2317,6 @@ pub const Dir = struct { |
| 2246 | return file.stat(); | 2317 | return file.stat(); |
| 2247 | } | 2318 | } |
| 2248 | 2319 | ||
| 2249 | pub const ChmodError = File.ChmodError; | ||
| 2250 | |||
| 2251 | /// Changes the mode of the directory. | ||
| 2252 | /// The process must have the correct privileges in order to do this | ||
| 2253 | /// successfully, or must have the effective user ID matching the owner | ||
| 2254 | /// of the directory. Additionally, the directory must have been opened | ||
| 2255 | /// with `OpenDirOptions{ .iterate = true }`. | ||
| 2256 | pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void { | ||
| 2257 | const file: File = .{ | ||
| 2258 | .handle = self.fd, | ||
| 2259 | .capable_io_mode = .blocking, | ||
| 2260 | }; | ||
| 2261 | try file.chmod(new_mode); | ||
| 2262 | } | ||
| 2263 | |||
| 2264 | /// Changes the owner and group of the directory. | ||
| 2265 | /// The process must have the correct privileges in order to do this | ||
| 2266 | /// successfully. The group may be changed by the owner of the directory to | ||
| 2267 | /// any group of which the owner is a member. Additionally, the directory | ||
| 2268 | /// must have been opened with `OpenDirOptions{ .iterate = true }`. If the | ||
| 2269 | /// owner or group is specified as `null`, the ID is not changed. | ||
| 2270 | pub fn chown(self: Dir, owner: ?File.Uid, group: ?File.Gid) ChownError!void { | ||
| 2271 | const file: File = .{ | ||
| 2272 | .handle = self.fd, | ||
| 2273 | .capable_io_mode = .blocking, | ||
| 2274 | }; | ||
| 2275 | try file.chown(owner, group); | ||
| 2276 | } | ||
| 2277 | |||
| 2278 | pub const ChownError = File.ChownError; | ||
| 2279 | |||
| 2280 | const Permissions = File.Permissions; | 2320 | const Permissions = File.Permissions; |
| 2281 | pub const SetPermissionsError = File.SetPermissionsError; | 2321 | pub const SetPermissionsError = File.SetPermissionsError; |
| 2282 | 2322 |
lib/std/fs/test.zig+21-20| ... | @@ -8,6 +8,7 @@ const wasi = std.os.wasi; | ... | @@ -8,6 +8,7 @@ const wasi = std.os.wasi; |
| 8 | 8 | ||
| 9 | const ArenaAllocator = std.heap.ArenaAllocator; | 9 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 10 | const Dir = std.fs.Dir; | 10 | const Dir = std.fs.Dir; |
| 11 | const IterableDir = std.fs.IterableDir; | ||
| 11 | const File = std.fs.File; | 12 | const File = std.fs.File; |
| 12 | const tmpDir = testing.tmpDir; | 13 | const tmpDir = testing.tmpDir; |
| 13 | 14 | ||
| ... | @@ -168,20 +169,20 @@ test "Dir.Iterator" { | ... | @@ -168,20 +169,20 @@ test "Dir.Iterator" { |
| 168 | defer arena.deinit(); | 169 | defer arena.deinit(); |
| 169 | const allocator = arena.allocator(); | 170 | const allocator = arena.allocator(); |
| 170 | 171 | ||
| 171 | var entries = std.ArrayList(Dir.Entry).init(allocator); | 172 | var entries = std.ArrayList(IterableDir.Entry).init(allocator); |
| 172 | 173 | ||
| 173 | // Create iterator. | 174 | // Create iterator. |
| 174 | var iter = tmp_dir.dir.iterate(); | 175 | var iter = tmp_dir.dir.intoIterable().iterate(); |
| 175 | while (try iter.next()) |entry| { | 176 | while (try iter.next()) |entry| { |
| 176 | // We cannot just store `entry` as on Windows, we're re-using the name buffer | 177 | // We cannot just store `entry` as on Windows, we're re-using the name buffer |
| 177 | // which means we'll actually share the `name` pointer between entries! | 178 | // which means we'll actually share the `name` pointer between entries! |
| 178 | const name = try allocator.dupe(u8, entry.name); | 179 | const name = try allocator.dupe(u8, entry.name); |
| 179 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); | 180 | try entries.append(.{ .name = name, .kind = entry.kind }); |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 182 | try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..' | 183 | try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..' |
| 183 | try testing.expect(contains(&entries, Dir.Entry{ .name = "some_file", .kind = Dir.Entry.Kind.File })); | 184 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File })); |
| 184 | try testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory })); | 185 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory })); |
| 185 | } | 186 | } |
| 186 | 187 | ||
| 187 | test "Dir.Iterator twice" { | 188 | test "Dir.Iterator twice" { |
| ... | @@ -200,28 +201,28 @@ test "Dir.Iterator twice" { | ... | @@ -200,28 +201,28 @@ test "Dir.Iterator twice" { |
| 200 | 201 | ||
| 201 | var i: u8 = 0; | 202 | var i: u8 = 0; |
| 202 | while (i < 2) : (i += 1) { | 203 | while (i < 2) : (i += 1) { |
| 203 | var entries = std.ArrayList(Dir.Entry).init(allocator); | 204 | var entries = std.ArrayList(IterableDir.Entry).init(allocator); |
| 204 | 205 | ||
| 205 | // Create iterator. | 206 | // Create iterator. |
| 206 | var iter = tmp_dir.dir.iterate(); | 207 | var iter = tmp_dir.dir.intoIterable().iterate(); |
| 207 | while (try iter.next()) |entry| { | 208 | while (try iter.next()) |entry| { |
| 208 | // We cannot just store `entry` as on Windows, we're re-using the name buffer | 209 | // We cannot just store `entry` as on Windows, we're re-using the name buffer |
| 209 | // which means we'll actually share the `name` pointer between entries! | 210 | // which means we'll actually share the `name` pointer between entries! |
| 210 | const name = try allocator.dupe(u8, entry.name); | 211 | const name = try allocator.dupe(u8, entry.name); |
| 211 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); | 212 | try entries.append(.{ .name = name, .kind = entry.kind }); |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 214 | try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..' | 215 | try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..' |
| 215 | try testing.expect(contains(&entries, Dir.Entry{ .name = "some_file", .kind = Dir.Entry.Kind.File })); | 216 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File })); |
| 216 | try testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory })); | 217 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory })); |
| 217 | } | 218 | } |
| 218 | } | 219 | } |
| 219 | 220 | ||
| 220 | fn entryEql(lhs: Dir.Entry, rhs: Dir.Entry) bool { | 221 | fn entryEql(lhs: IterableDir.Entry, rhs: IterableDir.Entry) bool { |
| 221 | return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind; | 222 | return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind; |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | fn contains(entries: *const std.ArrayList(Dir.Entry), el: Dir.Entry) bool { | 225 | fn contains(entries: *const std.ArrayList(IterableDir.Entry), el: IterableDir.Entry) bool { |
| 225 | for (entries.items) |entry| { | 226 | for (entries.items) |entry| { |
| 226 | if (entryEql(entry, el)) return true; | 227 | if (entryEql(entry, el)) return true; |
| 227 | } | 228 | } |
| ... | @@ -1014,7 +1015,7 @@ test "walker" { | ... | @@ -1014,7 +1015,7 @@ test "walker" { |
| 1014 | try tmp.dir.makePath(kv.key); | 1015 | try tmp.dir.makePath(kv.key); |
| 1015 | } | 1016 | } |
| 1016 | 1017 | ||
| 1017 | var walker = try tmp.dir.walk(testing.allocator); | 1018 | var walker = try tmp.dir.intoIterable().walk(testing.allocator); |
| 1018 | defer walker.deinit(); | 1019 | defer walker.deinit(); |
| 1019 | 1020 | ||
| 1020 | var num_walked: usize = 0; | 1021 | var num_walked: usize = 0; |
| ... | @@ -1121,11 +1122,11 @@ test "chmod" { | ... | @@ -1121,11 +1122,11 @@ test "chmod" { |
| 1121 | try testing.expect((try file.stat()).mode & 0o7777 == 0o644); | 1122 | try testing.expect((try file.stat()).mode & 0o7777 == 0o644); |
| 1122 | 1123 | ||
| 1123 | try tmp.dir.makeDir("test_dir"); | 1124 | try tmp.dir.makeDir("test_dir"); |
| 1124 | var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); | 1125 | var iterable_dir = try tmp.dir.openIterableDir("test_dir", .{}); |
| 1125 | defer dir.close(); | 1126 | defer iterable_dir.close(); |
| 1126 | 1127 | ||
| 1127 | try dir.chmod(0o700); | 1128 | try iterable_dir.chmod(0o700); |
| 1128 | try testing.expect((try dir.stat()).mode & 0o7777 == 0o700); | 1129 | try testing.expect((try iterable_dir.stat()).mode & 0o7777 == 0o700); |
| 1129 | } | 1130 | } |
| 1130 | 1131 | ||
| 1131 | test "chown" { | 1132 | test "chown" { |
| ... | @@ -1141,9 +1142,9 @@ test "chown" { | ... | @@ -1141,9 +1142,9 @@ test "chown" { |
| 1141 | 1142 | ||
| 1142 | try tmp.dir.makeDir("test_dir"); | 1143 | try tmp.dir.makeDir("test_dir"); |
| 1143 | 1144 | ||
| 1144 | var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); | 1145 | var iterable_dir = try tmp.dir.openDir("test_dir", .{}); |
| 1145 | defer dir.close(); | 1146 | defer iterable_dir.close(); |
| 1146 | try dir.chown(null, null); | 1147 | try iterable_dir.chown(null, null); |
| 1147 | } | 1148 | } |
| 1148 | 1149 | ||
| 1149 | test "File.Metadata" { | 1150 | test "File.Metadata" { |
src/main.zig+6-6| ... | @@ -4206,13 +4206,13 @@ fn fmtPathDir( | ... | @@ -4206,13 +4206,13 @@ fn fmtPathDir( |
| 4206 | parent_dir: fs.Dir, | 4206 | parent_dir: fs.Dir, |
| 4207 | parent_sub_path: []const u8, | 4207 | parent_sub_path: []const u8, |
| 4208 | ) FmtError!void { | 4208 | ) FmtError!void { |
| 4209 | var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); | 4209 | var iterable_dir = try parent_dir.openIterableDir(parent_sub_path, .{}); |
| 4210 | defer dir.close(); | 4210 | defer iterable_dir.close(); |
| 4211 | 4211 | ||
| 4212 | const stat = try dir.stat(); | 4212 | const stat = try iterable_dir.dir.stat(); |
| 4213 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; | 4213 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; |
| 4214 | 4214 | ||
| 4215 | var dir_it = dir.iterate(); | 4215 | var dir_it = iterable_dir.iterate(); |
| 4216 | while (try dir_it.next()) |entry| { | 4216 | while (try dir_it.next()) |entry| { |
| 4217 | const is_dir = entry.kind == .Directory; | 4217 | const is_dir = entry.kind == .Directory; |
| 4218 | 4218 | ||
| ... | @@ -4223,9 +4223,9 @@ fn fmtPathDir( | ... | @@ -4223,9 +4223,9 @@ fn fmtPathDir( |
| 4223 | defer fmt.gpa.free(full_path); | 4223 | defer fmt.gpa.free(full_path); |
| 4224 | 4224 | ||
| 4225 | if (is_dir) { | 4225 | if (is_dir) { |
| 4226 | try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); | 4226 | try fmtPathDir(fmt, full_path, check_mode, iterable_dir.dir, entry.name); |
| 4227 | } else { | 4227 | } else { |
| 4228 | fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { | 4228 | fmtPathFile(fmt, full_path, check_mode, iterable_dir.dir, entry.name) catch |err| { |
| 4229 | warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); | 4229 | warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); |
| 4230 | fmt.any_error = true; | 4230 | fmt.any_error = true; |
| 4231 | return; | 4231 | return; |
src/test.zig+1-1| ... | @@ -1096,7 +1096,7 @@ pub const TestContext = struct { | ... | @@ -1096,7 +1096,7 @@ pub const TestContext = struct { |
| 1096 | /// that if any errors occur the caller knows it happened during this file. | 1096 | /// that if any errors occur the caller knows it happened during this file. |
| 1097 | current_file: *[]const u8, | 1097 | current_file: *[]const u8, |
| 1098 | ) !void { | 1098 | ) !void { |
| 1099 | var it = try dir.walk(ctx.arena); | 1099 | var it = try dir.intoIterable().walk(ctx.arena); |
| 1100 | var filenames = std.ArrayList([]const u8).init(ctx.arena); | 1100 | var filenames = std.ArrayList([]const u8).init(ctx.arena); |
| 1101 | 1101 | ||
| 1102 | while (try it.next()) |entry| { | 1102 | while (try it.next()) |entry| { |
tools/process_headers.zig+3-3| ... | @@ -381,14 +381,14 @@ pub fn main() !void { | ... | @@ -381,14 +381,14 @@ pub fn main() !void { |
| 381 | try dir_stack.append(target_include_dir); | 381 | try dir_stack.append(target_include_dir); |
| 382 | 382 | ||
| 383 | while (dir_stack.popOrNull()) |full_dir_name| { | 383 | while (dir_stack.popOrNull()) |full_dir_name| { |
| 384 | var dir = std.fs.cwd().openDir(full_dir_name, .{ .iterate = true }) catch |err| switch (err) { | 384 | var iterable_dir = std.fs.cwd().openIterableDir(full_dir_name, .{}) catch |err| switch (err) { |
| 385 | error.FileNotFound => continue :search, | 385 | error.FileNotFound => continue :search, |
| 386 | error.AccessDenied => continue :search, | 386 | error.AccessDenied => continue :search, |
| 387 | else => return err, | 387 | else => return err, |
| 388 | }; | 388 | }; |
| 389 | defer dir.close(); | 389 | defer iterable_dir.close(); |
| 390 | 390 | ||
| 391 | var dir_it = dir.iterate(); | 391 | var dir_it = iterable_dir.iterate(); |
| 392 | 392 | ||
| 393 | while (try dir_it.next()) |entry| { | 393 | while (try dir_it.next()) |entry| { |
| 394 | const full_path = try std.fs.path.join(allocator, &[_][]const u8{ full_dir_name, entry.name }); | 394 | const full_path = try std.fs.path.join(allocator, &[_][]const u8{ full_dir_name, entry.name }); |
tools/update-license-headers.zig+4-4| ... | @@ -14,9 +14,9 @@ pub fn main() !void { | ... | @@ -14,9 +14,9 @@ pub fn main() !void { |
| 14 | 14 | ||
| 15 | const args = try std.process.argsAlloc(arena); | 15 | const args = try std.process.argsAlloc(arena); |
| 16 | const path_to_walk = args[1]; | 16 | const path_to_walk = args[1]; |
| 17 | const dir = try std.fs.cwd().openDir(path_to_walk, .{ .iterate = true }); | 17 | const iterable_dir = try std.fs.cwd().openIterableDir(path_to_walk, .{}); |
| 18 | 18 | ||
| 19 | var walker = try dir.walk(arena); | 19 | var walker = try iterable_dir.walk(arena); |
| 20 | defer walker.deinit(); | 20 | defer walker.deinit(); |
| 21 | 21 | ||
| 22 | var buffer: [500]u8 = undefined; | 22 | var buffer: [500]u8 = undefined; |
| ... | @@ -30,7 +30,7 @@ pub fn main() !void { | ... | @@ -30,7 +30,7 @@ pub fn main() !void { |
| 30 | node.activate(); | 30 | node.activate(); |
| 31 | defer node.end(); | 31 | defer node.end(); |
| 32 | 32 | ||
| 33 | const source = try dir.readFileAlloc(arena, entry.path, 20 * 1024 * 1024); | 33 | const source = try iterable_dir.dir.readFileAlloc(arena, entry.path, 20 * 1024 * 1024); |
| 34 | if (!std.mem.startsWith(u8, source, expected_header)) { | 34 | if (!std.mem.startsWith(u8, source, expected_header)) { |
| 35 | std.debug.print("no match: {s}\n", .{entry.path}); | 35 | std.debug.print("no match: {s}\n", .{entry.path}); |
| 36 | continue; | 36 | continue; |
| ... | @@ -42,6 +42,6 @@ pub fn main() !void { | ... | @@ -42,6 +42,6 @@ pub fn main() !void { |
| 42 | std.mem.copy(u8, new_source, new_header); | 42 | std.mem.copy(u8, new_source, new_header); |
| 43 | std.mem.copy(u8, new_source[new_header.len..], truncated_source); | 43 | std.mem.copy(u8, new_source[new_header.len..], truncated_source); |
| 44 | 44 | ||
| 45 | try dir.writeFile(entry.path, new_source); | 45 | try iterable_dir.dir.writeFile(entry.path, new_source); |
| 46 | } | 46 | } |
| 47 | } | 47 | } |
tools/update-linux-headers.zig+3-3| ... | @@ -181,14 +181,14 @@ pub fn main() !void { | ... | @@ -181,14 +181,14 @@ pub fn main() !void { |
| 181 | try dir_stack.append(target_include_dir); | 181 | try dir_stack.append(target_include_dir); |
| 182 | 182 | ||
| 183 | while (dir_stack.popOrNull()) |full_dir_name| { | 183 | while (dir_stack.popOrNull()) |full_dir_name| { |
| 184 | var dir = std.fs.cwd().openDir(full_dir_name, .{ .iterate = true }) catch |err| switch (err) { | 184 | var iterable_dir = std.fs.cwd().openIterableDir(full_dir_name, .{}) catch |err| switch (err) { |
| 185 | error.FileNotFound => continue :search, | 185 | error.FileNotFound => continue :search, |
| 186 | error.AccessDenied => continue :search, | 186 | error.AccessDenied => continue :search, |
| 187 | else => return err, | 187 | else => return err, |
| 188 | }; | 188 | }; |
| 189 | defer dir.close(); | 189 | defer iterable_dir.close(); |
| 190 | 190 | ||
| 191 | var dir_it = dir.iterate(); | 191 | var dir_it = iterable_dir.iterate(); |
| 192 | 192 | ||
| 193 | while (try dir_it.next()) |entry| { | 193 | while (try dir_it.next()) |entry| { |
| 194 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ full_dir_name, entry.name }); | 194 | const full_path = try std.fs.path.join(arena, &[_][]const u8{ full_dir_name, entry.name }); |
tools/update_glibc.zig+5-5| ... | @@ -41,7 +41,7 @@ pub fn main() !void { | ... | @@ -41,7 +41,7 @@ pub fn main() !void { |
| 41 | 41 | ||
| 42 | const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/glibc", .{zig_src_path}); | 42 | const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/glibc", .{zig_src_path}); |
| 43 | 43 | ||
| 44 | var dest_dir = fs.cwd().openDir(dest_dir_path, .{ .iterate = true }) catch |err| { | 44 | var dest_dir = fs.cwd().openIterableDir(dest_dir_path, .{}) catch |err| { |
| 45 | fatal("unable to open destination directory '{s}': {s}", .{ | 45 | fatal("unable to open destination directory '{s}': {s}", .{ |
| 46 | dest_dir_path, @errorName(err), | 46 | dest_dir_path, @errorName(err), |
| 47 | }); | 47 | }); |
| ... | @@ -63,14 +63,14 @@ pub fn main() !void { | ... | @@ -63,14 +63,14 @@ pub fn main() !void { |
| 63 | if (mem.eql(u8, entry.path, p)) continue :walk; | 63 | if (mem.eql(u8, entry.path, p)) continue :walk; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | glibc_src_dir.copyFile(entry.path, dest_dir, entry.path, .{}) catch |err| { | 66 | glibc_src_dir.copyFile(entry.path, dest_dir.dir, entry.path, .{}) catch |err| { |
| 67 | log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{ | 67 | log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{ |
| 68 | glibc_src_path, entry.path, | 68 | glibc_src_path, entry.path, |
| 69 | dest_dir_path, entry.path, | 69 | dest_dir_path, entry.path, |
| 70 | @errorName(err), | 70 | @errorName(err), |
| 71 | }); | 71 | }); |
| 72 | if (err == error.FileNotFound) { | 72 | if (err == error.FileNotFound) { |
| 73 | try dest_dir.deleteFile(entry.path); | 73 | try dest_dir.dir.deleteFile(entry.path); |
| 74 | } | 74 | } |
| 75 | }; | 75 | }; |
| 76 | } | 76 | } |
| ... | @@ -79,7 +79,7 @@ pub fn main() !void { | ... | @@ -79,7 +79,7 @@ pub fn main() !void { |
| 79 | // Warn about duplicated files inside glibc/include/* that can be omitted | 79 | // Warn about duplicated files inside glibc/include/* that can be omitted |
| 80 | // because they are already in generic-glibc/*. | 80 | // because they are already in generic-glibc/*. |
| 81 | 81 | ||
| 82 | var include_dir = dest_dir.openDir("include", .{ .iterate = true }) catch |err| { | 82 | var include_dir = dest_dir.dir.openIterableDir("include", .{}) catch |err| { |
| 83 | fatal("unable to open directory '{s}/include': {s}", .{ | 83 | fatal("unable to open directory '{s}/include': {s}", .{ |
| 84 | dest_dir_path, @errorName(err), | 84 | dest_dir_path, @errorName(err), |
| 85 | }); | 85 | }); |
| ... | @@ -116,7 +116,7 @@ pub fn main() !void { | ... | @@ -116,7 +116,7 @@ pub fn main() !void { |
| 116 | generic_glibc_path, entry.path, @errorName(e), | 116 | generic_glibc_path, entry.path, @errorName(e), |
| 117 | }), | 117 | }), |
| 118 | }; | 118 | }; |
| 119 | const glibc_include_contents = include_dir.readFileAlloc( | 119 | const glibc_include_contents = include_dir.dir.readFileAlloc( |
| 120 | arena, | 120 | arena, |
| 121 | entry.path, | 121 | entry.path, |
| 122 | max_file_size, | 122 | max_file_size, |
tools/update_spirv_features.zig+3-3| ... | @@ -218,7 +218,7 @@ pub fn main() !void { | ... | @@ -218,7 +218,7 @@ pub fn main() !void { |
| 218 | /// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies. | 218 | /// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies. |
| 219 | fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]const []const u8 { | 219 | fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]const []const u8 { |
| 220 | const extensions_path = try fs.path.join(allocator, &.{ spirv_registry_root, "extensions" }); | 220 | const extensions_path = try fs.path.join(allocator, &.{ spirv_registry_root, "extensions" }); |
| 221 | var extensions_dir = try fs.cwd().openDir(extensions_path, .{ .iterate = true }); | 221 | var extensions_dir = try fs.cwd().openIterableDir(extensions_path, .{}); |
| 222 | defer extensions_dir.close(); | 222 | defer extensions_dir.close(); |
| 223 | 223 | ||
| 224 | var extensions = std.ArrayList([]const u8).init(allocator); | 224 | var extensions = std.ArrayList([]const u8).init(allocator); |
| ... | @@ -227,7 +227,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c | ... | @@ -227,7 +227,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c |
| 227 | while (try vendor_it.next()) |vendor_entry| { | 227 | while (try vendor_it.next()) |vendor_entry| { |
| 228 | std.debug.assert(vendor_entry.kind == .Directory); // If this fails, the structure of SPIRV-Registry has changed. | 228 | std.debug.assert(vendor_entry.kind == .Directory); // If this fails, the structure of SPIRV-Registry has changed. |
| 229 | 229 | ||
| 230 | const vendor_dir = try extensions_dir.openDir(vendor_entry.name, .{ .iterate = true }); | 230 | const vendor_dir = try extensions_dir.dir.openIterableDir(vendor_entry.name, .{}); |
| 231 | var ext_it = vendor_dir.iterate(); | 231 | var ext_it = vendor_dir.iterate(); |
| 232 | while (try ext_it.next()) |ext_entry| { | 232 | while (try ext_it.next()) |ext_entry| { |
| 233 | // There is both a HTML and asciidoc version of every spec (as well as some other directories), | 233 | // There is both a HTML and asciidoc version of every spec (as well as some other directories), |
| ... | @@ -250,7 +250,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c | ... | @@ -250,7 +250,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c |
| 250 | // SPV_EXT_name | 250 | // SPV_EXT_name |
| 251 | // ``` | 251 | // ``` |
| 252 | 252 | ||
| 253 | const ext_spec = try vendor_dir.readFileAlloc(allocator, ext_entry.name, std.math.maxInt(usize)); | 253 | const ext_spec = try vendor_dir.dir.readFileAlloc(allocator, ext_entry.name, std.math.maxInt(usize)); |
| 254 | const name_strings = "Name Strings"; | 254 | const name_strings = "Name Strings"; |
| 255 | 255 | ||
| 256 | const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry; | 256 | const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry; |