aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-12-06 21:06:30 -0800
committerAndrew Kelley <andrew@ziglang.org>2025-12-23 22:15:08 -0800
commit916998315967f73c91e682e9ea05dd3232818654 (patch)
tree6cd1ee9b952441c6b6ea1ddbad17a5cfd4b5f860 /lib/std
parent877032ec6a0007316f42658d12042f1473de4856 (diff)
downloadzig-916998315967f73c91e682e9ea05dd3232818654.tar.gz
zig-916998315967f73c91e682e9ea05dd3232818654.zip
std.fs: migrate most of the API elsewhere
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Io/Dir.zig173
-rw-r--r--lib/std/Io/File.zig22
-rw-r--r--lib/std/crypto/Certificate/Bundle.zig2
-rw-r--r--lib/std/fs.zig266
-rw-r--r--lib/std/fs/test.zig29
-rw-r--r--lib/std/os.zig5
-rw-r--r--lib/std/process.zig2
-rw-r--r--lib/std/std.zig2
-rw-r--r--lib/std/zig/system.zig2
-rw-r--r--lib/std/zig/system/linux.zig2
10 files changed, 193 insertions, 312 deletions
diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig
index 71ea3b465a..3b552a556a 100644
--- a/lib/std/Io/Dir.zig
+++ b/lib/std/Io/Dir.zig
@@ -1,4 +1,5 @@
const Dir = @This();
+const root = @import("root");
const builtin = @import("builtin");
const native_os = builtin.os.tag;
@@ -11,6 +12,61 @@ const Allocator = std.mem.Allocator;
handle: Handle,
+pub const path = std.fs.path;
+
+/// The maximum length of a file path that the operating system will accept.
+///
+/// Paths, including those returned from file system operations, may be longer
+/// than this length, but such paths cannot be successfully passed back in
+/// other file system operations. However, all path components returned by file
+/// system operations are assumed to fit into a `u8` array of this length.
+///
+/// The byte count includes room for a null sentinel byte.
+///
+/// * On Windows, `[]u8` file paths are encoded as
+/// [WTF-8](https://wtf-8.codeberg.page/).
+/// * On WASI, `[]u8` file paths are encoded as valid UTF-8.
+/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with
+/// no particular encoding.
+pub const max_path_bytes = switch (native_os) {
+ .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => std.posix.PATH_MAX,
+ // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes.
+ // If it would require 4 WTF-8 bytes, then there would be a surrogate
+ // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
+ // +1 for the null byte at the end, which can be encoded in 1 byte.
+ .windows => std.os.windows.PATH_MAX_WIDE * 3 + 1,
+ else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX"))
+ root.os.PATH_MAX
+ else
+ @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)),
+};
+
+/// This represents the maximum size of a `[]u8` file name component that
+/// the platform's common file systems support. File name components returned by file system
+/// operations are likely to fit into a `u8` array of this length, but
+/// (depending on the platform) this assumption may not hold for every configuration.
+/// The byte count does not include a null sentinel byte.
+/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/).
+/// On WASI, file name components are encoded as valid UTF-8.
+/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
+pub const max_name_bytes = switch (native_os) {
+ .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => std.posix.NAME_MAX,
+ // Haiku's NAME_MAX includes the null terminator, so subtract one.
+ .haiku => std.posix.NAME_MAX - 1,
+ // Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
+ // If it would require 4 WTF-8 bytes, then there would be a surrogate
+ // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
+ .windows => std.os.windows.NAME_MAX * 3,
+ // For WASI, the MAX_NAME will depend on the host OS, so it needs to be
+ // as large as the largest max_name_bytes (Windows) in order to work on any host OS.
+ // TODO determine if this is a reasonable approach
+ .wasi => std.os.windows.NAME_MAX * 3,
+ else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX"))
+ root.os.NAME_MAX
+ else
+ @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)),
+};
+
pub const Entry = struct {
name: []const u8,
kind: File.Kind,
@@ -148,7 +204,7 @@ pub const SelectiveWalker = struct {
}) |entry| {
self.name_buffer.shrinkRetainingCapacity(dirname_len);
if (self.name_buffer.items.len != 0) {
- try self.name_buffer.append(self.allocator, std.fs.path.sep);
+ try self.name_buffer.append(self.allocator, path.sep);
dirname_len += 1;
}
try self.name_buffer.ensureUnusedCapacity(self.allocator, entry.name.len + 1);
@@ -252,7 +308,7 @@ pub const Walker = struct {
/// 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 std.mem.countScalar(u8, self.path, std.fs.path.sep) + 1;
+ return std.mem.countScalar(u8, self.path, path.sep) + 1;
}
};
@@ -340,6 +396,11 @@ pub fn access(dir: Dir, io: Io, sub_path: []const u8, options: AccessOptions) Ac
return io.vtable.dirAccess(io.userdata, dir, sub_path, options);
}
+pub fn accessAbsolute(io: Io, absolute_path: []const u8, options: AccessOptions) AccessError!void {
+ assert(path.isAbsolute(absolute_path));
+ return access(.cwd(), io, absolute_path, options);
+}
+
pub const OpenError = error{
FileNotFound,
NotDir,
@@ -379,6 +440,11 @@ pub fn openDir(dir: Dir, io: Io, sub_path: []const u8, options: OpenOptions) Ope
return io.vtable.dirOpenDir(io.userdata, dir, sub_path, options);
}
+pub fn openDirAbsolute(io: Io, absolute_path: []const u8, options: OpenOptions) OpenError!Dir {
+ assert(path.isAbsolute(absolute_path));
+ return openDir(.cwd(), io, absolute_path, options);
+}
+
pub fn close(dir: Dir, io: Io) void {
return io.vtable.dirClose(io.userdata, dir);
}
@@ -396,6 +462,11 @@ pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) F
return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags);
}
+pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
+ assert(path.isAbsolute(absolute_path));
+ return openFile(.cwd(), io, absolute_path, flags);
+}
+
/// Creates, opens, or overwrites a file with write access.
///
/// 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
return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags);
}
+pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
+ return createFile(.cwd(), io, absolute_path, flags);
+}
+
pub const WriteFileOptions = struct {
/// 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.
@@ -476,7 +551,7 @@ pub fn updateFile(
}
}
- if (std.fs.path.dirname(dest_path)) |dirname| {
+ if (path.dirname(dest_path)) |dirname| {
try dest_dir.makePath(io, dirname, .default_dir);
}
@@ -556,6 +631,21 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions)
return io.vtable.dirMake(io.userdata, dir, sub_path, permissions);
}
+/// Create a new directory, based on an absolute path.
+///
+/// Asserts that the path is absolute. See `makeDir` for a function that
+/// operates on both absolute and relative paths.
+///
+/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
+/// On WASI, `absolute_path` should be encoded as valid UTF-8.
+/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
+pub fn makeDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissions) MakeError!void {
+ assert(path.isAbsolute(absolute_path));
+ return makeDir(.cwd(), io, absolute_path, permissions);
+}
+
+test makeDirAbsolute {}
+
pub const MakePathError = MakeError || StatPathError;
/// Creates parent directories with default permissions as necessary to ensure
@@ -703,19 +793,20 @@ pub const RealPathAllocError = RealPathError || Allocator.Error;
/// Same as `realPath` except allocates result.
pub fn realPathAlloc(dir: Dir, io: Io, sub_path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {
- var buffer: [std.fs.max_path_bytes]u8 = undefined;
+ var buffer: [max_path_bytes]u8 = undefined;
const n = try realPath(dir, io, sub_path, &buffer);
return allocator.dupeZ(u8, buffer[0..n]);
}
-pub fn realPathAbsolute(io: Io, path: []const u8, out_buffer: []u8) RealPathError!usize {
- return io.vtable.dirRealPath(io.userdata, .cwd(), path, out_buffer);
+pub fn realPathAbsolute(io: Io, absolute_path: []const u8, out_buffer: []u8) RealPathError!usize {
+ assert(path.isAbsolute(absolute_path));
+ return io.vtable.dirRealPath(io.userdata, .cwd(), absolute_path, out_buffer);
}
/// Same as `realPathAbsolute` except allocates result.
-pub fn realPathAbsoluteAlloc(io: Io, path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {
- var buffer: [std.fs.max_path_bytes]u8 = undefined;
- const n = try realPathAbsolute(io, path, &buffer);
+pub fn realPathAbsoluteAlloc(io: Io, absolute_path: []const u8, allocator: Allocator) RealPathAllocError![:0]u8 {
+ var buffer: [max_path_bytes]u8 = undefined;
+ const n = try realPathAbsolute(io, absolute_path, &buffer);
return allocator.dupeZ(u8, buffer[0..n]);
}
@@ -754,6 +845,13 @@ pub fn deleteFile(dir: Dir, io: Io, sub_path: []const u8) DeleteFileError!void {
return io.vtable.dirDeleteFile(io.userdata, dir, sub_path);
}
+pub fn deleteFileAbsolute(io: Io, absolute_path: []const u8) DeleteFileError!void {
+ assert(path.isAbsolute(absolute_path));
+ return deleteFile(.cwd(), io, absolute_path);
+}
+
+test deleteFileAbsolute {}
+
pub const DeleteDirError = error{
DirNotEmpty,
FileNotFound,
@@ -785,6 +883,16 @@ pub fn deleteDir(dir: Dir, io: Io, sub_path: []const u8) DeleteDirError!void {
return io.vtable.dirDeleteDir(io.userdata, dir, sub_path);
}
+/// Same as `deleteDir` except the path is absolute.
+///
+/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
+/// On WASI, `dir_path` should be encoded as valid UTF-8.
+/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
+pub fn deleteDirAbsolute(io: Io, absolute_path: []const u8) DeleteDirError!void {
+ assert(path.isAbsolute(absolute_path));
+ return deleteDir(.cwd(), io, absolute_path);
+}
+
pub const RenameError = error{
/// In WASI, this error may occur when the file descriptor does
/// not hold the required rights to rename a resource by path relative to it.
@@ -893,6 +1001,17 @@ pub fn symLink(
return io.vtable.dirSymLink(io.userdata, dir, target_path, sym_link_path, flags);
}
+pub fn symLinkAbsolute(
+ io: Io,
+ target_path: []const u8,
+ sym_link_path: []const u8,
+ flags: SymLinkFlags,
+) SymLinkError!void {
+ assert(path.isAbsolute(target_path));
+ assert(path.isAbsolute(sym_link_path));
+ return symLink(.cwd(), io, target_path, sym_link_path, flags);
+}
+
/// Same as `symLink`, except tries to create the symbolic link until it
/// succeeds or encounters an error other than `error.PathAlreadyExists`.
///
@@ -913,15 +1032,15 @@ pub fn symLinkAtomic(
else => |e| return e,
}
- const dirname = std.fs.path.dirname(sym_link_path) orelse ".";
+ const dirname = path.dirname(sym_link_path) orelse ".";
const rand_len = @sizeOf(u64) * 2;
const temp_path_len = dirname.len + 1 + rand_len;
- var temp_path_buf: [std.fs.max_path_bytes]u8 = undefined;
+ var temp_path_buf: [max_path_bytes]u8 = undefined;
if (temp_path_len > temp_path_buf.len) return error.NameTooLong;
@memcpy(temp_path_buf[0..dirname.len], dirname);
- temp_path_buf[dirname.len] = std.fs.path.sep;
+ temp_path_buf[dirname.len] = path.sep;
const temp_path = temp_path_buf[0..temp_path_len];
@@ -985,8 +1104,8 @@ pub fn readLink(dir: Dir, io: Io, sub_path: []const u8, buffer: []u8) ReadLinkEr
/// On Windows, `path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
/// On WASI, `path` should be encoded as valid UTF-8.
/// On other platforms, `path` is an opaque sequence of bytes with no particular encoding.
-pub fn readLinkAbsolute(io: Io, path: []const u8, buffer: []u8) ReadLinkError!usize {
- assert(std.fs.path.isAbsolute(path));
+pub fn readLinkAbsolute(io: Io, absolute_path: []const u8, buffer: []u8) ReadLinkError!usize {
+ assert(path.isAbsolute(absolute_path));
return io.vtable.dirReadLink(io.userdata, .cwd(), path, buffer);
}
@@ -1298,7 +1417,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,
// Valid use of max_path_bytes because dir_name_buf will only
// ever store a single path component that was returned from the
// filesystem.
- var dir_name_buf: [std.fs.max_path_bytes]u8 = undefined;
+ var dir_name_buf: [max_path_bytes]u8 = undefined;
var dir_name: []const u8 = sub_path;
// Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.
@@ -1521,6 +1640,26 @@ pub fn copyFile(
try atomic_file.finish();
}
+/// Same as `copyFile`, except asserts that both `source_path` and `dest_path`
+/// are absolute.
+///
+/// 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 copyFileAbsolute(
+ source_path: []const u8,
+ dest_path: []const u8,
+ io: Io,
+ options: CopyFileOptions,
+) !void {
+ assert(path.isAbsolute(source_path));
+ assert(path.isAbsolute(dest_path));
+ const my_cwd = cwd();
+ return copyFile(my_cwd, source_path, my_cwd, dest_path, io, options);
+}
+
+test copyFileAbsolute {}
+
pub const AtomicFileOptions = struct {
permissions: File.Permissions = .default_file,
make_path: bool = false,
@@ -1538,13 +1677,13 @@ pub const AtomicFileOptions = struct {
/// 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(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFileOptions) !File.Atomic {
- if (std.fs.path.dirname(dest_path)) |dirname| {
+ if (path.dirname(dest_path)) |dirname| {
const dir = if (options.make_path)
try parent.makeOpenPath(io, dirname, .{})
else
try parent.openDir(io, dirname, .{});
- return .init(std.fs.path.basename(dest_path), options.permissions, dir, true, options.write_buffer);
+ return .init(path.basename(dest_path), options.permissions, dir, true, options.write_buffer);
} else {
return .init(dest_path, options.permissions, parent, false, options.write_buffer);
}
diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig
index b24c0b5100..8e71f648e2 100644
--- a/lib/std/Io/File.zig
+++ b/lib/std/Io/File.zig
@@ -489,22 +489,6 @@ pub const WriteFileStreamingError = error{
SystemResources,
} || Io.Cancelable || Io.UnexpectedError;
-/// Opens a file for reading or writing, without attempting to create a new
-/// file, based on an absolute path.
-///
-/// Returns an open resource to be released with `close`.
-///
-/// Asserts that the path is absolute. See `Dir.openFile` for a function that
-/// operates on both absolute and relative paths.
-///
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn openAbsolute(io: Io, absolute_path: []const u8, flags: OpenFlags) OpenError!File {
- assert(std.fs.path.isAbsolute(absolute_path));
- return Io.Dir.cwd().openFile(io, absolute_path, flags);
-}
-
pub const SeekError = error{
Unseekable,
/// The file descriptor does not hold the required rights to seek on it.
@@ -579,3 +563,9 @@ pub const DowngradeLockError = Io.Cancelable || Io.UnexpectedError;
pub fn downgradeLock(file: File, io: Io) LockError!void {
return io.vtable.fileDowngradeLock(io.userdata, file);
}
+
+test {
+ _ = Reader;
+ _ = Writer;
+ _ = Atomic;
+}
diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig
index eb60ad37a8..d4a9f1e757 100644
--- a/lib/std/crypto/Certificate/Bundle.zig
+++ b/lib/std/crypto/Certificate/Bundle.zig
@@ -221,7 +221,7 @@ pub fn addCertsFromFilePathAbsolute(
now: Io.Timestamp,
abs_file_path: []const u8,
) AddCertsFromFilePathError!void {
- var file = try fs.openFileAbsolute(abs_file_path, .{});
+ var file = try Io.Dir.openFileAbsolute(io, abs_file_path, .{});
defer file.close(io);
var file_reader = file.reader(io, &.{});
return addCertsFromFile(cb, gpa, &file_reader, now.toSeconds());
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 78c924f8d9..5f2d36323a 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1,280 +1,28 @@
//! File System.
-const builtin = @import("builtin");
-const native_os = builtin.os.tag;
const std = @import("std.zig");
-const Io = std.Io;
-const root = @import("root");
-const mem = std.mem;
-const base64 = std.base64;
-const crypto = std.crypto;
-const Allocator = std.mem.Allocator;
-const assert = std.debug.assert;
-const posix = std.posix;
-const windows = std.os.windows;
-
-const is_darwin = native_os.isDarwin();
-
-/// Deprecated.
-pub const AtomicFile = std.Io.File.Atomic;
-/// Deprecated.
-pub const Dir = std.Io.Dir;
-/// Deprecated.
-pub const File = std.Io.File;
+/// Deprecated, use `std.Io.Dir.path`.
pub const path = @import("fs/path.zig");
pub const wasi = @import("fs/wasi.zig");
pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir;
pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError;
-/// The maximum length of a file path that the operating system will accept.
-///
-/// Paths, including those returned from file system operations, may be longer
-/// than this length, but such paths cannot be successfully passed back in
-/// other file system operations. However, all path components returned by file
-/// system operations are assumed to fit into a `u8` array of this length.
-///
-/// The byte count includes room for a null sentinel byte.
-///
-/// * On Windows, `[]u8` file paths are encoded as
-/// [WTF-8](https://wtf-8.codeberg.page/).
-/// * On WASI, `[]u8` file paths are encoded as valid UTF-8.
-/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with
-/// no particular encoding.
-pub const max_path_bytes = switch (native_os) {
- .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .illumos, .plan9, .emscripten, .wasi, .serenity => posix.PATH_MAX,
- // Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes.
- // If it would require 4 WTF-8 bytes, then there would be a surrogate
- // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
- // +1 for the null byte at the end, which can be encoded in 1 byte.
- .windows => windows.PATH_MAX_WIDE * 3 + 1,
- else => if (@hasDecl(root, "os") and @hasDecl(root.os, "PATH_MAX"))
- root.os.PATH_MAX
- else
- @compileError("PATH_MAX not implemented for " ++ @tagName(native_os)),
-};
-
-/// This represents the maximum size of a `[]u8` file name component that
-/// the platform's common file systems support. File name components returned by file system
-/// operations are likely to fit into a `u8` array of this length, but
-/// (depending on the platform) this assumption may not hold for every configuration.
-/// The byte count does not include a null sentinel byte.
-/// On Windows, `[]u8` file name components are encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, file name components are encoded as valid UTF-8.
-/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
-pub const max_name_bytes = switch (native_os) {
- .linux, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .freebsd, .openbsd, .netbsd, .dragonfly, .illumos, .serenity => posix.NAME_MAX,
- // Haiku's NAME_MAX includes the null terminator, so subtract one.
- .haiku => posix.NAME_MAX - 1,
- // Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
- // If it would require 4 WTF-8 bytes, then there would be a surrogate
- // pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
- .windows => windows.NAME_MAX * 3,
- // For WASI, the MAX_NAME will depend on the host OS, so it needs to be
- // as large as the largest max_name_bytes (Windows) in order to work on any host OS.
- // TODO determine if this is a reasonable approach
- .wasi => windows.NAME_MAX * 3,
- else => if (@hasDecl(root, "os") and @hasDecl(root.os, "NAME_MAX"))
- root.os.NAME_MAX
- else
- @compileError("NAME_MAX not implemented for " ++ @tagName(native_os)),
-};
-
pub const base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
/// Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
-pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null);
+pub const base64_encoder = std.base64.Base64Encoder.init(base64_alphabet, null);
/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
-pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null);
-
-/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
-/// are absolute. See `Dir.copyFile` for a function that operates on both
-/// absolute and relative paths.
-/// 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 copyFileAbsolute(
- source_path: []const u8,
- dest_path: []const u8,
- args: Dir.CopyFileOptions,
-) !void {
- assert(path.isAbsolute(source_path));
- assert(path.isAbsolute(dest_path));
- const my_cwd = cwd();
- return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
-}
-
-test copyFileAbsolute {}
-
-/// Create a new directory, based on an absolute path.
-/// Asserts that the path is absolute. See `Dir.makeDir` for a function that operates
-/// on both absolute and relative paths.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn makeDirAbsolute(absolute_path: []const u8) !void {
- assert(path.isAbsolute(absolute_path));
- return posix.mkdir(absolute_path, Dir.default_mode);
-}
-
-test makeDirAbsolute {}
-
-/// Same as `makeDirAbsolute` except the parameter is null-terminated.
-pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {
- assert(path.isAbsoluteZ(absolute_path_z));
- return posix.mkdirZ(absolute_path_z, Dir.default_mode);
-}
-
-test makeDirAbsoluteZ {}
-
-/// Same as `Dir.deleteDir` except the path is absolute.
-/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `dir_path` should be encoded as valid UTF-8.
-/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
-pub fn deleteDirAbsolute(dir_path: []const u8) !void {
- assert(path.isAbsolute(dir_path));
- return posix.rmdir(dir_path);
-}
-
-/// Same as `deleteDirAbsolute` except the path parameter is null-terminated.
-pub fn deleteDirAbsoluteZ(dir_path: [*:0]const u8) !void {
- assert(path.isAbsoluteZ(dir_path));
- return posix.rmdirZ(dir_path);
-}
-
-/// Deprecated in favor of `Io.Dir.cwd`.
-pub fn cwd() Io.Dir {
- return .cwd();
-}
+pub const base64_decoder = std.base64.Base64Decoder.init(base64_alphabet, null);
-pub fn defaultWasiCwd() std.os.wasi.fd_t {
- // Expect the first preopen to be current working directory.
- return 3;
-}
-
-/// Opens a directory at the given path. The directory is a system resource that remains
-/// open until `close` is called on the result.
-/// See `openDirAbsoluteZ` for a function that accepts a null-terminated path.
-///
-/// Asserts that the path parameter has no null bytes.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn openDirAbsolute(absolute_path: []const u8, flags: Dir.OpenOptions) File.OpenError!Dir {
- assert(path.isAbsolute(absolute_path));
- return cwd().openDir(absolute_path, flags);
-}
-
-/// Deprecated in favor of `Io.File.openAbsolute`.
-pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) Io.File.OpenError!Io.File {
- var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.ioBasic();
- return Io.File.openAbsolute(io, absolute_path, flags);
-}
-
-/// Test accessing `path`.
-/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
-/// For example, instead of testing if a file exists and then opening it, just
-/// open it and handle the error for file not found.
-/// See `accessAbsoluteZ` for a function that accepts a null-terminated path.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn accessAbsolute(absolute_path: []const u8, flags: Io.Dir.AccessOptions) Dir.AccessError!void {
- assert(path.isAbsolute(absolute_path));
- try cwd().access(absolute_path, flags);
-}
-/// Creates, opens, or overwrites a file with write access, based on an absolute path.
-/// Call `File.close` to release the resource.
-/// Asserts that the path is absolute. See `Dir.createFile` for a function that
-/// operates on both absolute and relative paths.
-/// Asserts that the path parameter has no null bytes. See `createFileAbsoluteC` for a function
-/// that accepts a null-terminated path.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn createFileAbsolute(absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
- assert(path.isAbsolute(absolute_path));
- return cwd().createFile(absolute_path, flags);
-}
-
-/// Delete a file name and possibly the file it refers to, based on an absolute path.
-/// Asserts that the path is absolute. See `Dir.deleteFile` for a function that
-/// operates on both absolute and relative paths.
-/// Asserts that the path parameter has no null bytes.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void {
- assert(path.isAbsolute(absolute_path));
- return cwd().deleteFile(absolute_path);
-}
-
-/// Removes a symlink, file, or directory.
-/// This is equivalent to `Dir.deleteTree` with the base directory.
-/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that
-/// operates on both absolute and relative paths.
-/// Asserts that the path parameter has no null bytes.
-/// On Windows, `absolute_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, `absolute_path` should be encoded as valid UTF-8.
-/// On other platforms, `absolute_path` is an opaque sequence of bytes with no particular encoding.
-pub fn deleteTreeAbsolute(io: Io, absolute_path: []const u8) !void {
- assert(path.isAbsolute(absolute_path));
- const dirname = path.dirname(absolute_path) orelse return error{
- /// Attempt to remove the root file system path.
- /// This error is unreachable if `absolute_path` is relative.
- CannotDeleteRootDirectory,
- }.CannotDeleteRootDirectory;
-
- var dir = try cwd().openDir(dirname, .{});
- defer dir.close(io);
-
- return dir.deleteTree(path.basename(absolute_path));
-}
-
-/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
-/// 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.
-/// See also `symLinkAbsoluteZ` and `symLinkAbsoluteW`.
-/// 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 symLinkAbsolute(
- target_path: []const u8,
- sym_link_path: []const u8,
- flags: Dir.SymLinkFlags,
-) !void {
- assert(path.isAbsolute(target_path));
- assert(path.isAbsolute(sym_link_path));
- if (native_os == .windows) {
- const target_path_w = try windows.sliceToPrefixedFileW(null, target_path);
- const sym_link_path_w = try windows.sliceToPrefixedFileW(null, sym_link_path);
- return windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory);
- }
- return posix.symlink(target_path, sym_link_path);
-}
-
-/// Windows-only. Same as `symLinkAbsolute` except the parameters are null-terminated, WTF16 LE encoded.
-/// Note that this function will by default try creating a symbolic link to a file. If you would
-/// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`.
-/// See also `symLinkAbsolute`, `symLinkAbsoluteZ`.
-pub fn symLinkAbsoluteW(
- target_path_w: [*:0]const u16,
- sym_link_path_w: [*:0]const u16,
- flags: Dir.SymLinkFlags,
-) !void {
- assert(path.isAbsoluteWindowsW(target_path_w));
- assert(path.isAbsoluteWindowsW(sym_link_path_w));
- return windows.CreateSymbolicLink(null, mem.span(sym_link_path_w), mem.span(target_path_w), flags.is_directory);
-}
+/// Deprecated, use `std.Io.Dir.max_path_bytes`.
+pub const max_path_bytes = std.Io.Dir.max_path_bytes;
+/// Deprecated, use `std.Io.Dir.max_name_bytes`.
+pub const max_name_bytes = std.Io.Dir.max_name_bytes;
test {
- _ = AtomicFile;
- _ = Dir;
- _ = File;
_ = path;
_ = @import("fs/test.zig");
_ = @import("fs/get_app_data_dir.zig");
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index 1a600fb82c..f4bdecf89d 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -2087,7 +2087,7 @@ test "'.' and '..' in absolute functions" {
try fs.copyFileAbsolute(created_file_path, copied_file_path, .{});
const renamed_file_path = try fs.path.join(allocator, &.{ subdir_path, "../rename" });
try fs.renameAbsolute(copied_file_path, renamed_file_path);
- const renamed_file = try fs.openFileAbsolute(renamed_file_path, .{});
+ const renamed_file = try Dir.openFileAbsolute(renamed_file_path, .{});
renamed_file.close(io);
try fs.deleteFileAbsolute(renamed_file_path);
@@ -2202,20 +2202,19 @@ test "invalid UTF-8/WTF-8 paths" {
try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path));
if (native_os != .wasi and ctx.path_type != .relative) {
- try testing.expectError(expected_err, fs.copyFileAbsolute(invalid_path, invalid_path, .{}));
- try testing.expectError(expected_err, fs.makeDirAbsolute(invalid_path));
- try testing.expectError(expected_err, fs.deleteDirAbsolute(invalid_path));
- try testing.expectError(expected_err, fs.renameAbsolute(invalid_path, invalid_path));
- try testing.expectError(expected_err, fs.openDirAbsolute(invalid_path, .{}));
- try testing.expectError(expected_err, fs.openFileAbsolute(invalid_path, .{}));
- try testing.expectError(expected_err, fs.accessAbsolute(invalid_path, .{}));
- try testing.expectError(expected_err, fs.createFileAbsolute(invalid_path, .{}));
- try testing.expectError(expected_err, fs.deleteFileAbsolute(invalid_path));
- try testing.expectError(expected_err, fs.deleteTreeAbsolute(invalid_path));
- var readlink_buf: [fs.max_path_bytes]u8 = undefined;
- try testing.expectError(expected_err, fs.readLinkAbsolute(invalid_path, &readlink_buf));
- try testing.expectError(expected_err, fs.symLinkAbsolute(invalid_path, invalid_path, .{}));
- try testing.expectError(expected_err, fs.realpathAlloc(testing.allocator, invalid_path));
+ try testing.expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.makeDirAbsolute(invalid_path));
+ try testing.expectError(expected_err, Dir.deleteDirAbsolute(invalid_path));
+ try testing.expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path));
+ try testing.expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.accessAbsolute(invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.deleteFileAbsolute(invalid_path));
+ var readlink_buf: [Dir.max_path_bytes]u8 = undefined;
+ try testing.expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf));
+ try testing.expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{}));
+ try testing.expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path));
}
}
}.impl);
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 77a3833c2b..667d743f3d 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -72,3 +72,8 @@ pub fn fstat_wasi(fd: posix.fd_t) FstatError!wasi.filestat_t {
else => |err| return posix.unexpectedErrno(err),
}
}
+
+pub fn defaultWasiCwd() std.os.wasi.fd_t {
+ // Expect the first preopen to be current working directory.
+ return 3;
+}
diff --git a/lib/std/process.zig b/lib/std/process.zig
index 77f91587fe..5d60190c2b 100644
--- a/lib/std/process.zig
+++ b/lib/std/process.zig
@@ -1576,7 +1576,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
/// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else
/// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`.
pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo {
- const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
+ const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{});
defer file.close(io);
var buffer: [4096]u8 = undefined;
var file_reader = file.reader(&buffer);
diff --git a/lib/std/std.zig b/lib/std/std.zig
index 84e402f52b..106811859b 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -115,7 +115,7 @@ pub const Options = struct {
enable_segfault_handler: bool = debug.default_enable_segfault_handler,
/// Function used to implement `std.fs.cwd` for WASI.
- wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd,
+ wasiCwd: fn () os.wasi.fd_t = os.defaultWasiCwd,
/// The current log level.
log_level: log.Level = log.default_level,
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 5c110a576d..d3bafc16f2 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -1024,7 +1024,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ
};
while (true) {
- const file = fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) {
+ const file = Io.Dir.openFileAbsolute(io, file_name, .{}) catch |err| switch (err) {
error.NoSpaceLeft => return error.Unexpected,
error.NameTooLong => return error.Unexpected,
error.PathAlreadyExists => return error.Unexpected,
diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig
index 668e5a1d99..60f4d7bfec 100644
--- a/lib/std/zig/system/linux.zig
+++ b/lib/std/zig/system/linux.zig
@@ -444,7 +444,7 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
}
pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {
- var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
+ var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) {
else => return null,
};
defer file.close(io);