authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-09 18:59:21+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-15 13:04:21+03:00
log2b67f56c35d0a61be43f8ca23535096ae3ca4948
tree591eea9b6dce8bc4e0a524993da208515b109f92
parent577f9fdbae12eabbbf87bd2cc36a1565df3153b2

std.fs: split `Dir` into `IterableDir`

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 {
32453245 const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n");
32463246
32473247 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, .{});
32493249 defer src_dir.close();
32503250
32513251 // Create the output directory if it doesn't exist.
......@@ -3265,7 +3265,7 @@ pub const LibExeObjStep = struct {
32653265 mem.eql(u8, entry.name, "zld.id") or
32663266 mem.eql(u8, entry.name, "lld.id")) continue;
32673267
3268 _ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{});
3268 _ = try src_dir.dir.updateFile(entry.name, dest_dir, entry.name, .{});
32693269 }
32703270 } else {
32713271 self.output_dir = build_output_dir;
......@@ -3480,7 +3480,7 @@ pub const InstallDirStep = struct {
34803480 const self = @fieldParentPtr(InstallDirStep, "step", step);
34813481 const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir);
34823482 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, .{});
34843484 defer src_dir.close();
34853485 var it = try src_dir.walk(self.builder.allocator);
34863486 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_
283283 return os.renameatW(old_dir.fd, old_sub_path_w, new_dir.fd, new_sub_path_w);
284284}
285285
286pub const Dir = struct {
287 fd: os.fd_t,
286/// A directory that can be iterated. It is *NOT* legal to initialize this with a regular `Dir`
287/// that has been opened without iteration permission.
288pub const IterableDir = struct {
289 dir: Dir,
288290
289291 pub const Entry = struct {
290292 name: []const u8,
......@@ -779,7 +781,7 @@ pub const Dir = struct {
779781 else => @compileError("unimplemented"),
780782 };
781783
782 pub fn iterate(self: Dir) Iterator {
784 pub fn iterate(self: IterableDir) Iterator {
783785 switch (builtin.os.tag) {
784786 .macos,
785787 .ios,
......@@ -789,7 +791,7 @@ pub const Dir = struct {
789791 .openbsd,
790792 .solaris,
791793 => return Iterator{
792 .dir = self,
794 .dir = self.dir,
793795 .seek = 0,
794796 .index = 0,
795797 .end_index = 0,
......@@ -797,14 +799,14 @@ pub const Dir = struct {
797799 .first_iter = true,
798800 },
799801 .linux, .haiku => return Iterator{
800 .dir = self,
802 .dir = self.dir,
801803 .index = 0,
802804 .end_index = 0,
803805 .buf = undefined,
804806 .first_iter = true,
805807 },
806808 .windows => return Iterator{
807 .dir = self,
809 .dir = self.dir,
808810 .index = 0,
809811 .end_index = 0,
810812 .first_iter = true,
......@@ -812,7 +814,7 @@ pub const Dir = struct {
812814 .name_data = undefined,
813815 },
814816 .wasi => return Iterator{
815 .dir = self,
817 .dir = self.dir,
816818 .cookie = os.wasi.DIRCOOKIE_START,
817819 .index = 0,
818820 .end_index = 0,
......@@ -833,11 +835,11 @@ pub const Dir = struct {
833835 dir: Dir,
834836 basename: []const u8,
835837 path: []const u8,
836 kind: Dir.Entry.Kind,
838 kind: IterableDir.Entry.Kind,
837839 };
838840
839841 const StackItem = struct {
840 iter: Dir.Iterator,
842 iter: IterableDir.Iterator,
841843 dirname_len: usize,
842844 };
843845
......@@ -857,7 +859,7 @@ pub const Dir = struct {
857859 }
858860 try self.name_buffer.appendSlice(base.name);
859861 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) {
861863 error.NameTooLong => unreachable, // no path sep in base.name
862864 else => |e| return e,
863865 };
......@@ -896,11 +898,10 @@ pub const Dir = struct {
896898 };
897899
898900 /// Recursively iterates over a directory.
899 /// `self` must have been opened with `OpenDirOptions{.iterate = true}`.
900901 /// Must call `Walker.deinit` when done.
901902 /// The order of returned file system entries is undefined.
902903 /// `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 {
904905 var name_buffer = std.ArrayList(u8).init(allocator);
905906 errdefer name_buffer.deinit();
906907
......@@ -918,6 +919,52 @@ pub const Dir = struct {
918919 };
919920 }
920921
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
957pub 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
921968 pub const OpenError = error{
922969 FileNotFound,
923970 NotDir,
......@@ -1507,6 +1554,26 @@ pub const Dir = struct {
15071554 }
15081555 }
15091556
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
15101577 /// Same as `openDir` except only WASI.
15111578 pub fn openDirWasi(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {
15121579 const w = os.wasi;
......@@ -1552,7 +1619,7 @@ pub const Dir = struct {
15521619 error.FileBusy => unreachable, // can't happen for directories
15531620 else => |e| return e,
15541621 };
1555 return Dir{ .fd = fd };
1622 return Dir{ .fd = fd, .iterable = if (builtin.mode == .Debug) args.iterate else {} };
15561623 }
15571624
15581625 /// Same as `openDir` except the parameter is null-terminated.
......@@ -1566,7 +1633,9 @@ pub const Dir = struct {
15661633 const O_PATH = if (@hasDecl(os.O, "PATH")) os.O.PATH else 0;
15671634 return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | O_PATH | symlink_flags);
15681635 } 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;
15701639 }
15711640 }
15721641
......@@ -1578,7 +1647,9 @@ pub const Dir = struct {
15781647 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
15791648 w.SYNCHRONIZE | w.FILE_TRAVERSE;
15801649 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;
15821653 }
15831654
15841655 /// `flags` must contain `os.O.DIRECTORY`.
......@@ -1958,7 +2029,7 @@ pub const Dir = struct {
19582029 error.Unexpected,
19592030 => |e| return e,
19602031 }
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) {
19622033 error.NotDir => {
19632034 if (got_access_denied) {
19642035 return error.AccessDenied;
......@@ -1984,11 +2055,11 @@ pub const Dir = struct {
19842055 error.DeviceBusy,
19852056 => |e| return e,
19862057 };
1987 var cleanup_dir_parent: ?Dir = null;
2058 var cleanup_dir_parent: ?IterableDir = null;
19882059 defer if (cleanup_dir_parent) |*d| d.close();
19892060
19902061 var cleanup_dir = true;
1991 defer if (cleanup_dir) dir.close();
2062 defer if (cleanup_dir) iterable_dir.close();
19922063
19932064 // Valid use of MAX_PATH_BYTES because dir_name_buf will only
19942065 // ever store a single path component that was returned from the
......@@ -2001,9 +2072,9 @@ pub const Dir = struct {
20012072 // open it, and close the original directory. Repeat. Then start the entire operation over.
20022073
20032074 scan_dir: while (true) {
2004 var dir_it = dir.iterate();
2075 var dir_it = iterable_dir.iterate();
20052076 while (try dir_it.next()) |entry| {
2006 if (dir.deleteFile(entry.name)) {
2077 if (iterable_dir.dir.deleteFile(entry.name)) {
20072078 continue;
20082079 } else |err| switch (err) {
20092080 error.FileNotFound => continue,
......@@ -2026,7 +2097,7 @@ pub const Dir = struct {
20262097 => |e| return e,
20272098 }
20282099
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) {
20302101 error.NotDir => {
20312102 if (got_access_denied) {
20322103 return error.AccessDenied;
......@@ -2053,19 +2124,19 @@ pub const Dir = struct {
20532124 => |e| return e,
20542125 };
20552126 if (cleanup_dir_parent) |*d| d.close();
2056 cleanup_dir_parent = dir;
2057 dir = new_dir;
2127 cleanup_dir_parent = iterable_dir;
2128 iterable_dir = new_dir;
20582129 mem.copy(u8, &dir_name_buf, entry.name);
20592130 dir_name = dir_name_buf[0..entry.name.len];
20602131 continue :scan_dir;
20612132 }
20622133 // Reached the end of the directory entries, which means we successfully deleted all of them.
20632134 // Now to remove the directory itself.
2064 dir.close();
2135 iterable_dir.close();
20652136 cleanup_dir = false;
20662137
20672138 if (cleanup_dir_parent) |d| {
2068 d.deleteDir(dir_name) catch |err| switch (err) {
2139 d.dir.deleteDir(dir_name) catch |err| switch (err) {
20692140 // These two things can happen due to file system race conditions.
20702141 error.FileNotFound, error.DirNotEmpty => continue :start_over,
20712142 else => |e| return e,
......@@ -2246,37 +2317,6 @@ pub const Dir = struct {
22462317 return file.stat();
22472318 }
22482319
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
22802320 const Permissions = File.Permissions;
22812321 pub const SetPermissionsError = File.SetPermissionsError;
22822322
lib/std/fs/test.zig+21-20
......@@ -8,6 +8,7 @@ const wasi = std.os.wasi;
88
99const ArenaAllocator = std.heap.ArenaAllocator;
1010const Dir = std.fs.Dir;
11const IterableDir = std.fs.IterableDir;
1112const File = std.fs.File;
1213const tmpDir = testing.tmpDir;
1314
......@@ -168,20 +169,20 @@ test "Dir.Iterator" {
168169 defer arena.deinit();
169170 const allocator = arena.allocator();
170171
171 var entries = std.ArrayList(Dir.Entry).init(allocator);
172 var entries = std.ArrayList(IterableDir.Entry).init(allocator);
172173
173174 // Create iterator.
174 var iter = tmp_dir.dir.iterate();
175 var iter = tmp_dir.dir.intoIterable().iterate();
175176 while (try iter.next()) |entry| {
176177 // We cannot just store `entry` as on Windows, we're re-using the name buffer
177178 // which means we'll actually share the `name` pointer between entries!
178179 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 });
180181 }
181182
182183 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, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory }));
184 try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File }));
185 try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory }));
185186}
186187
187188test "Dir.Iterator twice" {
......@@ -200,28 +201,28 @@ test "Dir.Iterator twice" {
200201
201202 var i: u8 = 0;
202203 while (i < 2) : (i += 1) {
203 var entries = std.ArrayList(Dir.Entry).init(allocator);
204 var entries = std.ArrayList(IterableDir.Entry).init(allocator);
204205
205206 // Create iterator.
206 var iter = tmp_dir.dir.iterate();
207 var iter = tmp_dir.dir.intoIterable().iterate();
207208 while (try iter.next()) |entry| {
208209 // We cannot just store `entry` as on Windows, we're re-using the name buffer
209210 // which means we'll actually share the `name` pointer between entries!
210211 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 });
212213 }
213214
214215 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, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory }));
216 try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .File }));
217 try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .Directory }));
217218 }
218219}
219220
220fn entryEql(lhs: Dir.Entry, rhs: Dir.Entry) bool {
221fn entryEql(lhs: IterableDir.Entry, rhs: IterableDir.Entry) bool {
221222 return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind;
222223}
223224
224fn contains(entries: *const std.ArrayList(Dir.Entry), el: Dir.Entry) bool {
225fn contains(entries: *const std.ArrayList(IterableDir.Entry), el: IterableDir.Entry) bool {
225226 for (entries.items) |entry| {
226227 if (entryEql(entry, el)) return true;
227228 }
......@@ -1014,7 +1015,7 @@ test "walker" {
10141015 try tmp.dir.makePath(kv.key);
10151016 }
10161017
1017 var walker = try tmp.dir.walk(testing.allocator);
1018 var walker = try tmp.dir.intoIterable().walk(testing.allocator);
10181019 defer walker.deinit();
10191020
10201021 var num_walked: usize = 0;
......@@ -1121,11 +1122,11 @@ test "chmod" {
11211122 try testing.expect((try file.stat()).mode & 0o7777 == 0o644);
11221123
11231124 try tmp.dir.makeDir("test_dir");
1124 var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true });
1125 defer dir.close();
1125 var iterable_dir = try tmp.dir.openIterableDir("test_dir", .{});
1126 defer iterable_dir.close();
11261127
1127 try dir.chmod(0o700);
1128 try testing.expect((try dir.stat()).mode & 0o7777 == 0o700);
1128 try iterable_dir.chmod(0o700);
1129 try testing.expect((try iterable_dir.stat()).mode & 0o7777 == 0o700);
11291130}
11301131
11311132test "chown" {
......@@ -1141,9 +1142,9 @@ test "chown" {
11411142
11421143 try tmp.dir.makeDir("test_dir");
11431144
1144 var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true });
1145 defer dir.close();
1146 try dir.chown(null, null);
1145 var iterable_dir = try tmp.dir.openDir("test_dir", .{});
1146 defer iterable_dir.close();
1147 try iterable_dir.chown(null, null);
11471148}
11481149
11491150test "File.Metadata" {
src/main.zig+6-6
......@@ -4206,13 +4206,13 @@ fn fmtPathDir(
42064206 parent_dir: fs.Dir,
42074207 parent_sub_path: []const u8,
42084208) FmtError!void {
4209 var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
4210 defer dir.close();
4209 var iterable_dir = try parent_dir.openIterableDir(parent_sub_path, .{});
4210 defer iterable_dir.close();
42114211
4212 const stat = try dir.stat();
4212 const stat = try iterable_dir.dir.stat();
42134213 if (try fmt.seen.fetchPut(stat.inode, {})) |_| return;
42144214
4215 var dir_it = dir.iterate();
4215 var dir_it = iterable_dir.iterate();
42164216 while (try dir_it.next()) |entry| {
42174217 const is_dir = entry.kind == .Directory;
42184218
......@@ -4223,9 +4223,9 @@ fn fmtPathDir(
42234223 defer fmt.gpa.free(full_path);
42244224
42254225 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);
42274227 } 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| {
42294229 warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) });
42304230 fmt.any_error = true;
42314231 return;
src/test.zig+1-1
......@@ -1096,7 +1096,7 @@ pub const TestContext = struct {
10961096 /// that if any errors occur the caller knows it happened during this file.
10971097 current_file: *[]const u8,
10981098 ) !void {
1099 var it = try dir.walk(ctx.arena);
1099 var it = try dir.intoIterable().walk(ctx.arena);
11001100 var filenames = std.ArrayList([]const u8).init(ctx.arena);
11011101
11021102 while (try it.next()) |entry| {
tools/process_headers.zig+3-3
......@@ -381,14 +381,14 @@ pub fn main() !void {
381381 try dir_stack.append(target_include_dir);
382382
383383 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) {
385385 error.FileNotFound => continue :search,
386386 error.AccessDenied => continue :search,
387387 else => return err,
388388 };
389 defer dir.close();
389 defer iterable_dir.close();
390390
391 var dir_it = dir.iterate();
391 var dir_it = iterable_dir.iterate();
392392
393393 while (try dir_it.next()) |entry| {
394394 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 {
1414
1515 const args = try std.process.argsAlloc(arena);
1616 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, .{});
1818
19 var walker = try dir.walk(arena);
19 var walker = try iterable_dir.walk(arena);
2020 defer walker.deinit();
2121
2222 var buffer: [500]u8 = undefined;
......@@ -30,7 +30,7 @@ pub fn main() !void {
3030 node.activate();
3131 defer node.end();
3232
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);
3434 if (!std.mem.startsWith(u8, source, expected_header)) {
3535 std.debug.print("no match: {s}\n", .{entry.path});
3636 continue;
......@@ -42,6 +42,6 @@ pub fn main() !void {
4242 std.mem.copy(u8, new_source, new_header);
4343 std.mem.copy(u8, new_source[new_header.len..], truncated_source);
4444
45 try dir.writeFile(entry.path, new_source);
45 try iterable_dir.dir.writeFile(entry.path, new_source);
4646 }
4747}
tools/update-linux-headers.zig+3-3
......@@ -181,14 +181,14 @@ pub fn main() !void {
181181 try dir_stack.append(target_include_dir);
182182
183183 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) {
185185 error.FileNotFound => continue :search,
186186 error.AccessDenied => continue :search,
187187 else => return err,
188188 };
189 defer dir.close();
189 defer iterable_dir.close();
190190
191 var dir_it = dir.iterate();
191 var dir_it = iterable_dir.iterate();
192192
193193 while (try dir_it.next()) |entry| {
194194 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 {
4141
4242 const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/glibc", .{zig_src_path});
4343
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| {
4545 fatal("unable to open destination directory '{s}': {s}", .{
4646 dest_dir_path, @errorName(err),
4747 });
......@@ -63,14 +63,14 @@ pub fn main() !void {
6363 if (mem.eql(u8, entry.path, p)) continue :walk;
6464 }
6565
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| {
6767 log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{
6868 glibc_src_path, entry.path,
6969 dest_dir_path, entry.path,
7070 @errorName(err),
7171 });
7272 if (err == error.FileNotFound) {
73 try dest_dir.deleteFile(entry.path);
73 try dest_dir.dir.deleteFile(entry.path);
7474 }
7575 };
7676 }
......@@ -79,7 +79,7 @@ pub fn main() !void {
7979 // Warn about duplicated files inside glibc/include/* that can be omitted
8080 // because they are already in generic-glibc/*.
8181
82 var include_dir = dest_dir.openDir("include", .{ .iterate = true }) catch |err| {
82 var include_dir = dest_dir.dir.openIterableDir("include", .{}) catch |err| {
8383 fatal("unable to open directory '{s}/include': {s}", .{
8484 dest_dir_path, @errorName(err),
8585 });
......@@ -116,7 +116,7 @@ pub fn main() !void {
116116 generic_glibc_path, entry.path, @errorName(e),
117117 }),
118118 };
119 const glibc_include_contents = include_dir.readFileAlloc(
119 const glibc_include_contents = include_dir.dir.readFileAlloc(
120120 arena,
121121 entry.path,
122122 max_file_size,
tools/update_spirv_features.zig+3-3
......@@ -218,7 +218,7 @@ pub fn main() !void {
218218/// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies.
219219fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]const []const u8 {
220220 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, .{});
222222 defer extensions_dir.close();
223223
224224 var extensions = std.ArrayList([]const u8).init(allocator);
......@@ -227,7 +227,7 @@ fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]c
227227 while (try vendor_it.next()) |vendor_entry| {
228228 std.debug.assert(vendor_entry.kind == .Directory); // If this fails, the structure of SPIRV-Registry has changed.
229229
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, .{});
231231 var ext_it = vendor_dir.iterate();
232232 while (try ext_it.next()) |ext_entry| {
233233 // 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
250250 // SPV_EXT_name
251251 // ```
252252
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));
254254 const name_strings = "Name Strings";
255255
256256 const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry;