aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs/Dir.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/fs/Dir.zig')
-rw-r--r--lib/std/fs/Dir.zig288
1 files changed, 190 insertions, 98 deletions
diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig
index d097573122..67f0c0d724 100644
--- a/lib/std/fs/Dir.zig
+++ b/lib/std/fs/Dir.zig
@@ -663,35 +663,17 @@ fn iterateImpl(self: Dir, first_iter_start_value: bool) Iterator {
}
}
-pub const Walker = struct {
- stack: std.ArrayListUnmanaged(StackItem),
+pub const SelectiveWalker = struct {
+ stack: std.ArrayListUnmanaged(Walker.StackItem),
name_buffer: std.ArrayListUnmanaged(u8),
allocator: Allocator,
- pub const Entry = struct {
- /// The containing directory. This can be used to operate directly on `basename`
- /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
- /// The directory remains open until `next` or `deinit` is called.
- dir: Dir,
- basename: [:0]const u8,
- path: [:0]const u8,
- kind: Dir.Entry.Kind,
- };
-
- const StackItem = struct {
- iter: Dir.Iterator,
- dirname_len: usize,
- };
-
/// After each call to this function, and on deinit(), the memory returned
/// from this function becomes invalid. A copy must be made in order to keep
/// a reference to the path.
- pub fn next(self: *Walker) !?Walker.Entry {
- const gpa = self.allocator;
- while (self.stack.items.len != 0) {
- // `top` and `containing` become invalid after appending to `self.stack`
- var top = &self.stack.items[self.stack.items.len - 1];
- var containing = top;
+ pub fn next(self: *SelectiveWalker) !?Walker.Entry {
+ while (self.stack.items.len > 0) {
+ const top = &self.stack.items[self.stack.items.len - 1];
var dirname_len = top.dirname_len;
if (top.iter.next() catch |err| {
// If we get an error, then we want the user to be able to continue
@@ -703,36 +685,22 @@ pub const Walker = struct {
item.iter.dir.close();
}
return err;
- }) |base| {
+ }) |entry| {
self.name_buffer.shrinkRetainingCapacity(dirname_len);
if (self.name_buffer.items.len != 0) {
- try self.name_buffer.append(gpa, fs.path.sep);
+ try self.name_buffer.append(self.allocator, fs.path.sep);
dirname_len += 1;
}
- try self.name_buffer.ensureUnusedCapacity(gpa, base.name.len + 1);
- self.name_buffer.appendSliceAssumeCapacity(base.name);
+ try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1);
+ self.name_buffer.appendSliceAssumeCapacity(entry.name);
self.name_buffer.appendAssumeCapacity(0);
- if (base.kind == .directory) {
- var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
- error.NameTooLong => unreachable, // no path sep in base.name
- else => |e| return e,
- };
- {
- errdefer new_dir.close();
- try self.stack.append(gpa, .{
- .iter = new_dir.iterateAssumeFirstIteration(),
- .dirname_len = self.name_buffer.items.len - 1,
- });
- top = &self.stack.items[self.stack.items.len - 1];
- containing = &self.stack.items[self.stack.items.len - 2];
- }
- }
- return .{
- .dir = containing.iter.dir,
+ const walker_entry: Walker.Entry = .{
+ .dir = top.iter.dir,
.basename = self.name_buffer.items[dirname_len .. self.name_buffer.items.len - 1 :0],
.path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0],
- .kind = base.kind,
+ .kind = entry.kind,
};
+ return walker_entry;
} else {
var item = self.stack.pop().?;
if (self.stack.items.len != 0) {
@@ -743,20 +711,46 @@ pub const Walker = struct {
return null;
}
- pub fn deinit(self: *Walker) void {
- const gpa = self.allocator;
- // Close any remaining directories except the initial one (which is always at index 0)
- if (self.stack.items.len > 1) {
- for (self.stack.items[1..]) |*item| {
- item.iter.dir.close();
+ /// Traverses into the directory, continuing walking one level down.
+ pub fn enter(self: *SelectiveWalker, entry: Walker.Entry) !void {
+ if (entry.kind != .directory) {
+ @branchHint(.cold);
+ return;
+ }
+
+ var new_dir = entry.dir.openDir(entry.basename, .{ .iterate = true }) catch |err| {
+ switch (err) {
+ error.NameTooLong => unreachable,
+ else => |e| return e,
}
+ };
+ errdefer new_dir.close();
+
+ try self.stack.append(self.allocator, .{
+ .iter = new_dir.iterateAssumeFirstIteration(),
+ .dirname_len = self.name_buffer.items.len - 1,
+ });
+ }
+
+ pub fn deinit(self: *SelectiveWalker) void {
+ self.name_buffer.deinit(self.allocator);
+ self.stack.deinit(self.allocator);
+ }
+
+ /// Leaves the current directory, continuing walking one level up.
+ /// If the current entry is a directory entry, then the "current directory"
+ /// will pertain to that entry if `enter` is called before `leave`.
+ pub fn leave(self: *SelectiveWalker) void {
+ var item = self.stack.pop().?;
+ if (self.stack.items.len != 0) {
+ @branchHint(.likely);
+ item.iter.dir.close();
}
- self.stack.deinit(gpa);
- self.name_buffer.deinit(gpa);
}
};
-/// Recursively iterates over a directory.
+/// Recursively iterates over a directory, but requires the user to
+/// opt-in to recursing into each directory entry.
///
/// `self` must have been opened with `OpenOptions{.iterate = true}`.
///
@@ -765,7 +759,9 @@ pub const Walker = struct {
/// The order of returned file system entries is undefined.
///
/// `self` will not be closed after walking it.
-pub fn walk(self: Dir, allocator: Allocator) Allocator.Error!Walker {
+///
+/// See also `walk`.
+pub fn walkSelectively(self: Dir, allocator: Allocator) !SelectiveWalker {
var stack: std.ArrayListUnmanaged(Walker.StackItem) = .empty;
try stack.append(allocator, .{
@@ -780,6 +776,71 @@ pub fn walk(self: Dir, allocator: Allocator) Allocator.Error!Walker {
};
}
+pub const Walker = struct {
+ inner: SelectiveWalker,
+
+ pub const Entry = struct {
+ /// The containing directory. This can be used to operate directly on `basename`
+ /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
+ /// The directory remains open until `next` or `deinit` is called.
+ dir: Dir,
+ basename: [:0]const u8,
+ path: [:0]const u8,
+ kind: Dir.Entry.Kind,
+
+ /// Returns the depth of the entry relative to the initial directory.
+ /// Returns 1 for a direct child of the initial directory, 2 for an entry
+ /// within a direct child of the initial directory, etc.
+ pub fn depth(self: Walker.Entry) usize {
+ return mem.countScalar(u8, self.path, fs.path.sep) + 1;
+ }
+ };
+
+ const StackItem = struct {
+ iter: Dir.Iterator,
+ dirname_len: usize,
+ };
+
+ /// After each call to this function, and on deinit(), the memory returned
+ /// from this function becomes invalid. A copy must be made in order to keep
+ /// a reference to the path.
+ pub fn next(self: *Walker) !?Walker.Entry {
+ const entry = try self.inner.next();
+ if (entry != null and entry.?.kind == .directory) {
+ try self.inner.enter(entry.?);
+ }
+ return entry;
+ }
+
+ pub fn deinit(self: *Walker) void {
+ self.inner.deinit();
+ }
+
+ /// Leaves the current directory, continuing walking one level up.
+ /// If the current entry is a directory entry, then the "current directory"
+ /// is the directory pertaining to the current entry.
+ pub fn leave(self: *Walker) void {
+ self.inner.leave();
+ }
+};
+
+/// Recursively iterates over a directory.
+///
+/// `self` must have been opened with `OpenOptions{.iterate = true}`.
+///
+/// `Walker.deinit` releases allocated memory and directory handles.
+///
+/// The order of returned file system entries is undefined.
+///
+/// `self` will not be closed after walking it.
+///
+/// See also `walkSelectively`.
+pub fn walk(self: Dir, allocator: Allocator) Allocator.Error!Walker {
+ return .{
+ .inner = try walkSelectively(self, allocator),
+ };
+}
+
pub const OpenError = error{
FileNotFound,
NotDir,
@@ -794,7 +855,7 @@ pub const OpenError = error{
/// WASI-only; file paths must be valid UTF-8.
InvalidUtf8,
/// Windows-only; file paths provided by the user must be valid WTF-8.
- /// https://simonsapin.github.io/wtf-8/
+ /// https://wtf-8.codeberg.page/
InvalidWtf8,
BadPathName,
DeviceBusy,
@@ -812,7 +873,7 @@ pub fn close(self: *Dir) void {
/// To create a new file, see `createFile`.
/// Call `File.close` to release the resource.
/// Asserts that the path parameter has no null bytes.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
@@ -938,7 +999,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File
}
/// Same as `openFile` but Windows-only and the path parameter is
-/// [WTF-16](https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16) encoded.
+/// [WTF-16](https://wtf-8.codeberg.page/#potentially-ill-formed-utf-16) encoded.
pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File {
const w = windows;
const file: File = .{
@@ -977,7 +1038,7 @@ pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File
/// Creates, opens, or overwrites a file with write access.
/// Call `File.close` on the result when done.
/// Asserts that the path parameter has no null bytes.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
@@ -1089,7 +1150,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags
}
/// Same as `createFile` but Windows-only and the path parameter is
-/// [WTF-16](https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16) encoded.
+/// [WTF-16](https://wtf-8.codeberg.page/#potentially-ill-formed-utf-16) encoded.
pub fn createFileW(self: Dir, sub_path_w: []const u16, flags: File.CreateFlags) File.OpenError!File {
const w = windows;
const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0;
@@ -1134,7 +1195,7 @@ pub const MakeError = posix.MakeDirError;
/// Creates a single directory with a relative or absolute path.
/// To create multiple directories to make an entire path, see `makePath`.
/// To operate on only absolute paths, see `makeDirAbsolute`.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn makeDir(self: Dir, sub_path: []const u8) MakeError!void {
@@ -1160,7 +1221,7 @@ pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) MakeError!void {
/// Returns success if the path already exists and is a directory.
/// This function is not atomic, and if it returns an error, the file system may
/// have been modified regardless.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
/// Fails on an empty path with `error.BadPathName` as that is not a path that can be created.
@@ -1214,7 +1275,7 @@ pub fn makePathStatus(self: Dir, sub_path: []const u8) (MakeError || StatFileErr
/// Opens the dir if the path already exists and is a directory.
/// This function is not atomic, and if it returns an error, the file system may
/// have been modified regardless.
-/// `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
fn makeOpenPathAccessMaskW(self: Dir, sub_path: []const u8, access_mask: u32, no_follow: bool) (MakeError || OpenError || StatFileError)!Dir {
const w = windows;
var it = try fs.path.componentIterator(sub_path);
@@ -1265,7 +1326,7 @@ fn makeOpenPathAccessMaskW(self: Dir, sub_path: []const u8, access_mask: u32, no
/// This function performs `makePath`, followed by `openDir`.
/// If supported by the OS, this operation is atomic. It is not atomic on
/// all operating systems.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn makeOpenPath(self: Dir, sub_path: []const u8, open_dir_options: OpenOptions) (MakeError || OpenError || StatFileError)!Dir {
@@ -1296,9 +1357,9 @@ pub const RealPathError = posix.RealPathError;
/// `pathname` relative to this `Dir`. If `pathname` is absolute, ignores this
/// `Dir` handle and returns the canonicalized absolute pathname of `pathname`
/// argument.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
-/// On Windows, the result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, the result is encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On other platforms, the result is an opaque sequence of bytes with no particular encoding.
/// This function is not universally supported by all platforms.
/// Currently supported hosts are: Linux, macOS, and Windows.
@@ -1308,8 +1369,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
@compileError("realpath is not available on WASI");
}
if (native_os == .windows) {
- const pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname);
- return self.realpathW(pathname_w.span(), out_buffer);
+ var pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname);
+
+ const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data);
+
+ const len = std.unicode.calcWtf8Len(wide_slice);
+ if (len > out_buffer.len)
+ return error.NameTooLong;
+
+ const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
+ return out_buffer[0..end_index];
}
const pathname_c = try posix.toPosixPath(pathname);
return self.realpathZ(&pathname_c, out_buffer);
@@ -1319,8 +1388,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
/// See also `Dir.realpath`, `realpathZ`.
pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 {
if (native_os == .windows) {
- const pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname);
- return self.realpathW(pathname_w.span(), out_buffer);
+ var pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname);
+
+ const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data);
+
+ const len = std.unicode.calcWtf8Len(wide_slice);
+ if (len > out_buffer.len)
+ return error.NameTooLong;
+
+ const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
+ return out_buffer[0..end_index];
}
var flags: posix.O = .{};
@@ -1349,10 +1426,31 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE
return result;
}
+/// Deprecated: use `realpathW2`.
+///
/// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded.
-/// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// The result is encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// See also `Dir.realpath`, `realpathW`.
pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 {
+ var wide_buf: [std.os.windows.PATH_MAX_WIDE]u16 = undefined;
+ const wide_slice = try self.realpathW2(pathname, &wide_buf);
+
+ const len = std.unicode.calcWtf8Len(wide_slice);
+ if (len > out_buffer.len) return error.NameTooLong;
+
+ const end_index = std.unicode.wtf16LeToWtf8(&out_buffer, wide_slice);
+ return out_buffer[0..end_index];
+}
+
+/// Windows-only. Same as `Dir.realpath` except
+/// * `pathname` and the result are WTF-16 LE encoded
+/// * `pathname` is relative or has the NT namespace prefix. See `windows.wToPrefixedFileW` for details.
+///
+/// Additionally, `pathname` will never be accessed after `out_buffer` has been written to, so it
+/// is safe to reuse a single buffer for both.
+///
+/// See also `Dir.realpath`, `realpathW`.
+pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 {
const w = windows;
const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
@@ -1373,13 +1471,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr
};
defer w.CloseHandle(h_file);
- var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined;
- const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &wide_buf);
- const len = std.unicode.calcWtf8Len(wide_slice);
- if (len > out_buffer.len)
- return error.NameTooLong;
- const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
- return out_buffer[0..end_index];
+ return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer);
}
pub const RealPathAllocError = RealPathError || Allocator.Error;
@@ -1437,7 +1529,7 @@ pub const OpenOptions = struct {
/// open until `close` is called on the result.
/// The directory cannot be iterated unless the `iterate` option is set to `true`.
///
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
/// Asserts that the path parameter has no null bytes.
@@ -1652,7 +1744,7 @@ fn makeOpenDirAccessMaskW(self: Dir, sub_path_w: [*:0]const u16, access_mask: u3
pub const DeleteFileError = posix.UnlinkError;
/// Delete a file name and possibly the file it refers to, based on an open directory handle.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
/// Asserts that the path parameter has no null bytes.
@@ -1713,7 +1805,7 @@ pub const DeleteDirError = error{
/// WASI-only; file paths must be valid UTF-8.
InvalidUtf8,
/// Windows-only; file paths provided by the user must be valid WTF-8.
- /// https://simonsapin.github.io/wtf-8/
+ /// https://wtf-8.codeberg.page/
InvalidWtf8,
BadPathName,
/// On Windows, `\\server` or `\\server\share` was not found.
@@ -1724,7 +1816,7 @@ pub const DeleteDirError = error{
/// Returns `error.DirNotEmpty` if the directory is not empty.
/// To delete a directory recursively, see `deleteTree`.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
/// Asserts that the path parameter has no null bytes.
@@ -1766,7 +1858,7 @@ pub const RenameError = posix.RenameError;
/// If new_sub_path already exists, it will be replaced.
/// Renaming a file over an existing directory or a directory
/// over an existing file will fail with `error.IsDir` or `error.NotDir`
-/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, both paths should be encoded as valid UTF-8.
/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
pub fn rename(self: Dir, old_sub_path: []const u8, new_sub_path: []const u8) RenameError!void {
@@ -1797,7 +1889,7 @@ pub const SymLinkFlags = struct {
/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
/// one; the latter case is known as a dangling link.
/// If `sym_link_path` exists, it will not be overwritten.
-/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, both paths should be encoded as valid UTF-8.
/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
pub fn symLink(
@@ -1880,7 +1972,7 @@ pub fn symLinkW(
/// Same as `symLink`, except tries to create the symbolic link until it
/// succeeds or encounters an error other than `error.PathAlreadyExists`.
///
-/// * On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// * On WASI, both paths should be encoded as valid UTF-8.
/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
pub fn atomicSymLink(
@@ -1926,7 +2018,7 @@ pub const ReadLinkError = posix.ReadLinkError;
/// Read value of a symbolic link.
/// The return value is a slice of `buffer`, from index `0`.
/// Asserts that the path parameter has no null bytes.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ReadLinkError![]u8 {
@@ -1966,7 +2058,7 @@ pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u8) ![]u8 {
/// the situation is ambiguous. It could either mean that the entire file was read, and
/// it exactly fits the buffer, or it could mean the buffer was not big enough for the
/// entire file.
-/// On Windows, `file_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `file_path` should be encoded as valid UTF-8.
/// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding.
pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 {
@@ -1993,7 +2085,7 @@ pub const ReadFileAllocError = File.OpenError || File.ReadError || Allocator.Err
/// `File.Reader` which handles this seamlessly.
pub fn readFileAlloc(
dir: Dir,
- /// On Windows, should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+ /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, should be encoded as valid UTF-8.
/// On other platforms, an opaque sequence of bytes with no particular encoding.
sub_path: []const u8,
@@ -2012,7 +2104,7 @@ pub fn readFileAlloc(
/// `File.Reader`.
pub fn readFileAllocOptions(
dir: Dir,
- /// On Windows, should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+ /// On Windows, should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, should be encoded as valid UTF-8.
/// On other platforms, an opaque sequence of bytes with no particular encoding.
sub_path: []const u8,
@@ -2056,7 +2148,7 @@ pub const DeleteTreeError = error{
InvalidUtf8,
/// Windows-only; file paths provided by the user must be valid WTF-8.
- /// https://simonsapin.github.io/wtf-8/
+ /// https://wtf-8.codeberg.page/
InvalidWtf8,
/// On Windows, file paths cannot contain these characters:
@@ -2071,7 +2163,7 @@ pub const DeleteTreeError = error{
/// removes it. If it cannot be removed because it is a non-empty directory,
/// this function recursively removes its entries and then tries again.
/// This operation is not atomic on most file systems.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
@@ -2278,7 +2370,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
/// Like `deleteTree`, but only keeps one `Iterator` active at a time to minimize the function's stack size.
/// This is slower than `deleteTree` but uses less stack space.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn deleteTreeMinStackSize(self: Dir, sub_path: []const u8) DeleteTreeError!void {
@@ -2476,7 +2568,7 @@ fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File
pub const WriteFileError = File.WriteError || File.OpenError;
pub const WriteFileOptions = struct {
- /// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+ /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
sub_path: []const u8,
@@ -2494,7 +2586,7 @@ pub fn writeFile(self: Dir, options: WriteFileOptions) WriteFileError!void {
pub const AccessError = posix.AccessError;
/// Test accessing `sub_path`.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
@@ -2549,7 +2641,7 @@ pub const PrevStatus = enum {
/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
/// Returns the previous status of the file before updating.
/// If any of the directories do not exist for dest_path, they are created.
-/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, both paths should be encoded as valid UTF-8.
/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
pub fn updateFile(
@@ -2621,7 +2713,7 @@ pub const CopyFileError = File.OpenError || File.StatError ||
/// dest_path.
///
/// On Windows, both paths should be encoded as
-/// [WTF-8](https://simonsapin.github.io/wtf-8/). On WASI, both paths should be
+/// [WTF-8](https://wtf-8.codeberg.page/). On WASI, both paths should be
/// encoded as valid UTF-8. On other platforms, both paths are an opaque
/// sequence of bytes with no particular encoding.
pub fn copyFile(
@@ -2666,7 +2758,7 @@ pub const AtomicFileOptions = struct {
/// Always call `AtomicFile.deinit` to clean up, regardless of whether
/// `AtomicFile.finish` succeeded. `dest_path` must remain valid until
/// `AtomicFile.deinit` is called.
-/// On Windows, `dest_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `dest_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `dest_path` should be encoded as valid UTF-8.
/// On other platforms, `dest_path` is an opaque sequence of bytes with no particular encoding.
pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions) !AtomicFile {
@@ -2700,7 +2792,7 @@ pub const StatFileError = File.OpenError || File.StatError || posix.FStatAtError
/// Symlinks are followed.
///
/// `sub_path` may be absolute, in which case `self` is ignored.
-/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
+/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {