| author | |
| committer | |
| log | 7a361751e563c131399050f339dc47edf3c32325 |
| tree | 5141e62de6134816b62c7ff1399dcdc651f63b11 |
| parent | b1537b525fa0cd8d51ff89519254db0f066fc04b |
| parent | 46ffc798b6d9bb7be8b016ef7529092d647151ee |
| signature |
closes #474720 files changed, 157 insertions(+), 138 deletions(-)
doc/docgen.zig+1-1| ... | ... | @@ -48,7 +48,7 @@ pub fn main() !void { |
| 48 | 48 | var toc = try genToc(allocator, &tokenizer); |
| 49 | 49 | |
| 50 | 50 | try fs.cwd().makePath(tmp_dir_name); |
| 51 | defer fs.deleteTree(tmp_dir_name) catch {}; | |
| 51 | defer fs.cwd().deleteTree(tmp_dir_name) catch {}; | |
| 52 | 52 | |
| 53 | 53 | try genHtml(allocator, &tokenizer, &toc, buffered_out_stream.outStream(), zig_exe); |
| 54 | 54 | try buffered_out_stream.flush(); |
lib/std/build.zig+4-4| ... | ... | @@ -377,7 +377,7 @@ pub const Builder = struct { |
| 377 | 377 | if (self.verbose) { |
| 378 | 378 | warn("rm {}\n", .{full_path}); |
| 379 | 379 | } |
| 380 | fs.deleteTree(full_path) catch {}; | |
| 380 | fs.cwd().deleteTree(full_path) catch {}; | |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | 383 | // TODO remove empty directories |
| ... | ... | @@ -2156,10 +2156,10 @@ pub const LibExeObjStep = struct { |
| 2156 | 2156 | const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n"); |
| 2157 | 2157 | |
| 2158 | 2158 | if (self.output_dir) |output_dir| { |
| 2159 | var src_dir = try std.fs.cwd().openDirTraverse(build_output_dir); | |
| 2159 | var src_dir = try std.fs.cwd().openDir(build_output_dir, .{ .iterate = true }); | |
| 2160 | 2160 | defer src_dir.close(); |
| 2161 | 2161 | |
| 2162 | var dest_dir = try std.fs.cwd().openDirList(output_dir); | |
| 2162 | var dest_dir = try std.fs.cwd().openDir(output_dir, .{}); | |
| 2163 | 2163 | defer dest_dir.close(); |
| 2164 | 2164 | |
| 2165 | 2165 | var it = src_dir.iterate(); |
| ... | ... | @@ -2365,7 +2365,7 @@ pub const RemoveDirStep = struct { |
| 2365 | 2365 | const self = @fieldParentPtr(RemoveDirStep, "step", step); |
| 2366 | 2366 | |
| 2367 | 2367 | const full_path = self.builder.pathFromRoot(self.dir_path); |
| 2368 | fs.deleteTree(full_path) catch |err| { | |
| 2368 | fs.cwd().deleteTree(full_path) catch |err| { | |
| 2369 | 2369 | warn("Unable to remove {}: {}\n", .{ full_path, @errorName(err) }); |
| 2370 | 2370 | return err; |
| 2371 | 2371 | }; |
lib/std/build/write_file.zig+1-1| ... | ... | @@ -78,7 +78,7 @@ pub const WriteFileStep = struct { |
| 78 | 78 | warn("unable to make path {}: {}\n", .{ self.output_dir, @errorName(err) }); |
| 79 | 79 | return err; |
| 80 | 80 | }; |
| 81 | var dir = try fs.cwd().openDirTraverse(self.output_dir); | |
| 81 | var dir = try fs.cwd().openDir(self.output_dir, .{}); | |
| 82 | 82 | defer dir.close(); |
| 83 | 83 | for (self.files.toSliceConst()) |file| { |
| 84 | 84 | dir.writeFile(file.basename, file.bytes) catch |err| { |
lib/std/fs.zig+64-111| ... | ... | @@ -261,28 +261,6 @@ pub fn deleteDirW(dir_path: [*:0]const u16) !void { |
| 261 | 261 | return os.rmdirW(dir_path); |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | /// Removes a symlink, file, or directory. | |
| 265 | /// If `full_path` is relative, this is equivalent to `Dir.deleteTree` with the | |
| 266 | /// current working directory as the open directory handle. | |
| 267 | /// If `full_path` is absolute, this is equivalent to `Dir.deleteTree` with the | |
| 268 | /// base directory. | |
| 269 | pub fn deleteTree(full_path: []const u8) !void { | |
| 270 | if (path.isAbsolute(full_path)) { | |
| 271 | const dirname = path.dirname(full_path) orelse return error{ | |
| 272 | /// Attempt to remove the root file system path. | |
| 273 | /// This error is unreachable if `full_path` is relative. | |
| 274 | CannotDeleteRootDirectory, | |
| 275 | }.CannotDeleteRootDirectory; | |
| 276 | ||
| 277 | var dir = try cwd().openDirList(dirname); | |
| 278 | defer dir.close(); | |
| 279 | ||
| 280 | return dir.deleteTree(path.basename(full_path)); | |
| 281 | } else { | |
| 282 | return cwd().deleteTree(full_path); | |
| 283 | } | |
| 284 | } | |
| 285 | ||
| 286 | 264 | pub const Dir = struct { |
| 287 | 265 | fd: os.fd_t, |
| 288 | 266 | |
| ... | ... | @@ -339,7 +317,7 @@ pub const Dir = struct { |
| 339 | 317 | if (rc == 0) return null; |
| 340 | 318 | if (rc < 0) { |
| 341 | 319 | switch (os.errno(rc)) { |
| 342 | os.EBADF => unreachable, | |
| 320 | os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability | |
| 343 | 321 | os.EFAULT => unreachable, |
| 344 | 322 | os.ENOTDIR => unreachable, |
| 345 | 323 | os.EINVAL => unreachable, |
| ... | ... | @@ -388,7 +366,7 @@ pub const Dir = struct { |
| 388 | 366 | ); |
| 389 | 367 | switch (os.errno(rc)) { |
| 390 | 368 | 0 => {}, |
| 391 | os.EBADF => unreachable, | |
| 369 | os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability | |
| 392 | 370 | os.EFAULT => unreachable, |
| 393 | 371 | os.ENOTDIR => unreachable, |
| 394 | 372 | os.EINVAL => unreachable, |
| ... | ... | @@ -444,7 +422,7 @@ pub const Dir = struct { |
| 444 | 422 | const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len); |
| 445 | 423 | switch (os.linux.getErrno(rc)) { |
| 446 | 424 | 0 => {}, |
| 447 | os.EBADF => unreachable, | |
| 425 | os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability | |
| 448 | 426 | os.EFAULT => unreachable, |
| 449 | 427 | os.ENOTDIR => unreachable, |
| 450 | 428 | os.EINVAL => unreachable, |
| ... | ... | @@ -518,7 +496,8 @@ pub const Dir = struct { |
| 518 | 496 | self.end_index = io.Information; |
| 519 | 497 | switch (rc) { |
| 520 | 498 | .SUCCESS => {}, |
| 521 | .ACCESS_DENIED => return error.AccessDenied, | |
| 499 | .ACCESS_DENIED => return error.AccessDenied, // Double-check that the Dir was opened with iteration ability | |
| 500 | ||
| 522 | 501 | else => return w.unexpectedStatus(rc), |
| 523 | 502 | } |
| 524 | 503 | } |
| ... | ... | @@ -596,16 +575,6 @@ pub const Dir = struct { |
| 596 | 575 | DeviceBusy, |
| 597 | 576 | } || os.UnexpectedError; |
| 598 | 577 | |
| 599 | /// Deprecated; call `cwd().openDirList` directly. | |
| 600 | pub fn open(dir_path: []const u8) OpenError!Dir { | |
| 601 | return cwd().openDirList(dir_path); | |
| 602 | } | |
| 603 | ||
| 604 | /// Deprecated; call `cwd().openDirListC` directly. | |
| 605 | pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir { | |
| 606 | return cwd().openDirListC(dir_path_c); | |
| 607 | } | |
| 608 | ||
| 609 | 578 | pub fn close(self: *Dir) void { |
| 610 | 579 | if (need_async_thread) { |
| 611 | 580 | std.event.Loop.instance.?.close(self.fd); |
| ... | ... | @@ -792,79 +761,61 @@ pub const Dir = struct { |
| 792 | 761 | try os.fchdir(self.fd); |
| 793 | 762 | } |
| 794 | 763 | |
| 795 | /// Deprecated; call `openDirList` directly. | |
| 796 | pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir { | |
| 797 | return self.openDirList(sub_path); | |
| 798 | } | |
| 799 | ||
| 800 | /// Deprecated; call `openDirListC` directly. | |
| 801 | pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir { | |
| 802 | return self.openDirListC(sub_path_c); | |
| 803 | } | |
| 804 | ||
| 805 | /// Opens a directory at the given path with the ability to access subpaths | |
| 806 | /// of the result. Calling `iterate` on the result is illegal behavior; to | |
| 807 | /// list the contents of a directory, open it with `openDirList`. | |
| 808 | /// | |
| 809 | /// Call `close` on the result when done. | |
| 810 | /// | |
| 811 | /// Asserts that the path parameter has no null bytes. | |
| 812 | /// TODO collapse this and `openDirList` into one function with an options parameter | |
| 813 | pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir { | |
| 814 | if (builtin.os.tag == .windows) { | |
| 815 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | |
| 816 | return self.openDirTraverseW(&sub_path_w); | |
| 817 | } | |
| 764 | pub const OpenDirOptions = struct { | |
| 765 | /// `true` means the opened directory can be used as the `Dir` parameter | |
| 766 | /// for functions which operate based on an open directory handle. When `false`, | |
| 767 | /// such operations are Illegal Behavior. | |
| 768 | access_sub_paths: bool = true, | |
| 818 | 769 | |
| 819 | const sub_path_c = try os.toPosixPath(sub_path); | |
| 820 | return self.openDirTraverseC(&sub_path_c); | |
| 821 | } | |
| 770 | /// `true` means the opened directory can be scanned for the files and sub-directories | |
| 771 | /// of the result. It means the `iterate` function can be called. | |
| 772 | iterate: bool = false, | |
| 773 | }; | |
| 822 | 774 | |
| 823 | /// Opens a directory at the given path with the ability to access subpaths and list contents | |
| 824 | /// of the result. If the ability to list contents is unneeded, `openDirTraverse` acts the | |
| 825 | /// same and may be more efficient. | |
| 826 | /// | |
| 827 | /// Call `close` on the result when done. | |
| 775 | /// Opens a directory at the given path. The directory is a system resource that remains | |
| 776 | /// open until `close` is called on the result. | |
| 828 | 777 | /// |
| 829 | 778 | /// Asserts that the path parameter has no null bytes. |
| 830 | /// TODO collapse this and `openDirTraverse` into one function with an options parameter | |
| 831 | pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir { | |
| 779 | pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { | |
| 832 | 780 | if (builtin.os.tag == .windows) { |
| 833 | 781 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 834 | return self.openDirListW(&sub_path_w); | |
| 782 | return self.openDirW(&sub_path_w, args); | |
| 783 | } else { | |
| 784 | const sub_path_c = try os.toPosixPath(sub_path); | |
| 785 | return self.openDirC(&sub_path_c, args); | |
| 835 | 786 | } |
| 836 | ||
| 837 | const sub_path_c = try os.toPosixPath(sub_path); | |
| 838 | return self.openDirListC(&sub_path_c); | |
| 839 | 787 | } |
| 840 | 788 | |
| 841 | /// Same as `openDirTraverse` except the parameter is null-terminated. | |
| 842 | pub fn openDirTraverseC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir { | |
| 789 | /// Same as `openDir` except the parameter is null-terminated. | |
| 790 | pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir { | |
| 843 | 791 | if (builtin.os.tag == .windows) { |
| 844 | 792 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); |
| 845 | return self.openDirTraverseW(&sub_path_w); | |
| 846 | } else { | |
| 793 | return self.openDirW(&sub_path_w, args); | |
| 794 | } else if (!args.iterate) { | |
| 847 | 795 | const O_PATH = if (@hasDecl(os, "O_PATH")) os.O_PATH else 0; |
| 848 | return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC | O_PATH); | |
| 796 | return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC | O_PATH); | |
| 797 | } else { | |
| 798 | return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC); | |
| 849 | 799 | } |
| 850 | 800 | } |
| 851 | 801 | |
| 852 | /// Same as `openDirList` except the parameter is null-terminated. | |
| 853 | pub fn openDirListC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir { | |
| 854 | if (builtin.os.tag == .windows) { | |
| 855 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | |
| 856 | return self.openDirListW(&sub_path_w); | |
| 857 | } else { | |
| 858 | return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC); | |
| 859 | } | |
| 802 | /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed. | |
| 803 | /// This function asserts the target OS is Windows. | |
| 804 | pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) OpenError!Dir { | |
| 805 | const w = os.windows; | |
| 806 | // TODO remove some of these flags if args.access_sub_paths is false | |
| 807 | const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | | |
| 808 | w.SYNCHRONIZE | w.FILE_TRAVERSE; | |
| 809 | const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags; | |
| 810 | return self.openDirAccessMaskW(sub_path_w, flags); | |
| 860 | 811 | } |
| 861 | 812 | |
| 813 | /// `flags` must contain `os.O_DIRECTORY`. | |
| 862 | 814 | fn openDirFlagsC(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir { |
| 863 | const os_flags = flags | os.O_DIRECTORY; | |
| 864 | 815 | const result = if (need_async_thread) |
| 865 | std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, 0) | |
| 816 | std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, flags, 0) | |
| 866 | 817 | else |
| 867 | os.openatC(self.fd, sub_path_c, os_flags, 0); | |
| 818 | os.openatC(self.fd, sub_path_c, flags, 0); | |
| 868 | 819 | const fd = result catch |err| switch (err) { |
| 869 | 820 | error.FileTooBig => unreachable, // can't happen for directories |
| 870 | 821 | error.IsDir => unreachable, // we're providing O_DIRECTORY |
| ... | ... | @@ -875,22 +826,6 @@ pub const Dir = struct { |
| 875 | 826 | return Dir{ .fd = fd }; |
| 876 | 827 | } |
| 877 | 828 | |
| 878 | /// Same as `openDirTraverse` except the path parameter is UTF16LE, NT-prefixed. | |
| 879 | /// This function is Windows-only. | |
| 880 | pub fn openDirTraverseW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir { | |
| 881 | const w = os.windows; | |
| 882 | ||
| 883 | return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE); | |
| 884 | } | |
| 885 | ||
| 886 | /// Same as `openDirList` except the path parameter is UTF16LE, NT-prefixed. | |
| 887 | /// This function is Windows-only. | |
| 888 | pub fn openDirListW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir { | |
| 889 | const w = os.windows; | |
| 890 | ||
| 891 | return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE | w.FILE_LIST_DIRECTORY); | |
| 892 | } | |
| 893 | ||
| 894 | 829 | fn openDirAccessMaskW(self: Dir, sub_path_w: [*:0]const u16, access_mask: u32) OpenError!Dir { |
| 895 | 830 | const w = os.windows; |
| 896 | 831 | |
| ... | ... | @@ -1111,7 +1046,7 @@ pub const Dir = struct { |
| 1111 | 1046 | error.Unexpected, |
| 1112 | 1047 | => |e| return e, |
| 1113 | 1048 | } |
| 1114 | var dir = self.openDirList(sub_path) catch |err| switch (err) { | |
| 1049 | var dir = self.openDir(sub_path, .{ .iterate = true }) catch |err| switch (err) { | |
| 1115 | 1050 | error.NotDir => { |
| 1116 | 1051 | if (got_access_denied) { |
| 1117 | 1052 | return error.AccessDenied; |
| ... | ... | @@ -1144,7 +1079,6 @@ pub const Dir = struct { |
| 1144 | 1079 | |
| 1145 | 1080 | var dir_name_buf: [MAX_PATH_BYTES]u8 = undefined; |
| 1146 | 1081 | var dir_name: []const u8 = sub_path; |
| 1147 | var parent_dir = self; | |
| 1148 | 1082 | |
| 1149 | 1083 | // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function. |
| 1150 | 1084 | // Go through each entry and if it is not a directory, delete it. If it is a directory, |
| ... | ... | @@ -1176,7 +1110,7 @@ pub const Dir = struct { |
| 1176 | 1110 | => |e| return e, |
| 1177 | 1111 | } |
| 1178 | 1112 | |
| 1179 | const new_dir = dir.openDirList(entry.name) catch |err| switch (err) { | |
| 1113 | const new_dir = dir.openDir(entry.name, .{ .iterate = true }) catch |err| switch (err) { | |
| 1180 | 1114 | error.NotDir => { |
| 1181 | 1115 | if (got_access_denied) { |
| 1182 | 1116 | return error.AccessDenied; |
| ... | ... | @@ -1349,7 +1283,7 @@ pub const Dir = struct { |
| 1349 | 1283 | } |
| 1350 | 1284 | }; |
| 1351 | 1285 | |
| 1352 | /// Returns an handle to the current working directory that is open for traversal. | |
| 1286 | /// Returns an handle to the current working directory. It is not opened with iteration capability. | |
| 1353 | 1287 | /// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior. |
| 1354 | 1288 | /// On POSIX targets, this function is comptime-callable. |
| 1355 | 1289 | pub fn cwd() Dir { |
| ... | ... | @@ -1427,6 +1361,25 @@ pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void |
| 1427 | 1361 | return cwd().deleteFileW(absolute_path_w); |
| 1428 | 1362 | } |
| 1429 | 1363 | |
| 1364 | /// Removes a symlink, file, or directory. | |
| 1365 | /// This is equivalent to `Dir.deleteTree` with the base directory. | |
| 1366 | /// Asserts that the path is absolute. See `Dir.deleteTree` for a function that | |
| 1367 | /// operates on both absolute and relative paths. | |
| 1368 | /// Asserts that the path parameter has no null bytes. | |
| 1369 | pub fn deleteTreeAbsolute(absolute_path: []const u8) !void { | |
| 1370 | assert(path.isAbsolute(absolute_path)); | |
| 1371 | const dirname = path.dirname(absolute_path) orelse return error{ | |
| 1372 | /// Attempt to remove the root file system path. | |
| 1373 | /// This error is unreachable if `absolute_path` is relative. | |
| 1374 | CannotDeleteRootDirectory, | |
| 1375 | }.CannotDeleteRootDirectory; | |
| 1376 | ||
| 1377 | var dir = try cwd().openDir(dirname, .{}); | |
| 1378 | defer dir.close(); | |
| 1379 | ||
| 1380 | return dir.deleteTree(path.basename(absolute_path)); | |
| 1381 | } | |
| 1382 | ||
| 1430 | 1383 | pub const Walker = struct { |
| 1431 | 1384 | stack: std.ArrayList(StackItem), |
| 1432 | 1385 | name_buffer: std.Buffer, |
| ... | ... | @@ -1461,7 +1414,7 @@ pub const Walker = struct { |
| 1461 | 1414 | try self.name_buffer.appendByte(path.sep); |
| 1462 | 1415 | try self.name_buffer.append(base.name); |
| 1463 | 1416 | if (base.kind == .Directory) { |
| 1464 | var new_dir = top.dir_it.dir.openDirList(base.name) catch |err| switch (err) { | |
| 1417 | var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) { | |
| 1465 | 1418 | error.NameTooLong => unreachable, // no path sep in base.name |
| 1466 | 1419 | else => |e| return e, |
| 1467 | 1420 | }; |
| ... | ... | @@ -1499,7 +1452,7 @@ pub const Walker = struct { |
| 1499 | 1452 | pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker { |
| 1500 | 1453 | assert(!mem.endsWith(u8, dir_path, path.sep_str)); |
| 1501 | 1454 | |
| 1502 | var dir = try cwd().openDirList(dir_path); | |
| 1455 | var dir = try cwd().openDir(dir_path, .{ .iterate = true }); | |
| 1503 | 1456 | errdefer dir.close(); |
| 1504 | 1457 | |
| 1505 | 1458 | var name_buffer = try std.Buffer.init(allocator, dir_path); |
lib/std/fs/watch.zig+1-1| ... | ... | @@ -619,7 +619,7 @@ test "write a file, watch it, write it again" { |
| 619 | 619 | if (true) return error.SkipZigTest; |
| 620 | 620 | |
| 621 | 621 | try fs.cwd().makePath(test_tmp_dir); |
| 622 | defer os.deleteTree(test_tmp_dir) catch {}; | |
| 622 | defer fs.cwd().deleteTree(test_tmp_dir) catch {}; | |
| 623 | 623 | |
| 624 | 624 | const allocator = std.heap.page_allocator; |
| 625 | 625 | return testFsWatch(&allocator); |
lib/std/os.zig+25| ... | ... | @@ -3163,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 { |
| 3163 | 3163 | } |
| 3164 | 3164 | } |
| 3165 | 3165 | |
| 3166 | pub const FcntlError = error{ | |
| 3167 | PermissionDenied, | |
| 3168 | FileBusy, | |
| 3169 | ProcessFdQuotaExceeded, | |
| 3170 | Locked, | |
| 3171 | } || UnexpectedError; | |
| 3172 | ||
| 3173 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { | |
| 3174 | while (true) { | |
| 3175 | const rc = system.fcntl(fd, cmd, arg); | |
| 3176 | switch (errno(rc)) { | |
| 3177 | 0 => return @intCast(usize, rc), | |
| 3178 | EINTR => continue, | |
| 3179 | EACCES => return error.Locked, | |
| 3180 | EBADF => unreachable, | |
| 3181 | EBUSY => return error.FileBusy, | |
| 3182 | EINVAL => unreachable, // invalid parameters | |
| 3183 | EPERM => return error.PermissionDenied, | |
| 3184 | EMFILE => return error.ProcessFdQuotaExceeded, | |
| 3185 | ENOTDIR => unreachable, // invalid parameter | |
| 3186 | else => |err| return unexpectedErrno(err), | |
| 3187 | } | |
| 3188 | } | |
| 3189 | } | |
| 3190 | ||
| 3166 | 3191 | pub const RealPathError = error{ |
| 3167 | 3192 | FileNotFound, |
| 3168 | 3193 | AccessDenied, |
lib/std/os/bits/dragonfly.zig+2| ... | ... | @@ -283,6 +283,8 @@ pub const F_LOCK = 1; |
| 283 | 283 | pub const F_TLOCK = 2; |
| 284 | 284 | pub const F_TEST = 3; |
| 285 | 285 | |
| 286 | pub const FD_CLOEXEC = 1; | |
| 287 | ||
| 286 | 288 | pub const AT_FDCWD = -328243; |
| 287 | 289 | pub const AT_SYMLINK_NOFOLLOW = 1; |
| 288 | 290 | pub const AT_REMOVEDIR = 2; |
lib/std/os/bits/freebsd.zig+2| ... | ... | @@ -355,6 +355,8 @@ pub const F_GETOWN_EX = 16; |
| 355 | 355 | |
| 356 | 356 | pub const F_GETOWNER_UIDS = 17; |
| 357 | 357 | |
| 358 | pub const FD_CLOEXEC = 1; | |
| 359 | ||
| 358 | 360 | pub const SEEK_SET = 0; |
| 359 | 361 | pub const SEEK_CUR = 1; |
| 360 | 362 | pub const SEEK_END = 2; |
lib/std/os/bits/linux.zig+2| ... | ... | @@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000; |
| 136 | 136 | /// For anonymous mmap, memory could be uninitialized |
| 137 | 137 | pub const MAP_UNINITIALIZED = 0x4000000; |
| 138 | 138 | |
| 139 | pub const FD_CLOEXEC = 1; | |
| 140 | ||
| 139 | 141 | pub const F_OK = 0; |
| 140 | 142 | pub const X_OK = 1; |
| 141 | 143 | pub const W_OK = 2; |
lib/std/os/bits/netbsd.zig+2| ... | ... | @@ -312,6 +312,8 @@ pub const F_GETLK = 7; |
| 312 | 312 | pub const F_SETLK = 8; |
| 313 | 313 | pub const F_SETLKW = 9; |
| 314 | 314 | |
| 315 | pub const FD_CLOEXEC = 1; | |
| 316 | ||
| 315 | 317 | pub const SEEK_SET = 0; |
| 316 | 318 | pub const SEEK_CUR = 1; |
| 317 | 319 | pub const SEEK_END = 2; |
lib/std/os/linux.zig+4| ... | ... | @@ -588,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize { |
| 588 | 588 | return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0); |
| 589 | 589 | } |
| 590 | 590 | |
| 591 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize { | |
| 592 | return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), arg); | |
| 593 | } | |
| 594 | ||
| 591 | 595 | var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); |
| 592 | 596 | |
| 593 | 597 | // We must follow the C calling convention when we call into the VDSO |
lib/std/os/test.zig+36-6| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | 2 | const os = std.os; |
| 3 | 3 | const testing = std.testing; |
| 4 | const expect = std.testing.expect; | |
| 4 | const expect = testing.expect; | |
| 5 | const expectEqual = testing.expectEqual; | |
| 5 | 6 | const io = std.io; |
| 6 | 7 | const fs = std.fs; |
| 7 | 8 | const mem = std.mem; |
| ... | ... | @@ -19,8 +20,8 @@ test "makePath, put some files in it, deleteTree" { |
| 19 | 20 | try fs.cwd().makePath("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c"); |
| 20 | 21 | try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense"); |
| 21 | 22 | try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah"); |
| 22 | try fs.deleteTree("os_test_tmp"); | |
| 23 | if (fs.cwd().openDirTraverse("os_test_tmp")) |dir| { | |
| 23 | try fs.cwd().deleteTree("os_test_tmp"); | |
| 24 | if (fs.cwd().openDir("os_test_tmp", .{})) |dir| { | |
| 24 | 25 | @panic("expected error"); |
| 25 | 26 | } else |err| { |
| 26 | 27 | expect(err == error.FileNotFound); |
| ... | ... | @@ -37,7 +38,7 @@ test "access file" { |
| 37 | 38 | |
| 38 | 39 | try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", ""); |
| 39 | 40 | try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK); |
| 40 | try fs.deleteTree("os_test_tmp"); | |
| 41 | try fs.cwd().deleteTree("os_test_tmp"); | |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | fn testThreadIdFn(thread_id: *Thread.Id) void { |
| ... | ... | @@ -46,9 +47,9 @@ fn testThreadIdFn(thread_id: *Thread.Id) void { |
| 46 | 47 | |
| 47 | 48 | test "sendfile" { |
| 48 | 49 | try fs.cwd().makePath("os_test_tmp"); |
| 49 | defer fs.deleteTree("os_test_tmp") catch {}; | |
| 50 | defer fs.cwd().deleteTree("os_test_tmp") catch {}; | |
| 50 | 51 | |
| 51 | var dir = try fs.cwd().openDirList("os_test_tmp"); | |
| 52 | var dir = try fs.cwd().openDir("os_test_tmp", .{}); | |
| 52 | 53 | defer dir.close(); |
| 53 | 54 | |
| 54 | 55 | const line1 = "line1\n"; |
| ... | ... | @@ -446,3 +447,32 @@ test "getenv" { |
| 446 | 447 | expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null); |
| 447 | 448 | } |
| 448 | 449 | } |
| 450 | ||
| 451 | test "fcntl" { | |
| 452 | if (builtin.os.tag == .windows) | |
| 453 | return error.SkipZigTest; | |
| 454 | ||
| 455 | const test_out_file = "os_tmp_test"; | |
| 456 | ||
| 457 | const file = try fs.cwd().createFile(test_out_file, .{}); | |
| 458 | defer { | |
| 459 | file.close(); | |
| 460 | fs.cwd().deleteFile(test_out_file) catch {}; | |
| 461 | } | |
| 462 | ||
| 463 | // Note: The test assumes createFile opens the file with O_CLOEXEC | |
| 464 | { | |
| 465 | const flags = try os.fcntl(file.handle, os.F_GETFD, 0); | |
| 466 | expect((flags & os.FD_CLOEXEC) != 0); | |
| 467 | } | |
| 468 | { | |
| 469 | _ = try os.fcntl(file.handle, os.F_SETFD, 0); | |
| 470 | const flags = try os.fcntl(file.handle, os.F_GETFD, 0); | |
| 471 | expect((flags & os.FD_CLOEXEC) == 0); | |
| 472 | } | |
| 473 | { | |
| 474 | _ = try os.fcntl(file.handle, os.F_SETFD, os.FD_CLOEXEC); | |
| 475 | const flags = try os.fcntl(file.handle, os.F_GETFD, 0); | |
| 476 | expect((flags & os.FD_CLOEXEC) != 0); | |
| 477 | } | |
| 478 | } |
lib/std/zig/system.zig+1-1| ... | ... | @@ -754,7 +754,7 @@ pub const NativeTargetInfo = struct { |
| 754 | 754 | const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr)); |
| 755 | 755 | var it = mem.tokenize(rpath_list, ":"); |
| 756 | 756 | while (it.next()) |rpath| { |
| 757 | var dir = fs.cwd().openDirList(rpath) catch |err| switch (err) { | |
| 757 | var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) { | |
| 758 | 758 | error.NameTooLong => unreachable, |
| 759 | 759 | error.InvalidUtf8 => unreachable, |
| 760 | 760 | error.BadPathName => unreachable, |
src-self-hosted/compilation.zig+1-2| ... | ... | @@ -520,8 +520,7 @@ pub const Compilation = struct { |
| 520 | 520 | |
| 521 | 521 | if (comp.tmp_dir.getOrNull()) |tmp_dir_result| |
| 522 | 522 | if (tmp_dir_result.*) |tmp_dir| { |
| 523 | // TODO evented I/O? | |
| 524 | fs.deleteTree(tmp_dir) catch {}; | |
| 523 | fs.cwd().deleteTree(tmp_dir) catch {}; | |
| 525 | 524 | } else |_| {}; |
| 526 | 525 | } |
| 527 | 526 |
src-self-hosted/libc_installation.zig+5-5| ... | ... | @@ -280,7 +280,7 @@ pub const LibCInstallation = struct { |
| 280 | 280 | // search in reverse order |
| 281 | 281 | const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); |
| 282 | 282 | const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); |
| 283 | var search_dir = fs.cwd().openDirList(search_path) catch |err| switch (err) { | |
| 283 | var search_dir = fs.cwd().openDir(search_path, .{}) catch |err| switch (err) { | |
| 284 | 284 | error.FileNotFound, |
| 285 | 285 | error.NotDir, |
| 286 | 286 | error.NoDevice, |
| ... | ... | @@ -335,7 +335,7 @@ pub const LibCInstallation = struct { |
| 335 | 335 | const stream = result_buf.outStream(); |
| 336 | 336 | try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version }); |
| 337 | 337 | |
| 338 | var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { | |
| 338 | var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) { | |
| 339 | 339 | error.FileNotFound, |
| 340 | 340 | error.NotDir, |
| 341 | 341 | error.NoDevice, |
| ... | ... | @@ -382,7 +382,7 @@ pub const LibCInstallation = struct { |
| 382 | 382 | const stream = result_buf.outStream(); |
| 383 | 383 | try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir }); |
| 384 | 384 | |
| 385 | var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { | |
| 385 | var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) { | |
| 386 | 386 | error.FileNotFound, |
| 387 | 387 | error.NotDir, |
| 388 | 388 | error.NoDevice, |
| ... | ... | @@ -437,7 +437,7 @@ pub const LibCInstallation = struct { |
| 437 | 437 | const stream = result_buf.outStream(); |
| 438 | 438 | try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir }); |
| 439 | 439 | |
| 440 | var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { | |
| 440 | var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) { | |
| 441 | 441 | error.FileNotFound, |
| 442 | 442 | error.NotDir, |
| 443 | 443 | error.NoDevice, |
| ... | ... | @@ -475,7 +475,7 @@ pub const LibCInstallation = struct { |
| 475 | 475 | |
| 476 | 476 | try result_buf.append("\\include"); |
| 477 | 477 | |
| 478 | var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { | |
| 478 | var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) { | |
| 479 | 479 | error.FileNotFound, |
| 480 | 480 | error.NotDir, |
| 481 | 481 | error.NoDevice, |
src-self-hosted/main.zig+1-1| ... | ... | @@ -734,7 +734,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 734 | 734 | max_src_size, |
| 735 | 735 | ) catch |err| switch (err) { |
| 736 | 736 | error.IsDir, error.AccessDenied => { |
| 737 | var dir = try fs.cwd().openDirList(file_path); | |
| 737 | var dir = try fs.cwd().openDir(file_path, .{ .iterate = true }); | |
| 738 | 738 | defer dir.close(); |
| 739 | 739 | |
| 740 | 740 | var group = event.Group(FmtError!void).init(fmt.allocator); |
src-self-hosted/print_targets.zig+1-1| ... | ... | @@ -72,7 +72,7 @@ pub fn cmdTargets( |
| 72 | 72 | }; |
| 73 | 73 | defer allocator.free(zig_lib_dir); |
| 74 | 74 | |
| 75 | var dir = try std.fs.cwd().openDirList(zig_lib_dir); | |
| 75 | var dir = try std.fs.cwd().openDir(zig_lib_dir, .{}); | |
| 76 | 76 | defer dir.close(); |
| 77 | 77 | |
| 78 | 78 | const vers_txt = try dir.readFileAlloc(allocator, "libc/glibc/vers.txt", 10 * 1024); |
src-self-hosted/stage2.zig+1-1| ... | ... | @@ -319,7 +319,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { |
| 319 | 319 | const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { |
| 320 | 320 | error.IsDir, error.AccessDenied => { |
| 321 | 321 | // TODO make event based (and dir.next()) |
| 322 | var dir = try fs.cwd().openDirList(file_path); | |
| 322 | var dir = try fs.cwd().openDir(file_path, .{ .iterate = true }); | |
| 323 | 323 | defer dir.close(); |
| 324 | 324 | |
| 325 | 325 | var dir_it = dir.iterate(); |
src-self-hosted/test.zig+2-2| ... | ... | @@ -57,11 +57,11 @@ pub const TestContext = struct { |
| 57 | 57 | errdefer allocator.free(self.zig_lib_dir); |
| 58 | 58 | |
| 59 | 59 | try std.fs.cwd().makePath(tmp_dir_name); |
| 60 | errdefer std.fs.deleteTree(tmp_dir_name) catch {}; | |
| 60 | errdefer std.fs.cwd().deleteTree(tmp_dir_name) catch {}; | |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | fn deinit(self: *TestContext) void { |
| 64 | std.fs.deleteTree(tmp_dir_name) catch {}; | |
| 64 | std.fs.cwd().deleteTree(tmp_dir_name) catch {}; | |
| 65 | 65 | allocator.free(self.zig_lib_dir); |
| 66 | 66 | self.zig_compiler.deinit(); |
| 67 | 67 | } |
test/cli.zig+1-1| ... | ... | @@ -36,7 +36,7 @@ pub fn main() !void { |
| 36 | 36 | testMissingOutputPath, |
| 37 | 37 | }; |
| 38 | 38 | for (test_fns) |testFn| { |
| 39 | try fs.deleteTree(dir_path); | |
| 39 | try fs.cwd().deleteTree(dir_path); | |
| 40 | 40 | try fs.cwd().makeDir(dir_path); |
| 41 | 41 | try testFn(zig_exe, dir_path); |
| 42 | 42 | } |