authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-06 21:06:30-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:08-08:00
log916998315967f73c91e682e9ea05dd3232818654
tree6cd1ee9b952441c6b6ea1ddbad17a5cfd4b5f860
parent877032ec6a0007316f42658d12042f1473de4856

std.fs: migrate most of the API elsewhere


10 files changed, 193 insertions(+), 312 deletions(-)

lib/std/Io/Dir.zig+156-17
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const Dir = @This();1const Dir = @This();
2const root = @import("root");
23
3const builtin = @import("builtin");4const builtin = @import("builtin");
4const native_os = builtin.os.tag;5const native_os = builtin.os.tag;
...@@ -11,6 +12,61 @@ const Allocator = std.mem.Allocator;...@@ -11,6 +12,61 @@ const Allocator = std.mem.Allocator;
1112
12handle: Handle,13handle: Handle,
1314
15pub const path = std.fs.path;
16
17/// The maximum length of a file path that the operating system will accept.
18///
19/// Paths, including those returned from file system operations, may be longer
20/// than this length, but such paths cannot be successfully passed back in
21/// other file system operations. However, all path components returned by file
22/// system operations are assumed to fit into a `u8` array of this length.
23///
24/// The byte count includes room for a null sentinel byte.
25///
26/// * On Windows, `[]u8` file paths are encoded as
27/// [WTF-8](https://wtf-8.codeberg.page/).
28/// * On WASI, `[]u8` file paths are encoded as valid UTF-8.
29/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with
30/// no particular encoding.
31pub const max_path_bytes = switch (native_os) {
32 .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => std.posix.PATH_MAX,
33 // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes.
34 // If it would require 4 WTF-8 bytes, then there would be a surrogate
35 // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
36 // +1 for the null byte at the end, which can be encoded in 1 byte.
37 .windows => std.os.windows.PATH_MAX_WIDE * 3 + 1,
38 else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX"))
39 root.os.PATH_MAX
40 else
41 @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)),
42};
43
44/// This represents the maximum size of a `[]u8` file name component that
45/// the platform's common file systems support. File name components returned by file system
46/// operations are likely to fit into a `u8` array of this length, but
47/// (depending on the platform) this assumption may not hold for every configuration.
48/// The byte count does not include a null sentinel byte.
49/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/).
50/// On WASI, file name components are encoded as valid UTF-8.
51/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
52pub const max_name_bytes = switch (native_os) {
53 .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => std.posix.NAME_MAX,
54 // Haiku's NAME_MAX includes the null terminator, so subtract one.
55 .haiku => std.posix.NAME_MAX - 1,
56 // Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
57 // If it would require 4 WTF-8 bytes, then there would be a surrogate
58 // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
59 .windows => std.os.windows.NAME_MAX * 3,
60 // For WASI, the MAX_NAME will depend on the host OS, so it needs to be
61 // as large as the largest max_name_bytes (Windows) in order to work on any host OS.
62 // TODO determine if this is a reasonable approach
63 .wasi => std.os.windows.NAME_MAX * 3,
64 else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX"))
65 root.os.NAME_MAX
66 else
67 @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)),
68};
69
14pub const Entry = struct {70pub const Entry = struct {
15 name: []const u8,71 name: []const u8,
16 kind: File.Kind,72 kind: File.Kind,
...@@ -148,7 +204,7 @@ pub const SelectiveWalker = struct {...@@ -148,7 +204,7 @@ pub const SelectiveWalker = struct {
148 }) |entry| {204 }) |entry| {
149 self.name_buffer.shrinkRetainingCapacity(dirname_len);205 self.name_buffer.shrinkRetainingCapacity(dirname_len);
150 if (self.name_buffer.items.len != 0) {206 if (self.name_buffer.items.len != 0) {
151 try self.name_buffer.append(self.allocator, std.fs.path.sep);207 try self.name_buffer.append(self.allocator, path.sep);
152 dirname_len += 1;208 dirname_len += 1;
153 }209 }
154 try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1);210 try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1);
...@@ -252,7 +308,7 @@ pub const Walker = struct {...@@ -252,7 +308,7 @@ pub const Walker = struct {
252 /// Returns 1 for a direct child of the initial directory, 2 for an entry308 /// Returns 1 for a direct child of the initial directory, 2 for an entry
253 /// within a direct child of the initial directory, etc.309 /// within a direct child of the initial directory, etc.
254 pub fn depth(self: Walker.Entry) usize {310 pub fn depth(self: Walker.Entry) usize {
255 return std.mem.countScalar(u8, self.path, std.fs.path.sep) + 1;311 return std.mem.countScalar(u8, self.path, path.sep) + 1;
256 }312 }
257 };313 };
258314
...@@ -340,6 +396,11 @@ pub fn access(dir: Dir, io: Io, sub_path: []const u8, options: AccessOptions) Ac...@@ -340,6 +396,11 @@ pub fn access(dir: Dir, io: Io, sub_path: []const u8, options: AccessOptions) Ac
340 return io.vtable.dirAccess(io.userdata, dir, sub_path, options);396 return io.vtable.dirAccess(io.userdata, dir, sub_path, options);
341}397}
342398
399pub fn accessAbsolute(io: Io, absolute_path: []const u8, options: AccessOptions) AccessError!void {
400 assert(path.isAbsolute(absolute_path));
401 return access(.cwd(), io, absolute_path, options);
402}
403
343pub const OpenError = error{404pub const OpenError = error{
344 FileNotFound,405 FileNotFound,
345 NotDir,406 NotDir,
...@@ -379,6 +440,11 @@ pub fn openDir(dir: Dir, io: Io, sub_path: []const u8, options: OpenOptions) Ope...@@ -379,6 +440,11 @@ pub fn openDir(dir: Dir, io: Io, sub_path: []const u8, options: OpenOptions) Ope
379 return io.vtable.dirOpenDir(io.userdata, dir, sub_path, options);440 return io.vtable.dirOpenDir(io.userdata, dir, sub_path, options);
380}441}
381442
443pub fn openDirAbsolute(io: Io, absolute_path: []const u8, options: OpenOptions) OpenError!Dir {
444 assert(path.isAbsolute(absolute_path));
445 return openDir(.cwd(), io, absolute_path, options);
446}
447
382pub fn close(dir: Dir, io: Io) void {448pub fn close(dir: Dir, io: Io) void {
383 return io.vtable.dirClose(io.userdata, dir);449 return io.vtable.dirClose(io.userdata, dir);
384}450}
...@@ -396,6 +462,11 @@ pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) F...@@ -396,6 +462,11 @@ pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) F
396 return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags);462 return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags);
397}463}
398464
465pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
466 assert(path.isAbsolute(absolute_path));
467 return openFile(.cwd(), io, absolute_path, flags);
468}
469
399/// Creates, opens, or overwrites a file with write access.470/// Creates, opens, or overwrites a file with write access.
400///471///
401/// Allocates a resource to be dellocated with `File.close`.472/// Allocates a resource to be dellocated with `File.close`.
...@@ -407,6 +478,10 @@ pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlag...@@ -407,6 +478,10 @@ pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlag
407 return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags);478 return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags);
408}479}
409480
481pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
482 return createFile(.cwd(), io, absolute_path, flags);
483}
484
410pub const WriteFileOptions = struct {485pub const WriteFileOptions = struct {
411 /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).486 /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
412 /// On WASI, `sub_path` should be encoded as valid UTF-8.487 /// On WASI, `sub_path` should be encoded as valid UTF-8.
...@@ -476,7 +551,7 @@ pub fn updateFile(...@@ -476,7 +551,7 @@ pub fn updateFile(
476 }551 }
477 }552 }
478553
479 if (std.fs.path.dirname(dest_path)) |dirname| {554 if (path.dirname(dest_path)) |dirname| {
480 try dest_dir.makePath(io, dirname, .default_dir);555 try dest_dir.makePath(io, dirname, .default_dir);
481 }556 }
482557
...@@ -556,6 +631,21 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions)...@@ -556,6 +631,21 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions)
556 return io.vtable.dirMake(io.userdata, dir, sub_path, permissions);631 return io.vtable.dirMake(io.userdata, dir, sub_path, permissions);
557}632}
558633
634/// Create a new directory, based on an absolute path.
635///
636/// Asserts that the path is absolute. See `makeDir` for a function that
637/// operates on both absolute and relative paths.
638///
639/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
640/// On WASI, `absolute_path` should be encoded as valid UTF-8.
641/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
642pub fn makeDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissions) MakeError!void {
643 assert(path.isAbsolute(absolute_path));
644 return makeDir(.cwd(), io, absolute_path, permissions);
645}
646
647test makeDirAbsolute {}
648
559pub const MakePathError = MakeError || StatPathError;649pub const MakePathError = MakeError || StatPathError;
560650
561/// Creates parent directories with default permissions as necessary to ensure651/// Creates parent directories with default permissions as necessary to ensure
...@@ -703,19 +793,20 @@ pub const RealPathAllocError = RealPathError || Allocator.Error;...@@ -703,19 +793,20 @@ pub const RealPathAllocError = RealPathError || Allocator.Error;
703793
704/// Same as `realPath` except allocates result.794/// Same as `realPath` except allocates result.
705pub fn realPathAlloc(dir: Dir, io: Io, sub_path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {795pub fn realPathAlloc(dir: Dir, io: Io, sub_path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {
706 var buffer: [std.fs.max_path_bytes]u8 = undefined;796 var buffer: [max_path_bytes]u8 = undefined;
707 const n = try realPath(dir, io, sub_path, &buffer);797 const n = try realPath(dir, io, sub_path, &buffer);
708 return allocator.dupeZ(u8, buffer[0..n]);798 return allocator.dupeZ(u8, buffer[0..n]);
709}799}
710800
711pub fn realPathAbsolute(io: Io, path: []const u8, out_buffer: []u8) RealPathError!usize {801pub fn realPathAbsolute(io: Io, absolute_path: []const u8, out_buffer: []u8) RealPathError!usize {
712 return io.vtable.dirRealPath(io.userdata, .cwd(), path, out_buffer);802 assert(path.isAbsolute(absolute_path));
803 return io.vtable.dirRealPath(io.userdata, .cwd(), absolute_path, out_buffer);
713}804}
714805
715/// Same as `realPathAbsolute` except allocates result.806/// Same as `realPathAbsolute` except allocates result.
716pub fn realPathAbsoluteAlloc(io: Io, path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {807pub fn realPathAbsoluteAlloc(io: Io, absolute_path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {
717 var buffer: [std.fs.max_path_bytes]u8 = undefined;808 var buffer: [max_path_bytes]u8 = undefined;
718 const n = try realPathAbsolute(io, path, &buffer);809 const n = try realPathAbsolute(io, absolute_path, &buffer);
719 return allocator.dupeZ(u8, buffer[0..n]);810 return allocator.dupeZ(u8, buffer[0..n]);
720}811}
721812
...@@ -754,6 +845,13 @@ pub fn deleteFile(dir: Dir, io: Io, sub_path: []const u8) DeleteFileError!void {...@@ -754,6 +845,13 @@ pub fn deleteFile(dir: Dir, io: Io, sub_path: []const u8) DeleteFileError!void {
754 return io.vtable.dirDeleteFile(io.userdata, dir, sub_path);845 return io.vtable.dirDeleteFile(io.userdata, dir, sub_path);
755}846}
756847
848pub fn deleteFileAbsolute(io: Io, absolute_path: []const u8) DeleteFileError!void {
849 assert(path.isAbsolute(absolute_path));
850 return deleteFile(.cwd(), io, absolute_path);
851}
852
853test deleteFileAbsolute {}
854
757pub const DeleteDirError = error{855pub const DeleteDirError = error{
758 DirNotEmpty,856 DirNotEmpty,
759 FileNotFound,857 FileNotFound,
...@@ -785,6 +883,16 @@ pub fn deleteDir(dir: Dir, io: Io, sub_path: []const u8) DeleteDirError!void {...@@ -785,6 +883,16 @@ pub fn deleteDir(dir: Dir, io: Io, sub_path: []const u8) DeleteDirError!void {
785 return io.vtable.dirDeleteDir(io.userdata, dir, sub_path);883 return io.vtable.dirDeleteDir(io.userdata, dir, sub_path);
786}884}
787885
886/// Same as `deleteDir` except the path is absolute.
887///
888/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
889/// On WASI, `dir_path` should be encoded as valid UTF-8.
890/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
891pub fn deleteDirAbsolute(io: Io, absolute_path: []const u8) DeleteDirError!void {
892 assert(path.isAbsolute(absolute_path));
893 return deleteDir(.cwd(), io, absolute_path);
894}
895
788pub const RenameError = error{896pub const RenameError = error{
789 /// In WASI, this error may occur when the file descriptor does897 /// In WASI, this error may occur when the file descriptor does
790 /// not hold the required rights to rename a resource by path relative to it.898 /// not hold the required rights to rename a resource by path relative to it.
...@@ -893,6 +1001,17 @@ pub fn symLink(...@@ -893,6 +1001,17 @@ pub fn symLink(
893 return io.vtable.dirSymLink(io.userdata, dir, target_path, sym_link_path, flags);1001 return io.vtable.dirSymLink(io.userdata, dir, target_path, sym_link_path, flags);
894}1002}
8951003
1004pub fn symLinkAbsolute(
1005 io: Io,
1006 target_path: []const u8,
1007 sym_link_path: []const u8,
1008 flags: SymLinkFlags,
1009) SymLinkError!void {
1010 assert(path.isAbsolute(target_path));
1011 assert(path.isAbsolute(sym_link_path));
1012 return symLink(.cwd(), io, target_path, sym_link_path, flags);
1013}
1014
896/// Same as `symLink`, except tries to create the symbolic link until it1015/// Same as `symLink`, except tries to create the symbolic link until it
897/// succeeds or encounters an error other than `error.PathAlreadyExists`.1016/// succeeds or encounters an error other than `error.PathAlreadyExists`.
898///1017///
...@@ -913,15 +1032,15 @@ pub fn symLinkAtomic(...@@ -913,15 +1032,15 @@ pub fn symLinkAtomic(
913 else => |e| return e,1032 else => |e| return e,
914 }1033 }
9151034
916 const dirname = std.fs.path.dirname(sym_link_path) orelse ".";1035 const dirname = path.dirname(sym_link_path) orelse ".";
9171036
918 const rand_len = @sizeOf(u64) * 2;1037 const rand_len = @sizeOf(u64) * 2;
919 const temp_path_len = dirname.len + 1 + rand_len;1038 const temp_path_len = dirname.len + 1 + rand_len;
920 var temp_path_buf: [std.fs.max_path_bytes]u8 = undefined;1039 var temp_path_buf: [max_path_bytes]u8 = undefined;
9211040
922 if (temp_path_len > temp_path_buf.len) return error.NameTooLong;1041 if (temp_path_len > temp_path_buf.len) return error.NameTooLong;
923 @memcpy(temp_path_buf[0..dirname.len], dirname);1042 @memcpy(temp_path_buf[0..dirname.len], dirname);
924 temp_path_buf[dirname.len] = std.fs.path.sep;1043 temp_path_buf[dirname.len] = path.sep;
9251044
926 const temp_path = temp_path_buf[0..temp_path_len];1045 const temp_path = temp_path_buf[0..temp_path_len];
9271046
...@@ -985,8 +1104,8 @@ pub fn readLink(dir: Dir, io: Io, sub_path: []const u8, buffer: []u8) ReadLinkEr...@@ -985,8 +1104,8 @@ pub fn readLink(dir: Dir, io: Io, sub_path: []const u8, buffer: []u8) ReadLinkEr
985/// On Windows, `path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).1104/// On Windows, `path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
986/// On WASI, `path` should be encoded as valid UTF-8.1105/// On WASI, `path` should be encoded as valid UTF-8.
987/// On other platforms, `path` is an opaque sequence of bytes with no particular encoding.1106/// On other platforms, `path` is an opaque sequence of bytes with no particular encoding.
988pub fn readLinkAbsolute(io: Io, path: []const u8, buffer: []u8) ReadLinkError!usize {1107pub fn readLinkAbsolute(io: Io, absolute_path: []const u8, buffer: []u8) ReadLinkError!usize {
989 assert(std.fs.path.isAbsolute(path));1108 assert(path.isAbsolute(absolute_path));
990 return io.vtable.dirReadLink(io.userdata, .cwd(), path, buffer);1109 return io.vtable.dirReadLink(io.userdata, .cwd(), path, buffer);
991}1110}
9921111
...@@ -1298,7 +1417,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,...@@ -1298,7 +1417,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,
1298 // Valid use of max_path_bytes because dir_name_buf will only1417 // Valid use of max_path_bytes because dir_name_buf will only
1299 // ever store a single path component that was returned from the1418 // ever store a single path component that was returned from the
1300 // filesystem.1419 // filesystem.
1301 var dir_name_buf: [std.fs.max_path_bytes]u8 = undefined;1420 var dir_name_buf: [max_path_bytes]u8 = undefined;
1302 var dir_name: []const u8 = sub_path;1421 var dir_name: []const u8 = sub_path;
13031422
1304 // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.1423 // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.
...@@ -1521,6 +1640,26 @@ pub fn copyFile(...@@ -1521,6 +1640,26 @@ pub fn copyFile(
1521 try atomic_file.finish();1640 try atomic_file.finish();
1522}1641}
15231642
1643/// Same as `copyFile`, except asserts that both `source_path` and `dest_path`
1644/// are absolute.
1645///
1646/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
1647/// On WASI, both paths should be encoded as valid UTF-8.
1648/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
1649pub fn copyFileAbsolute(
1650 source_path: []const u8,
1651 dest_path: []const u8,
1652 io: Io,
1653 options: CopyFileOptions,
1654) !void {
1655 assert(path.isAbsolute(source_path));
1656 assert(path.isAbsolute(dest_path));
1657 const my_cwd = cwd();
1658 return copyFile(my_cwd, source_path, my_cwd, dest_path, io, options);
1659}
1660
1661test copyFileAbsolute {}
1662
1524pub const AtomicFileOptions = struct {1663pub const AtomicFileOptions = struct {
1525 permissions: File.Permissions = .default_file,1664 permissions: File.Permissions = .default_file,
1526 make_path: bool = false,1665 make_path: bool = false,
...@@ -1538,13 +1677,13 @@ pub const AtomicFileOptions = struct {...@@ -1538,13 +1677,13 @@ pub const AtomicFileOptions = struct {
1538/// On WASI, `dest_path` should be encoded as valid UTF-8.1677/// On WASI, `dest_path` should be encoded as valid UTF-8.
1539/// On other platforms, `dest_path` is an opaque sequence of bytes with no particular encoding.1678/// On other platforms, `dest_path` is an opaque sequence of bytes with no particular encoding.
1540pub fn atomicFile(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFileOptions) !File.Atomic {1679pub fn atomicFile(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFileOptions) !File.Atomic {
1541 if (std.fs.path.dirname(dest_path)) |dirname| {1680 if (path.dirname(dest_path)) |dirname| {
1542 const dir = if (options.make_path)1681 const dir = if (options.make_path)
1543 try parent.makeOpenPath(io, dirname, .{})1682 try parent.makeOpenPath(io, dirname, .{})
1544 else1683 else
1545 try parent.openDir(io, dirname, .{});1684 try parent.openDir(io, dirname, .{});
15461685
1547 return .init(std.fs.path.basename(dest_path), options.permissions, dir, true, options.write_buffer);1686 return .init(path.basename(dest_path), options.permissions, dir, true, options.write_buffer);
1548 } else {1687 } else {
1549 return .init(dest_path, options.permissions, parent, false, options.write_buffer);1688 return .init(dest_path, options.permissions, parent, false, options.write_buffer);
1550 }1689 }
lib/std/Io/File.zig+6-16
...@@ -489,22 +489,6 @@ pub const WriteFileStreamingError = error{...@@ -489,22 +489,6 @@ pub const WriteFileStreamingError = error{
489 SystemResources,489 SystemResources,
490} || Io.Cancelable || Io.UnexpectedError;490} || Io.Cancelable || Io.UnexpectedError;
491491
492/// Opens a file for reading or writing, without attempting to create a new
493/// file, based on an absolute path.
494///
495/// Returns an open resource to be released with `close`.
496///
497/// Asserts that the path is absolute. See `Dir.openFile` for a function that
498/// operates on both absolute and relative paths.
499///
500/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
501/// On WASI, `absolute_path` should be encoded as valid UTF-8.
502/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
503pub fn openAbsolute(io: Io, absolute_path: []const u8, flags: OpenFlags) OpenError!File {
504 assert(std.fs.path.isAbsolute(absolute_path));
505 return Io.Dir.cwd().openFile(io, absolute_path, flags);
506}
507
508pub const SeekError = error{492pub const SeekError = error{
509 Unseekable,493 Unseekable,
510 /// The file descriptor does not hold the required rights to seek on it.494 /// The file descriptor does not hold the required rights to seek on it.
...@@ -579,3 +563,9 @@ pub const DowngradeLockError = Io.Cancelable || Io.UnexpectedError;...@@ -579,3 +563,9 @@ pub const DowngradeLockError = Io.Cancelable || Io.UnexpectedError;
579pub fn downgradeLock(file: File, io: Io) LockError!void {563pub fn downgradeLock(file: File, io: Io) LockError!void {
580 return io.vtable.fileDowngradeLock(io.userdata, file);564 return io.vtable.fileDowngradeLock(io.userdata, file);
581}565}
566
567test {
568 _ = Reader;
569 _ = Writer;
570 _ = Atomic;
571}
lib/std/crypto/Certificate/Bundle.zig+1-1
...@@ -221,7 +221,7 @@ pub fn addCertsFromFilePathAbsolute(...@@ -221,7 +221,7 @@ pub fn addCertsFromFilePathAbsolute(
221 now: Io.Timestamp,221 now: Io.Timestamp,
222 abs_file_path: []const u8,222 abs_file_path: []const u8,
223) AddCertsFromFilePathError!void {223) AddCertsFromFilePathError!void {
224 var file = try fs.openFileAbsolute(abs_file_path, .{});224 var file = try Io.Dir.openFileAbsolute(io, abs_file_path, .{});
225 defer file.close(io);225 defer file.close(io);
226 var file_reader = file.reader(io, &.{});226 var file_reader = file.reader(io, &.{});
227 return addCertsFromFile(cb, gpa, &file_reader, now.toSeconds());227 return addCertsFromFile(cb, gpa, &file_reader, now.toSeconds());
lib/std/fs.zig+7-259
...@@ -1,280 +1,28 @@...@@ -1,280 +1,28 @@
1//! File System.1//! File System.
2const builtin = @import("builtin");
3const native_os = builtin.os.tag;
42
5const std = @import("std.zig");3const std = @import("std.zig");
6const Io = std.Io;
7const root = @import("root");
8const mem = std.mem;
9const base64 = std.base64;
10const crypto = std.crypto;
11const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;
13const posix = std.posix;
14const windows = std.os.windows;
15
16const is_darwin = native_os.isDarwin();
17
18/// Deprecated.
19pub const AtomicFile = std.Io.File.Atomic;
20/// Deprecated.
21pub const Dir = std.Io.Dir;
22/// Deprecated.
23pub const File = std.Io.File;
244
5/// Deprecated, use `std.Io.Dir.path`.
25pub const path = @import("fs/path.zig");6pub const path = @import("fs/path.zig");
26pub const wasi = @import("fs/wasi.zig");7pub const wasi = @import("fs/wasi.zig");
278
28pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir;9pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir;
29pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError;10pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError;
3011
31/// The maximum length of a file path that the operating system will accept.
32///
33/// Paths, including those returned from file system operations, may be longer
34/// than this length, but such paths cannot be successfully passed back in
35/// other file system operations. However, all path components returned by file
36/// system operations are assumed to fit into a `u8` array of this length.
37///
38/// The byte count includes room for a null sentinel byte.
39///
40/// * On Windows, `[]u8` file paths are encoded as
41/// [WTF-8](https://wtf-8.codeberg.page/).
42/// * On WASI, `[]u8` file paths are encoded as valid UTF-8.
43/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with
44/// no particular encoding.
45pub const max_path_bytes = switch (native_os) {
46 .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => posix.PATH_MAX,
47 // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes.
48 // If it would require 4 WTF-8 bytes, then there would be a surrogate
49 // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
50 // +1 for the null byte at the end, which can be encoded in 1 byte.
51 .windows => windows.PATH_MAX_WIDE * 3 + 1,
52 else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX"))
53 root.os.PATH_MAX
54 else
55 @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)),
56};
57
58/// This represents the maximum size of a `[]u8` file name component that
59/// the platform's common file systems support. File name components returned by file system
60/// operations are likely to fit into a `u8` array of this length, but
61/// (depending on the platform) this assumption may not hold for every configuration.
62/// The byte count does not include a null sentinel byte.
63/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/).
64/// On WASI, file name components are encoded as valid UTF-8.
65/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
66pub const max_name_bytes = switch (native_os) {
67 .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => posix.NAME_MAX,
68 // Haiku's NAME_MAX includes the null terminator, so subtract one.
69 .haiku => posix.NAME_MAX - 1,
70 // Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
71 // If it would require 4 WTF-8 bytes, then there would be a surrogate
72 // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
73 .windows => windows.NAME_MAX * 3,
74 // For WASI, the MAX_NAME will depend on the host OS, so it needs to be
75 // as large as the largest max_name_bytes (Windows) in order to work on any host OS.
76 // TODO determine if this is a reasonable approach
77 .wasi => windows.NAME_MAX * 3,
78 else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX"))
79 root.os.NAME_MAX
80 else
81 @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)),
82};
83
84pub const base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;12pub const base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
8513
86/// Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.14/// Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
87pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null);15pub const base64_encoder = std.base64.Base64Encoder.init(base64_alphabet, null);
8816
89/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.17/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
90pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null);18pub const base64_decoder = std.base64.Base64Decoder.init(base64_alphabet, null);
91
92/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
93/// are absolute. See `Dir.copyFile` for a function that operates on both
94/// absolute and relative paths.
95/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
96/// On WASI, both paths should be encoded as valid UTF-8.
97/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
98pub fn copyFileAbsolute(
99 source_path: []const u8,
100 dest_path: []const u8,
101 args: Dir.CopyFileOptions,
102) !void {
103 assert(path.isAbsolute(source_path));
104 assert(path.isAbsolute(dest_path));
105 const my_cwd = cwd();
106 return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
107}
108
109test copyFileAbsolute {}
110
111/// Create a new directory, based on an absolute path.
112/// Asserts that the path is absolute. See `Dir.makeDir` for a function that operates
113/// on both absolute and relative paths.
114/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
115/// On WASI, `absolute_path` should be encoded as valid UTF-8.
116/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
117pub fn makeDirAbsolute(absolute_path: []const u8) !void {
118 assert(path.isAbsolute(absolute_path));
119 return posix.mkdir(absolute_path, Dir.default_mode);
120}
121
122test makeDirAbsolute {}
123
124/// Same as `makeDirAbsolute` except the parameter is null-terminated.
125pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {
126 assert(path.isAbsoluteZ(absolute_path_z));
127 return posix.mkdirZ(absolute_path_z, Dir.default_mode);
128}
129
130test makeDirAbsoluteZ {}
131
132/// Same as `Dir.deleteDir` except the path is absolute.
133/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
134/// On WASI, `dir_path` should be encoded as valid UTF-8.
135/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
136pub fn deleteDirAbsolute(dir_path: []const u8) !void {
137 assert(path.isAbsolute(dir_path));
138 return posix.rmdir(dir_path);
139}
140
141/// Same as `deleteDirAbsolute` except the path parameter is null-terminated.
142pub fn deleteDirAbsoluteZ(dir_path: [*:0]const u8) !void {
143 assert(path.isAbsoluteZ(dir_path));
144 return posix.rmdirZ(dir_path);
145}
146
147/// Deprecated in favor of `Io.Dir.cwd`.
148pub fn cwd() Io.Dir {
149 return .cwd();
150}
15119
152pub fn defaultWasiCwd() std.os.wasi.fd_t {20/// Deprecated, use `std.Io.Dir.max_path_bytes`.
153 // Expect the first preopen to be current working directory.21pub const max_path_bytes = std.Io.Dir.max_path_bytes;
154 return 3;22/// Deprecated, use `std.Io.Dir.max_name_bytes`.
155}23pub const max_name_bytes = std.Io.Dir.max_name_bytes;
156
157/// Opens a directory at the given path. The directory is a system resource that remains
158/// open until `close` is called on the result.
159/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path.
160///
161/// Asserts that the path parameter has no null bytes.
162/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
163/// On WASI, `absolute_path` should be encoded as valid UTF-8.
164/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
165pub fn openDirAbsolute(absolute_path: []const u8, flags: Dir.OpenOptions) File.OpenError!Dir {
166 assert(path.isAbsolute(absolute_path));
167 return cwd().openDir(absolute_path, flags);
168}
169
170/// Deprecated in favor of `Io.File.openAbsolute`.
171pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) Io.File.OpenError!Io.File {
172 var threaded: Io.Threaded = .init_single_threaded;
173 const io = threaded.ioBasic();
174 return Io.File.openAbsolute(io, absolute_path, flags);
175}
176
177/// Test accessing `path`.
178/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
179/// For example, instead of testing if a file exists and then opening it, just
180/// open it and handle the error for file not found.
181/// See `accessAbsoluteZ` for a function that accepts a null-terminated path.
182/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
183/// On WASI, `absolute_path` should be encoded as valid UTF-8.
184/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
185pub fn accessAbsolute(absolute_path: []const u8, flags: Io.Dir.AccessOptions) Dir.AccessError!void {
186 assert(path.isAbsolute(absolute_path));
187 try cwd().access(absolute_path, flags);
188}
189/// Creates, opens, or overwrites a file with write access, based on an absolute path.
190/// Call `File.close` to release the resource.
191/// Asserts that the path is absolute. See `Dir.createFile` for a function that
192/// operates on both absolute and relative paths.
193/// Asserts that the path parameter has no null bytes. See `createFileAbsoluteC` for a function
194/// that accepts a null-terminated path.
195/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
196/// On WASI, `absolute_path` should be encoded as valid UTF-8.
197/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
198pub fn createFileAbsolute(absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
199 assert(path.isAbsolute(absolute_path));
200 return cwd().createFile(absolute_path, flags);
201}
202
203/// Delete a file name and possibly the file it refers to, based on an absolute path.
204/// Asserts that the path is absolute. See `Dir.deleteFile` for a function that
205/// operates on both absolute and relative paths.
206/// Asserts that the path parameter has no null bytes.
207/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
208/// On WASI, `absolute_path` should be encoded as valid UTF-8.
209/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
210pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void {
211 assert(path.isAbsolute(absolute_path));
212 return cwd().deleteFile(absolute_path);
213}
214
215/// Removes a symlink, file, or directory.
216/// This is equivalent to `Dir.deleteTree` with the base directory.
217/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that
218/// operates on both absolute and relative paths.
219/// Asserts that the path parameter has no null bytes.
220/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
221/// On WASI, `absolute_path` should be encoded as valid UTF-8.
222/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
223pub fn deleteTreeAbsolute(io: Io, absolute_path: []const u8) !void {
224 assert(path.isAbsolute(absolute_path));
225 const dirname = path.dirname(absolute_path) orelse return error{
226 /// Attempt to remove the root file system path.
227 /// This error is unreachable if `absolute_path` is relative.
228 CannotDeleteRootDirectory,
229 }.CannotDeleteRootDirectory;
230
231 var dir = try cwd().openDir(dirname, .{});
232 defer dir.close(io);
233
234 return dir.deleteTree(path.basename(absolute_path));
235}
236
237/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
238/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
239/// one; the latter case is known as a dangling link.
240/// If `sym_link_path` exists, it will not be overwritten.
241/// See also `symLinkAbsoluteZ` and `symLinkAbsoluteW`.
242/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
243/// On WASI, both paths should be encoded as valid UTF-8.
244/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
245pub fn symLinkAbsolute(
246 target_path: []const u8,
247 sym_link_path: []const u8,
248 flags: Dir.SymLinkFlags,
249) !void {
250 assert(path.isAbsolute(target_path));
251 assert(path.isAbsolute(sym_link_path));
252 if (native_os == .windows) {
253 const target_path_w = try windows.sliceToPrefixedFileW(null, target_path);
254 const sym_link_path_w = try windows.sliceToPrefixedFileW(null, sym_link_path);
255 return windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory);
256 }
257 return posix.symlink(target_path, sym_link_path);
258}
259
260/// Windows-only. Same as `symLinkAbsolute` except the parameters are null-terminated, WTF16 LE encoded.
261/// Note that this function will by default try creating a symbolic link to a file. If you would
262/// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`.
263/// See also `symLinkAbsolute`, `symLinkAbsoluteZ`.
264pub fn symLinkAbsoluteW(
265 target_path_w: [*:0]const u16,
266 sym_link_path_w: [*:0]const u16,
267 flags: Dir.SymLinkFlags,
268) !void {
269 assert(path.isAbsoluteWindowsW(target_path_w));
270 assert(path.isAbsoluteWindowsW(sym_link_path_w));
271 return windows.CreateSymbolicLink(null, mem.span(sym_link_path_w), mem.span(target_path_w), flags.is_directory);
272}
27324
274test {25test {
275 _ = AtomicFile;
276 _ = Dir;
277 _ = File;
278 _ = path;26 _ = path;
279 _ = @import("fs/test.zig");27 _ = @import("fs/test.zig");
280 _ = @import("fs/get_app_data_dir.zig");28 _ = @import("fs/get_app_data_dir.zig");
lib/std/fs/test.zig+14-15
...@@ -2087,7 +2087,7 @@ test "'.' and '..' in absolute functions" {...@@ -2087,7 +2087,7 @@ test "'.' and '..' in absolute functions" {
2087 try fs.copyFileAbsolute(created_file_path, copied_file_path, .{});2087 try fs.copyFileAbsolute(created_file_path, copied_file_path, .{});
2088 const renamed_file_path = try fs.path.join(allocator, &.{ subdir_path, "../rename" });2088 const renamed_file_path = try fs.path.join(allocator, &.{ subdir_path, "../rename" });
2089 try fs.renameAbsolute(copied_file_path, renamed_file_path);2089 try fs.renameAbsolute(copied_file_path, renamed_file_path);
2090 const renamed_file = try fs.openFileAbsolute(renamed_file_path, .{});2090 const renamed_file = try Dir.openFileAbsolute(renamed_file_path, .{});
2091 renamed_file.close(io);2091 renamed_file.close(io);
2092 try fs.deleteFileAbsolute(renamed_file_path);2092 try fs.deleteFileAbsolute(renamed_file_path);
20932093
...@@ -2202,20 +2202,19 @@ test "invalid UTF-8/WTF-8 paths" {...@@ -2202,20 +2202,19 @@ test "invalid UTF-8/WTF-8 paths" {
2202 try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path));2202 try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path));
22032203
2204 if (native_os != .wasi and ctx.path_type != .relative) {2204 if (native_os != .wasi and ctx.path_type != .relative) {
2205 try testing.expectError(expected_err, fs.copyFileAbsolute(invalid_path, invalid_path, .{}));2205 try testing.expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{}));
2206 try testing.expectError(expected_err, fs.makeDirAbsolute(invalid_path));2206 try testing.expectError(expected_err, Dir.makeDirAbsolute(invalid_path));
2207 try testing.expectError(expected_err, fs.deleteDirAbsolute(invalid_path));2207 try testing.expectError(expected_err, Dir.deleteDirAbsolute(invalid_path));
2208 try testing.expectError(expected_err, fs.renameAbsolute(invalid_path, invalid_path));2208 try testing.expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path));
2209 try testing.expectError(expected_err, fs.openDirAbsolute(invalid_path, .{}));2209 try testing.expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{}));
2210 try testing.expectError(expected_err, fs.openFileAbsolute(invalid_path, .{}));2210 try testing.expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{}));
2211 try testing.expectError(expected_err, fs.accessAbsolute(invalid_path, .{}));2211 try testing.expectError(expected_err, Dir.accessAbsolute(invalid_path, .{}));
2212 try testing.expectError(expected_err, fs.createFileAbsolute(invalid_path, .{}));2212 try testing.expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{}));
2213 try testing.expectError(expected_err, fs.deleteFileAbsolute(invalid_path));2213 try testing.expectError(expected_err, Dir.deleteFileAbsolute(invalid_path));
2214 try testing.expectError(expected_err, fs.deleteTreeAbsolute(invalid_path));2214 var readlink_buf: [Dir.max_path_bytes]u8 = undefined;
2215 var readlink_buf: [fs.max_path_bytes]u8 = undefined;2215 try testing.expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf));
2216 try testing.expectError(expected_err, fs.readLinkAbsolute(invalid_path, &readlink_buf));2216 try testing.expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{}));
2217 try testing.expectError(expected_err, fs.symLinkAbsolute(invalid_path, invalid_path, .{}));2217 try testing.expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path));
2218 try testing.expectError(expected_err, fs.realpathAlloc(testing.allocator, invalid_path));
2219 }2218 }
2220 }2219 }
2221 }.impl);2220 }.impl);
lib/std/os.zig+5
...@@ -72,3 +72,8 @@ pub fn fstat_wasi(fd: posix.fd_t) FstatError!wasi.filestat_t {...@@ -72,3 +72,8 @@ pub fn fstat_wasi(fd: posix.fd_t) FstatError!wasi.filestat_t {
72 else => |err| return posix.unexpectedErrno(err),72 else => |err| return posix.unexpectedErrno(err),
73 }73 }
74}74}
75
76pub fn defaultWasiCwd() std.os.wasi.fd_t {
77 // Expect the first preopen to be current working directory.
78 return 3;
79}
lib/std/process.zig+1-1
...@@ -1576,7 +1576,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {...@@ -1576,7 +1576,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
1576/// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else1576/// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else
1577/// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`.1577/// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`.
1578pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {1578pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {
1579 const file = try std.fs.openFileAbsolute("/etc/passwd", .{});1579 const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{});
1580 defer file.close(io);1580 defer file.close(io);
1581 var buffer: [4096]u8 = undefined;1581 var buffer: [4096]u8 = undefined;
1582 var file_reader = file.reader(&buffer);1582 var file_reader = file.reader(&buffer);
lib/std/std.zig+1-1
...@@ -115,7 +115,7 @@ pub const Options = struct {...@@ -115,7 +115,7 @@ pub const Options = struct {
115 enable_segfault_handler: bool = debug.default_enable_segfault_handler,115 enable_segfault_handler: bool = debug.default_enable_segfault_handler,
116116
117 /// Function used to implement `std.fs.cwd` for WASI.117 /// Function used to implement `std.fs.cwd` for WASI.
118 wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd,118 wasiCwd: fn () os.wasi.fd_t = os.defaultWasiCwd,
119119
120 /// The current log level.120 /// The current log level.
121 log_level: log.Level = log.default_level,121 log_level: log.Level = log.default_level,
lib/std/zig/system.zig+1-1
...@@ -1024,7 +1024,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ...@@ -1024,7 +1024,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ
1024 };1024 };
10251025
1026 while (true) {1026 while (true) {
1027 const file = fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) {1027 const file = Io.Dir.openFileAbsolute(io, file_name, .{}) catch |err| switch (err) {
1028 error.NoSpaceLeft => return error.Unexpected,1028 error.NoSpaceLeft => return error.Unexpected,
1029 error.NameTooLong => return error.Unexpected,1029 error.NameTooLong => return error.Unexpected,
1030 error.PathAlreadyExists => return error.Unexpected,1030 error.PathAlreadyExists => return error.Unexpected,
lib/std/zig/system/linux.zig+1-1
...@@ -444,7 +444,7 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {...@@ -444,7 +444,7 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
444}444}
445445
446pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {446pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {
447 var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {447 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) {
448 else => return null,448 else => return null,
449 };449 };
450 defer file.close(io);450 defer file.close(io);