From d1d2c37af26902f953b2b72335b326c4b01e3bb2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 3 Dec 2025 20:37:43 -0800 Subject: std: all Dir functions moved to std.Io --- lib/std/Build/Step.zig | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index c247e69461..33fe755c2b 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -510,20 +510,16 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u const io = b.graph.io; const src_path = src_lazy_path.getPath3(b, s); try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path }); - return Io.Dir.updateFile(src_path.root_dir.handle.adaptToNewApi(), io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| { - return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ - src_path, dest_path, err, - }); - }; + return Io.Dir.updateFile(src_path.root_dir.handle, io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| + return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); } /// Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output. pub fn installDir(s: *Step, dest_path: []const u8) !std.fs.Dir.MakePathStatus { const b = s.owner; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); - return std.fs.cwd().makePathStatus(dest_path) catch |err| { + return std.fs.cwd().makePathStatus(dest_path) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); - }; } fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build.WebServer, gpa: Allocator) !?Path { -- cgit v1.2.3 From aafddc2ea13e40a8262d9378aeca2e097a37ac03 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 5 Dec 2025 19:08:37 -0800 Subject: update all occurrences of close() to close(io) --- build.zig | 4 +- lib/compiler/aro/aro/Compilation.zig | 8 +- lib/compiler/aro/aro/Driver.zig | 12 +- lib/compiler/aro/aro/Driver/Filesystem.zig | 28 +-- lib/compiler/aro/aro/Toolchain.zig | 3 +- lib/compiler/objcopy.zig | 4 +- lib/compiler/resinator/cli.zig | 4 +- lib/compiler/resinator/compile.zig | 34 ++-- lib/compiler/resinator/errors.zig | 4 +- lib/compiler/resinator/main.zig | 14 +- lib/compiler/resinator/utils.zig | 9 +- lib/compiler/std-docs.zig | 33 ++-- lib/compiler/translate-c/main.zig | 5 +- lib/std/Build/Cache/Directory.zig | 4 +- lib/std/Build/Fuzz.zig | 4 +- lib/std/Build/Step.zig | 3 +- lib/std/Build/Step/InstallArtifact.zig | 3 +- lib/std/Build/Step/InstallDir.zig | 2 +- lib/std/Build/Step/Run.zig | 20 ++- lib/std/Build/Step/WriteFile.zig | 10 +- lib/std/Build/Watch/FsEvents.zig | 9 +- lib/std/Build/WebServer.zig | 7 +- lib/std/Io/Dir.zig | 41 +++-- lib/std/Io/Writer.zig | 6 +- lib/std/Io/net/test.zig | 10 +- lib/std/Io/test.zig | 16 +- lib/std/Thread.zig | 7 +- lib/std/crypto/Certificate/Bundle.zig | 6 +- lib/std/crypto/codecs/asn1/test.zig | 2 +- lib/std/debug.zig | 8 +- lib/std/debug/ElfFile.zig | 26 ++- lib/std/debug/Info.zig | 21 ++- lib/std/debug/MachOFile.zig | 18 +- lib/std/debug/SelfInfo/Elf.zig | 10 +- lib/std/debug/SelfInfo/MachO.zig | 4 +- lib/std/debug/SelfInfo/Windows.zig | 6 +- lib/std/dynamic_library.zig | 34 ++-- lib/std/fs.zig | 4 +- lib/std/fs/test.zig | 270 ++++++++++++++++++----------- lib/std/http/Client.zig | 4 +- lib/std/os/linux/IoUring.zig | 85 ++++++--- lib/std/os/linux/test.zig | 12 +- lib/std/posix/test.zig | 54 ++++-- lib/std/process.zig | 12 +- lib/std/process/Child.zig | 43 ++--- lib/std/tar.zig | 71 ++++---- lib/std/tar/test.zig | 8 +- lib/std/testing.zig | 6 +- lib/std/zig/LibCInstallation.zig | 71 ++++---- lib/std/zig/WindowsSdk.zig | 67 +++---- lib/std/zig/llvm/Builder.zig | 19 +- lib/std/zig/system.zig | 4 +- lib/std/zig/system/linux.zig | 2 +- lib/std/zip.zig | 6 +- src/Compilation.zig | 64 +++---- src/Package/Fetch.zig | 72 ++++---- src/Package/Fetch/git.zig | 26 +-- src/Zcu.zig | 10 +- src/Zcu/PerThread.zig | 6 +- src/codegen/llvm.zig | 5 +- src/fmt.zig | 10 +- src/introspect.zig | 28 +-- src/libs/freebsd.zig | 4 +- src/libs/glibc.zig | 4 +- src/libs/mingw.zig | 6 +- src/libs/netbsd.zig | 4 +- src/link.zig | 83 +++++---- src/link/C.zig | 6 +- src/link/Elf.zig | 6 +- src/link/Lld.zig | 2 +- src/link/MachO.zig | 16 +- src/link/MachO/DebugSymbols.zig | 50 +++--- src/link/Wasm.zig | 4 +- src/main.zig | 135 ++++++++------- src/print_targets.zig | 3 +- 75 files changed, 1014 insertions(+), 707 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/build.zig b/build.zig index ade4825927..7ea515de3e 100644 --- a/build.zig +++ b/build.zig @@ -1604,12 +1604,12 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath { b.build_root, @errorName(err), }); }; - defer dir.close(); + defer dir.close(io); var wf = b.addWriteFiles(); var it = dir.iterateAssumeFirstIteration(); - while (it.next() catch @panic("failed to read dir")) |entry| { + while (it.next(io) catch @panic("failed to read dir")) |entry| { if (std.mem.startsWith(u8, entry.name, ".") or entry.kind != .file) continue; diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index d5f4ebe2d9..9fb8123146 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -1639,8 +1639,10 @@ fn addSourceFromPathExtra(comp: *Compilation, path: []const u8, kind: Source.Kin return error.FileNotFound; } + const io = comp.io; + const file = try comp.cwd.openFile(path, .{}); - defer file.close(); + defer file.close(io); return comp.addSourceFromFile(file, path, kind); } @@ -1971,8 +1973,10 @@ fn getPathContents(comp: *Compilation, path: []const u8, limit: Io.Limit) ![]u8 return error.FileNotFound; } + const io = comp.io; + const file = try comp.cwd.openFile(path, .{}); - defer file.close(); + defer file.close(io); return comp.getFileContents(file, limit); } diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index 6a399ece39..888ade2be4 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1286,6 +1286,8 @@ fn processSource( d.comp.generated_buf.items.len = 0; const prev_total = d.diagnostics.errors; + const io = d.comp.io; + var pp = try Preprocessor.initDefault(d.comp); defer pp.deinit(); @@ -1328,7 +1330,7 @@ fn processSource( return d.fatal("unable to create dependency file '{s}': {s}", .{ path, errorDescription(er) }) else std.fs.File.stdout(); - defer if (dep_file_name != null) file.close(); + defer if (dep_file_name != null) file.close(io); var file_writer = file.writer(&writer_buf); dep_file.write(&file_writer.interface) catch @@ -1353,7 +1355,7 @@ fn processSource( return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) }) else std.fs.File.stdout(); - defer if (d.output_name != null) file.close(); + defer if (d.output_name != null) file.close(io); var file_writer = file.writer(&writer_buf); pp.prettyPrintTokens(&file_writer.interface, dump_mode) catch @@ -1404,7 +1406,7 @@ fn processSource( if (d.only_preprocess_and_compile) { const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); assembly.writeToFile(out_file) catch |er| return d.fatal("unable to write to output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); @@ -1418,7 +1420,7 @@ fn processSource( const assembly_out_file_name = try d.getRandomFilename(&assembly_name_buf, ".s"); const out_file = d.comp.cwd.createFile(assembly_out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ assembly_out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); assembly.writeToFile(out_file) catch |er| return d.fatal("unable to write to output file '{s}': {s}", .{ assembly_out_file_name, errorDescription(er) }); try d.invokeAssembler(tc, assembly_out_file_name, out_file_name); @@ -1454,7 +1456,7 @@ fn processSource( const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); - defer out_file.close(); + defer out_file.close(io); var file_writer = out_file.writer(&writer_buf); obj.finish(&file_writer.interface) catch diff --git a/lib/compiler/aro/aro/Driver/Filesystem.zig b/lib/compiler/aro/aro/Driver/Filesystem.zig index 87092cb235..19ac9bfe41 100644 --- a/lib/compiler/aro/aro/Driver/Filesystem.zig +++ b/lib/compiler/aro/aro/Driver/Filesystem.zig @@ -1,8 +1,10 @@ -const std = @import("std"); -const mem = std.mem; const builtin = @import("builtin"); const is_windows = builtin.os.tag == .windows; +const std = @import("std"); +const Io = std.Io; +const mem = std.std.mem; + fn readFileFake(entries: []const Filesystem.Entry, path: []const u8, buf: []u8) ?[]const u8 { @branchHint(.cold); for (entries) |entry| { @@ -96,7 +98,7 @@ fn findProgramByNamePosix(name: []const u8, path: ?[]const u8, buf: []u8) ?[]con } pub const Filesystem = union(enum) { - real: std.fs.Dir, + real: std.Io.Dir, fake: []const Entry, const Entry = struct { @@ -121,7 +123,7 @@ pub const Filesystem = union(enum) { base: []const u8, i: usize = 0, - fn next(self: *@This()) !?std.fs.Dir.Entry { + fn next(self: *@This()) !?std.Io.Dir.Entry { while (self.i < self.entries.len) { const entry = self.entries[self.i]; self.i += 1; @@ -130,7 +132,7 @@ pub const Filesystem = union(enum) { const remaining = entry.path[self.base.len + 1 ..]; if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; const extension = std.fs.path.extension(remaining); - const kind: std.fs.Dir.Entry.Kind = if (extension.len == 0) .directory else .file; + const kind: std.Io.Dir.Entry.Kind = if (extension.len == 0) .directory else .file; return .{ .name = remaining, .kind = kind }; } } @@ -140,7 +142,7 @@ pub const Filesystem = union(enum) { }; const Dir = union(enum) { - dir: std.fs.Dir, + dir: std.Io.Dir, fake: FakeDir, pub fn iterate(self: Dir) Iterator { @@ -150,19 +152,19 @@ pub const Filesystem = union(enum) { }; } - pub fn close(self: *Dir) void { + pub fn close(self: *Dir, io: Io) void { switch (self.*) { - .dir => |*d| d.close(), + .dir => |*d| d.close(io), .fake => {}, } } }; const Iterator = union(enum) { - iterator: std.fs.Dir.Iterator, + iterator: std.Io.Dir.Iterator, fake: FakeDir.Iterator, - pub fn next(self: *Iterator) std.fs.Dir.Iterator.Error!?std.fs.Dir.Entry { + pub fn next(self: *Iterator) std.Io.Dir.Iterator.Error!?std.Io.Dir.Entry { return switch (self.*) { .iterator => |*it| it.next(), .fake => |*it| it.next(), @@ -208,11 +210,11 @@ pub const Filesystem = union(enum) { /// Read the file at `path` into `buf`. /// Returns null if any errors are encountered /// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned - pub fn readFile(fs: Filesystem, path: []const u8, buf: []u8) ?[]const u8 { + pub fn readFile(fs: Filesystem, io: Io, path: []const u8, buf: []u8) ?[]const u8 { return switch (fs) { .real => |cwd| { const file = cwd.openFile(path, .{}) catch return null; - defer file.close(); + defer file.close(io); const bytes_read = file.readAll(buf) catch return null; return buf[0..bytes_read]; @@ -221,7 +223,7 @@ pub const Filesystem = union(enum) { }; } - pub fn openDir(fs: Filesystem, dir_name: []const u8) std.fs.Dir.OpenError!Dir { + pub fn openDir(fs: Filesystem, dir_name: []const u8) std.Io.Dir.OpenError!Dir { return switch (fs) { .real => |cwd| .{ .dir = try cwd.openDir(dir_name, .{ .access_sub_paths = false, .iterate = true }) }, .fake => |entries| .{ .fake = .{ .entries = entries, .path = dir_name } }, diff --git a/lib/compiler/aro/aro/Toolchain.zig b/lib/compiler/aro/aro/Toolchain.zig index 326278cc38..ae84369205 100644 --- a/lib/compiler/aro/aro/Toolchain.zig +++ b/lib/compiler/aro/aro/Toolchain.zig @@ -497,6 +497,7 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { const comp = d.comp; const gpa = comp.gpa; const arena = comp.arena; + const io = comp.io; try d.includes.ensureUnusedCapacity(gpa, 1); if (d.resource_dir) |resource_dir| { const path = try std.fs.path.join(arena, &.{ resource_dir, "include" }); @@ -509,7 +510,7 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { var search_path = d.aro_name; while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) { var base_dir = d.comp.cwd.openDir(dirname, .{}) catch continue; - defer base_dir.close(); + defer base_dir.close(io); base_dir.access("include/stddef.h", .{}) catch continue; const path = try std.fs.path.join(arena, &.{ dirname, "include" }); diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 7cf0f14e42..1608c121b1 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -152,7 +152,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void const io = threaded.io(); const input_file = fs.cwd().openFile(input, .{}) catch |err| fatal("failed to open {s}: {t}", .{ input, err }); - defer input_file.close(); + defer input_file.close(io); const stat = input_file.stat() catch |err| fatal("failed to stat {s}: {t}", .{ input, err }); @@ -180,7 +180,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void const mode = if (out_fmt != .elf or only_keep_debug) fs.File.default_mode else stat.mode; var output_file = try fs.cwd().createFile(output, .{ .mode = mode }); - defer output_file.close(); + defer output_file.close(io); var out = output_file.writer(&output_buffer); diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 59568e9cef..ffaa62e7ca 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -1991,6 +1991,8 @@ test "parse: input and output formats" { } test "maybeAppendRC" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); @@ -2001,7 +2003,7 @@ test "maybeAppendRC" { // Create the file so that it's found. In this scenario, .rc should not get // appended. var file = try tmp.dir.createFile("foo", .{}); - file.close(); + file.close(io); try options.maybeAppendRC(tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig index 08e161e505..7dc77e5ee1 100644 --- a/lib/compiler/resinator/compile.zig +++ b/lib/compiler/resinator/compile.zig @@ -34,7 +34,7 @@ const code_pages = @import("code_pages.zig"); const errors = @import("errors.zig"); pub const CompileOptions = struct { - cwd: std.fs.Dir, + cwd: std.Io.Dir, diagnostics: *Diagnostics, source_mappings: ?*SourceMappings = null, /// List of paths (absolute or relative to `cwd`) for every file that the resources within the .rc file depend on. @@ -107,7 +107,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io // the cwd so we don't need to add it as a distinct search path. if (std.fs.path.dirname(root_path)) |root_dir_path| { var root_dir = try options.cwd.openDir(root_dir_path, .{}); - errdefer root_dir.close(); + errdefer root_dir.close(io); try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); } } @@ -136,7 +136,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io // TODO: maybe a warning that the search path is skipped? continue; }; - errdefer dir.close(); + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); } for (options.system_include_paths) |system_include_path| { @@ -144,7 +144,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io // TODO: maybe a warning that the search path is skipped? continue; }; - errdefer dir.close(); + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); } if (!options.ignore_include_env_var) { @@ -160,7 +160,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter); while (it.next()) |search_path| { var dir = openSearchPathDir(options.cwd, search_path) catch continue; - errdefer dir.close(); + errdefer dir.close(io); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); } } @@ -196,7 +196,7 @@ pub const Compiler = struct { arena: Allocator, allocator: Allocator, io: Io, - cwd: std.fs.Dir, + cwd: std.Io.Dir, state: State = .{}, diagnostics: *Diagnostics, dependencies: ?*Dependencies, @@ -388,7 +388,9 @@ pub const Compiler = struct { /// matching file is invalid. That is, it does not do the `cmd` PATH searching /// thing of continuing to look for matching files until it finds a valid /// one if a matching file is invalid. - fn searchForFile(self: *Compiler, path: []const u8) !std.fs.File { + fn searchForFile(self: *Compiler, path: []const u8) !std.Io.File { + const io = self.io; + // If the path is absolute, then it is not resolved relative to any search // paths, so there's no point in checking them. // @@ -405,7 +407,7 @@ pub const Compiler = struct { // an absolute path. if (std.fs.path.isAbsolute(path)) { const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); - errdefer file.close(); + errdefer file.close(io); if (self.dependencies) |dependencies| { const duped_path = try dependencies.allocator.dupe(u8, path); @@ -414,10 +416,10 @@ pub const Compiler = struct { } } - var first_error: ?(std.fs.File.OpenError || std.fs.File.StatError) = null; + var first_error: ?(std.Io.File.OpenError || std.Io.File.StatError) = null; for (self.search_dirs) |search_dir| { if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| { - errdefer file.close(); + errdefer file.close(io); if (self.dependencies) |dependencies| { const searched_file_path = try std.fs.path.join(dependencies.allocator, &.{ @@ -587,7 +589,7 @@ pub const Compiler = struct { }); }, }; - defer file_handle.close(); + defer file_handle.close(io); var file_buffer: [2048]u8 = undefined; var file_reader = file_handle.reader(io, &file_buffer); @@ -2892,9 +2894,9 @@ pub const Compiler = struct { } }; -pub const OpenSearchPathError = std.fs.Dir.OpenError; +pub const OpenSearchPathError = std.Io.Dir.OpenError; -fn openSearchPathDir(dir: std.fs.Dir, path: []const u8) OpenSearchPathError!std.fs.Dir { +fn openSearchPathDir(dir: std.Io.Dir, path: []const u8) OpenSearchPathError!std.Io.Dir { // Validate the search path to avoid possible unreachable on invalid paths, // see https://github.com/ziglang/zig/issues/15607 for why this is currently necessary. try validateSearchPath(path); @@ -2927,11 +2929,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void { } pub const SearchDir = struct { - dir: std.fs.Dir, + dir: std.Io.Dir, path: ?[]const u8, - pub fn deinit(self: *SearchDir, allocator: Allocator) void { - self.dir.close(); + pub fn deinit(self: *SearchDir, allocator: Allocator, io: Io) void { + self.dir.close(io); if (self.path) |path| { allocator.free(path); } diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 0060990ab6..8509aa610f 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -1221,8 +1221,8 @@ const CorrespondingLines = struct { }; } - pub fn deinit(self: *CorrespondingLines) void { - self.file.close(); + pub fn deinit(self: *CorrespondingLines, io: Io) void { + self.file.close(io); } }; diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index 6d6819f45a..42308a8987 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -296,7 +296,7 @@ pub fn main() !void { error.ParseError, error.CompileError => { try error_handler.emitDiagnostics(gpa, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings); // Delete the output file on error - res_stream.cleanupAfterError(); + res_stream.cleanupAfterError(io); std.process.exit(1); }, else => |e| return e, @@ -315,7 +315,7 @@ pub fn main() !void { try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) }); std.process.exit(1); }; - defer depfile.close(); + defer depfile.close(io); var depfile_buffer: [1024]u8 = undefined; var depfile_writer = depfile.writer(&depfile_buffer); @@ -402,7 +402,7 @@ pub fn main() !void { }, } // Delete the output file on error - coff_stream.cleanupAfterError(); + coff_stream.cleanupAfterError(io); std.process.exit(1); }; @@ -434,11 +434,11 @@ const IoStream = struct { self.source.deinit(allocator); } - pub fn cleanupAfterError(self: *IoStream) void { + pub fn cleanupAfterError(self: *IoStream, io: Io) void { switch (self.source) { .file => |file| { // Delete the output file on error - file.close(); + file.close(io); // Failing to delete is not really a big deal, so swallow any errors std.fs.cwd().deleteFile(self.name) catch {}; }, @@ -465,9 +465,9 @@ const IoStream = struct { } } - pub fn deinit(self: *Source, allocator: Allocator) void { + pub fn deinit(self: *Source, allocator: Allocator, io: Io) void { switch (self.*) { - .file => |file| file.close(), + .file => |file| file.close(io), .stdio => {}, .memory => |*list| list.deinit(allocator), .closed => {}, diff --git a/lib/compiler/resinator/utils.zig b/lib/compiler/resinator/utils.zig index 021b8cf4de..f8080539cb 100644 --- a/lib/compiler/resinator/utils.zig +++ b/lib/compiler/resinator/utils.zig @@ -1,6 +1,8 @@ -const std = @import("std"); const builtin = @import("builtin"); +const std = @import("std"); +const Io = std.Io; + pub const UncheckedSliceWriter = struct { const Self = @This(); @@ -28,11 +30,12 @@ pub const UncheckedSliceWriter = struct { /// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed. pub fn openFileNotDir( cwd: std.fs.Dir, + io: Io, path: []const u8, flags: std.fs.File.OpenFlags, ) (std.fs.File.OpenError || std.fs.File.StatError)!std.fs.File { - const file = try cwd.openFile(path, flags); - errdefer file.close(); + const file = try cwd.openFile(io, path, flags); + errdefer file.close(io); // https://github.com/ziglang/zig/issues/5732 if (builtin.os.tag != .windows) { const stat = try file.stat(); diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index 12825146a2..15c17ee59b 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -1,12 +1,14 @@ const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; const Cache = std.Build.Cache; fn usage() noreturn { - std.fs.File.stdout().writeAll( + std.Io.File.stdout().writeAll( \\Usage: zig std [options] \\ \\Options: @@ -27,6 +29,10 @@ pub fn main() !void { var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; const gpa = general_purpose_allocator.allocator(); + var threaded: std.Io.Threaded = .init(gpa); + defer threaded.deinit(); + const io = threaded.io(); + var argv = try std.process.argsWithAllocator(arena); defer argv.deinit(); assert(argv.skip()); @@ -35,7 +41,7 @@ pub fn main() !void { const global_cache_path = argv.next().?; var lib_dir = try std.fs.cwd().openDir(zig_lib_directory, .{}); - defer lib_dir.close(); + defer lib_dir.close(io); var listen_port: u16 = 0; var force_open_browser: ?bool = null; @@ -64,7 +70,7 @@ pub fn main() !void { }); const port = http_server.listen_address.in.getPort(); const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port}); - std.fs.File.stdout().writeAll(url_with_newline) catch {}; + std.Io.File.stdout().writeAll(url_with_newline) catch {}; if (should_open_browser) { openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { std.log.err("unable to open browser: {s}", .{@errorName(err)}); @@ -73,6 +79,7 @@ pub fn main() !void { var context: Context = .{ .gpa = gpa, + .io = io, .zig_exe_path = zig_exe_path, .global_cache_path = global_cache_path, .lib_dir = lib_dir, @@ -83,14 +90,15 @@ pub fn main() !void { const connection = try http_server.accept(); _ = std.Thread.spawn(.{}, accept, .{ &context, connection }) catch |err| { std.log.err("unable to accept connection: {s}", .{@errorName(err)}); - connection.stream.close(); + connection.stream.close(io); continue; }; } } fn accept(context: *Context, connection: std.net.Server.Connection) void { - defer connection.stream.close(); + const io = context.io; + defer connection.stream.close(io); var recv_buffer: [4000]u8 = undefined; var send_buffer: [4000]u8 = undefined; @@ -124,6 +132,7 @@ fn accept(context: *Context, connection: std.net.Server.Connection) void { const Context = struct { gpa: Allocator, + io: Io, lib_dir: std.fs.Dir, zig_lib_directory: []const u8, zig_exe_path: []const u8, @@ -185,6 +194,7 @@ fn serveDocsFile( fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { const gpa = context.gpa; + const io = context.io; var send_buffer: [0x4000]u8 = undefined; var response = try request.respondStreaming(&send_buffer, .{ @@ -197,7 +207,7 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { }); var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true }); - defer std_dir.close(); + defer std_dir.close(io); var walker = try std_dir.walk(gpa); defer walker.deinit(); @@ -216,11 +226,11 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { else => continue, } var file = try entry.dir.openFile(entry.basename, .{}); - defer file.close(); + defer file.close(io); const stat = try file.stat(); - var file_reader: std.fs.File.Reader = .{ + var file_reader: std.Io.File.Reader = .{ .file = file, - .interface = std.fs.File.Reader.initInterface(&.{}), + .interface = std.Io.File.Reader.initInterface(&.{}), .size = stat.size, }; try archiver.writeFile(entry.path, &file_reader, stat.mtime); @@ -283,6 +293,7 @@ fn buildWasmBinary( optimize_mode: std.builtin.OptimizeMode, ) !Cache.Path { const gpa = context.gpa; + const io = context.io; var argv: std.ArrayList([]const u8) = .empty; @@ -371,7 +382,7 @@ fn buildWasmBinary( } // Send EOF to stdin. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; switch (try child.wait()) { @@ -410,7 +421,7 @@ fn buildWasmBinary( }; } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(file: std.Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index b0d7a5d9bd..0c72298b30 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -121,6 +121,7 @@ pub const usage = fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void { const gpa = d.comp.gpa; + const io = d.comp.io; const aro_args = args: { var i: usize = 0; @@ -228,7 +229,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration return d.fatal("unable to create dependency file '{s}': {s}", .{ path, aro.Driver.errorDescription(er) }) else std.fs.File.stdout(); - defer if (dep_file_name != null) file.close(); + defer if (dep_file_name != null) file.close(io); var file_writer = file.writer(&out_buf); dep_file.write(&file_writer.interface) catch @@ -246,7 +247,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration var close_out_file = false; var out_file_path: []const u8 = ""; var out_file: std.fs.File = .stdout(); - defer if (close_out_file) out_file.close(); + defer if (close_out_file) out_file.close(io); if (d.output_name) |path| blk: { if (std.mem.eql(u8, path, "-")) break :blk; diff --git a/lib/std/Build/Cache/Directory.zig b/lib/std/Build/Cache/Directory.zig index 305ef25361..ce5f5b02bb 100644 --- a/lib/std/Build/Cache/Directory.zig +++ b/lib/std/Build/Cache/Directory.zig @@ -52,8 +52,8 @@ pub fn joinZ(self: Directory, allocator: Allocator, paths: []const []const u8) ! /// Whether or not the handle should be closed, or the path should be freed /// is determined by usage, however this function is provided for convenience /// if it happens to be what the caller needs. -pub fn closeAndFree(self: *Directory, gpa: Allocator) void { - self.handle.close(); +pub fn closeAndFree(self: *Directory, gpa: Allocator, io: Io) void { + self.handle.close(io); if (self.path) |p| gpa.free(p); self.* = undefined; } diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index 2897b29969..db83f393fd 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -411,7 +411,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO }); return error.AlreadyReported; }; - defer coverage_file.close(); + defer coverage_file.close(io); const file_size = coverage_file.getEndPos() catch |err| { log.err("unable to check len of coverage file '{f}': {t}", .{ coverage_file_path, err }); @@ -533,7 +533,7 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) void { cov.run.step.name, coverage_file_path, err, }); }; - defer coverage_file.close(); + defer coverage_file.close(io); const fuzz_abi = std.Build.abi.fuzz; var rbuf: [0x1000]u8 = undefined; diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 33fe755c2b..acde47071d 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -441,6 +441,7 @@ pub fn evalZigProcess( assert(argv.len != 0); const b = s.owner; const arena = b.allocator; + const io = b.graph.io; try handleChildProcUnsupported(s); try handleVerbose(s.owner, null, argv); @@ -474,7 +475,7 @@ pub fn evalZigProcess( if (!watch) { // Send EOF to stdin. - zp.child.stdin.?.close(); + zp.child.stdin.?.close(io); zp.child.stdin = null; const term = zp.child.wait() catch |err| { diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig index c203ae924b..1cdb232770 100644 --- a/lib/std/Build/Step/InstallArtifact.zig +++ b/lib/std/Build/Step/InstallArtifact.zig @@ -119,6 +119,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { _ = options; const install_artifact: *InstallArtifact = @fieldParentPtr("step", step); const b = step.owner; + const io = b.graph.io; var all_cached = true; @@ -168,7 +169,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { src_dir_path, @errorName(err), }); }; - defer src_dir.close(); + defer src_dir.close(io); var it = try src_dir.walk(b.allocator); next_entry: while (try it.next()) |entry| { diff --git a/lib/std/Build/Step/InstallDir.zig b/lib/std/Build/Step/InstallDir.zig index ecb0959cc7..788d5565a7 100644 --- a/lib/std/Build/Step/InstallDir.zig +++ b/lib/std/Build/Step/InstallDir.zig @@ -68,7 +68,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { return step.fail("unable to open source directory '{f}': {t}", .{ src_dir_path, err }); }; - defer src_dir.close(); + defer src_dir.close(io); var it = try src_dir.walk(arena); var all_cached = true; next_entry: while (try it.next()) |entry| { diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 28c09e1faf..e66e30cc79 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -851,7 +851,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .{ file_path, err }, ); }; - defer file.close(); + defer file.close(io); var buf: [1024]u8 = undefined; var file_reader = file.reader(io, &buf); @@ -1111,7 +1111,7 @@ pub fn rerunInFuzzMode( result.writer.writeAll(file_plp.prefix) catch return error.OutOfMemory; const file = try file_path.root_dir.handle.openFile(file_path.subPathOrDot(), .{}); - defer file.close(); + defer file.close(io); var buf: [1024]u8 = undefined; var file_reader = file.reader(io, &buf); @@ -1671,8 +1671,10 @@ fn evalZigTest( options: Step.MakeOptions, fuzz_context: ?FuzzContext, ) !EvalZigTestResult { - const gpa = run.step.owner.allocator; - const arena = run.step.owner.allocator; + const step_owner = run.step.owner; + const gpa = step_owner.allocator; + const arena = step_owner.allocator; + const io = step_owner.graph.io; // We will update this every time a child runs. run.step.result_peak_rss = 0; @@ -1724,7 +1726,7 @@ fn evalZigTest( run.step.result_stderr = try arena.dupe(u8, poller.reader(.stderr).buffered()); // Clean up everything and wait for the child to exit. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; poller.deinit(); child_killed = true; @@ -1744,7 +1746,7 @@ fn evalZigTest( poller.reader(.stderr).tossBuffered(); // Clean up everything and wait for the child to exit. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; poller.deinit(); child_killed = true; @@ -2177,7 +2179,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { child.stdin.?.writeAll(bytes) catch |err| { return run.step.fail("unable to write stdin: {s}", .{@errorName(err)}); }; - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; }, .lazy_path => |lazy_path| { @@ -2185,7 +2187,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { const file = path.root_dir.handle.openFile(path.subPathOrDot(), .{}) catch |err| { return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)}); }; - defer file.close(); + defer file.close(io); // TODO https://github.com/ziglang/zig/issues/23955 var read_buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &read_buffer); @@ -2204,7 +2206,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { stdin_writer.err.?, }), }; - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; }, .none => {}, diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 030c7c6811..201b132271 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -206,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { } } - const open_dir_cache = try arena.alloc(fs.Dir, write_file.directories.items.len); + const open_dir_cache = try arena.alloc(Io.Dir, write_file.directories.items.len); var open_dirs_count: usize = 0; defer closeDirs(open_dir_cache[0..open_dirs_count]); @@ -264,7 +264,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { b.cache_root, cache_path, @errorName(err), }); }; - defer cache_dir.close(); + defer cache_dir.close(io); for (write_file.files.items) |file| { if (fs.path.dirname(file.sub_path)) |dirname| { @@ -342,6 +342,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try step.writeManifest(&man); } -fn closeDirs(dirs: []fs.Dir) void { - for (dirs) |*d| d.close(); +fn closeDirs(io: Io, dirs: []Io.Dir) void { + var group: Io.Group = .init; + defer group.wait(); + for (dirs) |d| group.async(Io.Dir.close, .{ d, io }); } diff --git a/lib/std/Build/Watch/FsEvents.zig b/lib/std/Build/Watch/FsEvents.zig index 6131663993..59238c8725 100644 --- a/lib/std/Build/Watch/FsEvents.zig +++ b/lib/std/Build/Watch/FsEvents.zig @@ -78,10 +78,10 @@ const ResolvedSymbols = struct { kCFAllocatorUseContext: *const CFAllocatorRef, }; -pub fn init() error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { +pub fn init(io: Io) error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { var core_services = std.DynLib.open("/System/Library/Frameworks/CoreServices.framework/CoreServices") catch return error.OpenFrameworkFailed; - errdefer core_services.close(); + errdefer core_services.close(io); var resolved_symbols: ResolvedSymbols = undefined; inline for (@typeInfo(ResolvedSymbols).@"struct".fields) |f| { @@ -102,10 +102,10 @@ pub fn init() error{ OpenFrameworkFailed, MissingCoreServicesSymbol }!FsEvents { }; } -pub fn deinit(fse: *FsEvents, gpa: Allocator) void { +pub fn deinit(fse: *FsEvents, gpa: Allocator, io: Io) void { dispatch_release(fse.waiting_semaphore); dispatch_release(fse.dispatch_queue); - fse.core_services.close(); + fse.core_services.close(io); gpa.free(fse.watch_roots); fse.watch_paths.deinit(gpa); @@ -487,6 +487,7 @@ const FSEventStreamEventFlags = packed struct(u32) { }; const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const watch_log = std.log.scoped(.watch); diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 2c865a8889..f91075b444 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -129,6 +129,7 @@ pub fn init(opts: Options) WebServer { } pub fn deinit(ws: *WebServer) void { const gpa = ws.gpa; + const io = ws.graph.io; gpa.free(ws.step_names_trailing); gpa.free(ws.step_status_bits); @@ -139,7 +140,7 @@ pub fn deinit(ws: *WebServer) void { gpa.free(ws.time_report_update_times); if (ws.serve_thread) |t| { - if (ws.tcp_server) |*s| s.stream.close(); + if (ws.tcp_server) |*s| s.stream.close(io); t.join(); } if (ws.tcp_server) |*s| s.deinit(); @@ -507,7 +508,7 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons log.err("failed to open '{f}': {s}", .{ path, @errorName(err) }); continue; }; - defer file.close(); + defer file.close(io); const stat = try file.stat(); var read_buffer: [1024]u8 = undefined; var file_reader: Io.File.Reader = .initSize(file.adaptToNewApi(), io, &read_buffer, stat.size); @@ -634,7 +635,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim } // Send EOF to stdin. - child.stdin.?.close(); + child.stdin.?.close(io); child.stdin = null; switch (try child.wait()) { diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 348950e20a..5a74c8ca72 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -131,7 +131,7 @@ pub const SelectiveWalker = struct { /// 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: *SelectiveWalker) Error!?Walker.Entry { + pub fn next(self: *SelectiveWalker, io: Io) Error!?Walker.Entry { while (self.stack.items.len > 0) { const top = &self.stack.items[self.stack.items.len - 1]; var dirname_len = top.dirname_len; @@ -142,7 +142,7 @@ pub const SelectiveWalker = struct { // likely just fail with the same error. var item = self.stack.pop().?; if (self.stack.items.len != 0) { - item.iter.dir.close(); + item.iter.dir.close(io); } return err; }) |entry| { @@ -164,7 +164,7 @@ pub const SelectiveWalker = struct { } else { var item = self.stack.pop().?; if (self.stack.items.len != 0) { - item.iter.dir.close(); + item.iter.dir.close(io); } } } @@ -172,7 +172,7 @@ pub const SelectiveWalker = struct { } /// Traverses into the directory, continuing walking one level down. - pub fn enter(self: *SelectiveWalker, entry: Walker.Entry) !void { + pub fn enter(self: *SelectiveWalker, io: Io, entry: Walker.Entry) !void { if (entry.kind != .directory) { @branchHint(.cold); return; @@ -184,7 +184,7 @@ pub const SelectiveWalker = struct { else => |e| return e, } }; - errdefer new_dir.close(); + errdefer new_dir.close(io); try self.stack.append(self.allocator, .{ .iter = new_dir.iterateAssumeFirstIteration(), @@ -200,11 +200,11 @@ pub const SelectiveWalker = struct { /// 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 { + pub fn leave(self: *SelectiveWalker, io: Io) void { var item = self.stack.pop().?; if (self.stack.items.len != 0) { @branchHint(.likely); - item.iter.dir.close(); + item.iter.dir.close(io); } } }; @@ -558,7 +558,8 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) pub const MakePathError = MakeError || StatPathError; -/// Creates parent directories as necessary to ensure `sub_path` exists as a directory. +/// Creates parent directories with default permissions as necessary to ensure +/// `sub_path` exists as a directory. /// /// Returns success if the path already exists and is a directory. /// @@ -579,8 +580,11 @@ pub const MakePathError = MakeError || StatPathError; /// - On other platforms, `..` are not resolved before the path is passed to `mkdirat`, /// meaning a `sub_path` like "first/../second" will create both a `./first` /// and a `./second` directory. -pub fn makePath(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) MakePathError!void { - _ = try io.vtable.dirMakePath(io.userdata, dir, sub_path, permissions); +/// +/// See also: +/// * `makePathStatus` +pub fn makePath(dir: Dir, io: Io, sub_path: []const u8) MakePathError!void { + _ = try io.vtable.dirMakePath(io.userdata, dir, sub_path, .default_dir); } pub const MakePathStatus = enum { existed, created }; @@ -593,6 +597,11 @@ pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8, permissions: Permi pub const MakeOpenPathError = MakeError || OpenError || StatPathError; +pub const MakeOpenPathOptions = struct { + open_options: OpenOptions = .{}, + permissions: Permissions = .default_dir, +}; + /// Performs the equivalent of `makePath` followed by `openDir`, atomically if possible. /// /// When this operation is canceled, it may leave the file system in a @@ -601,8 +610,8 @@ pub const MakeOpenPathError = MakeError || OpenError || StatPathError; /// 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(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions, options: OpenOptions) MakeOpenPathError!Dir { - return io.vtable.dirMakeOpenPath(io.userdata, dir, sub_path, permissions, options); +pub fn makeOpenPath(dir: Dir, io: Io, sub_path: []const u8, options: MakeOpenPathOptions) MakeOpenPathError!Dir { + return io.vtable.dirMakeOpenPath(io.userdata, dir, sub_path, options.permissions, options.open_options); } pub const Stat = File.Stat; @@ -1266,10 +1275,10 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8, start_over: while (true) { var dir = (try parent.deleteTreeOpenInitialSubpath(io, sub_path, kind_hint)) orelse return; var cleanup_dir_parent: ?Dir = null; - defer if (cleanup_dir_parent) |*d| d.close(); + defer if (cleanup_dir_parent) |*d| d.close(io); var cleanup_dir = true; - defer if (cleanup_dir) dir.close(); + defer if (cleanup_dir) dir.close(io); // Valid use of max_path_bytes because dir_name_buf will only // ever store a single path component that was returned from the @@ -1315,7 +1324,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8, error.Canceled, => |e| return e, }; - if (cleanup_dir_parent) |*d| d.close(); + if (cleanup_dir_parent) |*d| d.close(io); cleanup_dir_parent = dir; dir = new_dir; const result = dir_name_buf[0..entry.name.len]; @@ -1354,7 +1363,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8, } // Reached the end of the directory entries, which means we successfully deleted all of them. // Now to remove the directory itself. - dir.close(); + dir.close(io); cleanup_dir = false; if (cleanup_dir_parent) |d| { diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index f49ef8eb67..5601293cfb 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2835,7 +2835,7 @@ test "discarding sendFile" { defer tmp_dir.cleanup(); const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + defer file.close(io); var r_buffer: [256]u8 = undefined; var file_writer: std.fs.File.Writer = .init(file, &r_buffer); try file_writer.interface.writeByte('h'); @@ -2857,7 +2857,7 @@ test "allocating sendFile" { defer tmp_dir.cleanup(); const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + defer file.close(io); var r_buffer: [2]u8 = undefined; var file_writer: std.fs.File.Writer = .init(file, &r_buffer); try file_writer.interface.writeAll("abcd"); @@ -2881,7 +2881,7 @@ test sendFileReading { defer tmp_dir.cleanup(); const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + defer file.close(io); var r_buffer: [2]u8 = undefined; var file_writer: std.fs.File.Writer = .init(file, &r_buffer); try file_writer.interface.writeAll("abcd"); diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig index e234a9edde..5818f6c3f7 100644 --- a/lib/std/Io/net/test.zig +++ b/lib/std/Io/net/test.zig @@ -232,8 +232,10 @@ test "listen on an in use port" { fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyerror!void { if (builtin.os.tag == .wasi) return error.SkipZigTest; + const io = testing.io; + const connection = try net.tcpConnectToHost(allocator, name, port); - defer connection.close(); + defer connection.close(io); var buf: [100]u8 = undefined; const len = try connection.read(&buf); @@ -244,8 +246,10 @@ fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyer fn testClient(addr: net.IpAddress) anyerror!void { if (builtin.os.tag == .wasi) return error.SkipZigTest; + const io = testing.io; + const socket_file = try net.tcpConnectToAddress(addr); - defer socket_file.close(); + defer socket_file.close(io); var buf: [100]u8 = undefined; const len = try socket_file.read(&buf); @@ -330,7 +334,7 @@ test "non-blocking tcp server" { try testing.expectError(error.WouldBlock, accept_err); const socket_file = try net.tcpConnectToAddress(server.socket.address); - defer socket_file.close(); + defer socket_file.close(io); var stream = try server.accept(io); defer stream.close(io); diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index f7965ed14e..9ea2d48ee5 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -28,7 +28,7 @@ test "write a file, read it, then delete it" { const tmp_file_name = "temp_test_file.txt"; { var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); var file_writer = file.writer(&.{}); const st = &file_writer.interface; @@ -45,7 +45,7 @@ test "write a file, read it, then delete it" { { var file = try tmp.dir.openFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); const file_size = try file.getEndPos(); const expected_file_size: u64 = "begin".len + data.len + "end".len; @@ -67,9 +67,11 @@ test "File seek ops" { var tmp = tmpDir(.{}); defer tmp.cleanup(); + const io = testing.io; + const tmp_file_name = "temp_test_file.txt"; var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); try file.writeAll(&([_]u8{0x55} ** 8192)); @@ -88,12 +90,14 @@ test "File seek ops" { } test "setEndPos" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "temp_test_file.txt"; var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); // Verify that the file size changes and the file offset is not moved try expect((try file.getEndPos()) == 0); @@ -111,12 +115,14 @@ test "setEndPos" { } test "updateTimes" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; var file = try tmp.dir.createFile(tmp_file_name, .{ .read = true }); - defer file.close(); + defer file.close(io); const stat_old = try file.stat(); // Set atime and mtime to 5s before diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 35b268b349..9f532c3bec 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -7,6 +7,7 @@ const target = builtin.target; const native_os = builtin.os.tag; const std = @import("std.zig"); +const Io = std.Io; const math = std.math; const assert = std.debug.assert; const posix = std.posix; @@ -176,7 +177,7 @@ pub const SetNameError = error{ InvalidWtf8, } || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError; -pub fn setName(self: Thread, name: []const u8) SetNameError!void { +pub fn setName(self: Thread, io: Io, name: []const u8) SetNameError!void { if (name.len > max_name_len) return error.NameTooLong; const name_with_terminator = blk: { @@ -208,7 +209,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only }); - defer file.close(); + defer file.close(io); try file.writeAll(name); return; @@ -325,7 +326,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co const io = threaded.ioBasic(); const file = try std.fs.cwd().openFile(path, .{}); - defer file.close(); + defer file.close(io); var file_reader = file.readerStreaming(io, &.{}); const data_len = file_reader.interface.readSliceShort(buffer_ptr[0 .. max_name_len + 1]) catch |err| switch (err) { diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig index 53fb638250..9541e01db5 100644 --- a/lib/std/crypto/Certificate/Bundle.zig +++ b/lib/std/crypto/Certificate/Bundle.zig @@ -181,7 +181,7 @@ pub fn addCertsFromDirPath( sub_dir_path: []const u8, ) AddCertsFromDirPathError!void { var iterable_dir = try dir.openDir(sub_dir_path, .{ .iterate = true }); - defer iterable_dir.close(); + defer iterable_dir.close(io); return addCertsFromDir(cb, gpa, io, iterable_dir); } @@ -194,7 +194,7 @@ pub fn addCertsFromDirPathAbsolute( ) AddCertsFromDirPathError!void { assert(fs.path.isAbsolute(abs_dir_path)); var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true }); - defer iterable_dir.close(); + defer iterable_dir.close(io); return addCertsFromDir(cb, gpa, io, now, iterable_dir); } @@ -222,7 +222,7 @@ pub fn addCertsFromFilePathAbsolute( abs_file_path: []const u8, ) AddCertsFromFilePathError!void { var file = try fs.openFileAbsolute(abs_file_path, .{}); - defer file.close(); + defer file.close(io); var file_reader = file.reader(io, &.{}); return addCertsFromFile(cb, gpa, &file_reader, now.toSeconds()); } diff --git a/lib/std/crypto/codecs/asn1/test.zig b/lib/std/crypto/codecs/asn1/test.zig index fe12cba819..ff854fcbde 100644 --- a/lib/std/crypto/codecs/asn1/test.zig +++ b/lib/std/crypto/codecs/asn1/test.zig @@ -75,6 +75,6 @@ test AllTypes { // Use this to update test file. // const dir = try std.fs.cwd().openDir("lib/std/crypto/asn1", .{}); // var file = try dir.createFile(path, .{}); - // defer file.close(); + // defer file.close(io); // try file.writeAll(buf); } diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 7c5993dfcf..0cb96ed593 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1298,7 +1298,7 @@ test printLineFromFile { } { const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{}); - defer file.close(); + defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "line_overlaps_page_boundary.zig" }); defer gpa.free(path); @@ -1317,7 +1317,7 @@ test printLineFromFile { } { const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{}); - defer file.close(); + defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); defer gpa.free(path); @@ -1331,7 +1331,7 @@ test printLineFromFile { } { const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{}); - defer file.close(); + defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); defer gpa.free(path); @@ -1357,7 +1357,7 @@ test printLineFromFile { } { const file = try test_dir.dir.createFile("file_of_newlines.zig", .{}); - defer file.close(); + defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "file_of_newlines.zig" }); defer gpa.free(path); diff --git a/lib/std/debug/ElfFile.zig b/lib/std/debug/ElfFile.zig index e81943ab49..92bcca1bcf 100644 --- a/lib/std/debug/ElfFile.zig +++ b/lib/std/debug/ElfFile.zig @@ -1,5 +1,13 @@ //! A helper type for loading an ELF file and collecting its DWARF debug information, unwind //! information, and symbol table. +const ElfFile = @This(); + +const std = @import("std"); +const Io = std.Io; +const Endian = std.builtin.Endian; +const Dwarf = std.debug.Dwarf; +const Allocator = std.mem.Allocator; +const elf = std.elf; is_64: bool, endian: Endian, @@ -358,10 +366,17 @@ const Section = struct { const Array = std.enums.EnumArray(Section.Id, ?Section); }; -fn loadSeparateDebugFile(arena: Allocator, main_loaded: *LoadInnerResult, opt_crc: ?u32, comptime fmt: []const u8, args: anytype) Allocator.Error!?[]align(std.heap.page_size_min) const u8 { +fn loadSeparateDebugFile( + arena: Allocator, + io: Io, + main_loaded: *LoadInnerResult, + opt_crc: ?u32, + comptime fmt: []const u8, + args: anytype, +) Allocator.Error!?[]align(std.heap.page_size_min) const u8 { const path = try std.fmt.allocPrint(arena, fmt, args); const elf_file = std.fs.cwd().openFile(path, .{}) catch return null; - defer elf_file.close(); + defer elf_file.close(io); const result = loadInner(arena, elf_file, opt_crc) catch |err| switch (err) { error.OutOfMemory => |e| return e, @@ -529,10 +544,3 @@ fn loadInner( .mapped_mem = mapped_mem, }; } - -const std = @import("std"); -const Endian = std.builtin.Endian; -const Dwarf = std.debug.Dwarf; -const ElfFile = @This(); -const Allocator = std.mem.Allocator; -const elf = std.elf; diff --git a/lib/std/debug/Info.zig b/lib/std/debug/Info.zig index 921cd36ab8..9268ca0247 100644 --- a/lib/std/debug/Info.zig +++ b/lib/std/debug/Info.zig @@ -5,19 +5,18 @@ //! Unlike `std.debug.SelfInfo`, this API does not assume the debug information //! in question happens to match the host CPU architecture, OS, or other target //! properties. +const Info = @This(); const std = @import("../std.zig"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Path = std.Build.Cache.Path; const assert = std.debug.assert; const Coverage = std.debug.Coverage; const SourceLocation = std.debug.Coverage.SourceLocation; - const ElfFile = std.debug.ElfFile; const MachOFile = std.debug.MachOFile; -const Info = @This(); - impl: union(enum) { elf: ElfFile, macho: MachOFile, @@ -25,13 +24,23 @@ impl: union(enum) { /// Externally managed, outlives this `Info` instance. coverage: *Coverage, -pub const LoadError = std.fs.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError || error{ MissingDebugInfo, UnsupportedDebugInfo }; +pub const LoadError = error{ + MissingDebugInfo, + UnsupportedDebugInfo, +} || std.fs.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError; -pub fn load(gpa: Allocator, path: Path, coverage: *Coverage, format: std.Target.ObjectFormat, arch: std.Target.Cpu.Arch) LoadError!Info { +pub fn load( + gpa: Allocator, + io: Io, + path: Path, + coverage: *Coverage, + format: std.Target.ObjectFormat, + arch: std.Target.Cpu.Arch, +) LoadError!Info { switch (format) { .elf => { var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - defer file.close(); + defer file.close(io); var elf_file: ElfFile = try .load(gpa, file, null, &.none); errdefer elf_file.deinit(gpa); diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig index 3be1b1daff..3f0f620a90 100644 --- a/lib/std/debug/MachOFile.zig +++ b/lib/std/debug/MachOFile.zig @@ -27,13 +27,13 @@ pub fn deinit(mf: *MachOFile, gpa: Allocator) void { posix.munmap(mf.mapped_memory); } -pub fn load(gpa: Allocator, path: []const u8, arch: std.Target.Cpu.Arch) Error!MachOFile { +pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) Error!MachOFile { switch (arch) { .x86_64, .aarch64 => {}, else => unreachable, } - const all_mapped_memory = try mapDebugInfoFile(path); + const all_mapped_memory = try mapDebugInfoFile(io, path); errdefer posix.munmap(all_mapped_memory); // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal @@ -239,7 +239,7 @@ pub fn load(gpa: Allocator, path: []const u8, arch: std.Target.Cpu.Arch) Error!M .text_vmaddr = text_vmaddr, }; } -pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, vaddr: u64) !struct { *Dwarf, u64 } { +pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, io: Io, vaddr: u64) !struct { *Dwarf, u64 } { const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo; if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo; @@ -254,7 +254,7 @@ pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, vaddr: u64) !struct { const gop = try mf.ofiles.getOrPut(gpa, symbol.ofile); if (!gop.found_existing) { const name = mem.sliceTo(mf.strings[symbol.ofile..], 0); - gop.value_ptr.* = loadOFile(gpa, name); + gop.value_ptr.* = loadOFile(gpa, io, name); } const of = &(gop.value_ptr.* catch |err| return err); @@ -356,7 +356,7 @@ test { _ = Symbol; } -fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { +fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { const all_mapped_memory, const mapped_ofile = map: { const open_paren = paren: { if (std.mem.endsWith(u8, o_file_name, ")")) { @@ -365,7 +365,7 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { } } // Not an archive, just a normal path to a .o file - const m = try mapDebugInfoFile(o_file_name); + const m = try mapDebugInfoFile(io, o_file_name); break :map .{ m, m }; }; @@ -373,7 +373,7 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { const archive_path = o_file_name[0..open_paren]; const target_name_in_archive = o_file_name[open_paren + 1 .. o_file_name.len - 1]; - const mapped_archive = try mapDebugInfoFile(archive_path); + const mapped_archive = try mapDebugInfoFile(io, archive_path); errdefer posix.munmap(mapped_archive); var ar_reader: Io.Reader = .fixed(mapped_archive); @@ -511,12 +511,12 @@ fn loadOFile(gpa: Allocator, o_file_name: []const u8) !OFile { } /// Uses `mmap` to map the file at `path` into memory. -fn mapDebugInfoFile(path: []const u8) ![]align(std.heap.page_size_min) const u8 { +fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { const file = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; - defer file.close(); + defer file.close(io); const file_len = std.math.cast( usize, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 59c0b42451..155dac6fb8 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -319,14 +319,14 @@ const Module = struct { } /// Assumes we already hold an exclusive lock. - fn getLoadedElf(mod: *Module, gpa: Allocator) Error!*LoadedElf { - if (mod.loaded_elf == null) mod.loaded_elf = loadElf(mod, gpa); + fn getLoadedElf(mod: *Module, gpa: Allocator, io: Io) Error!*LoadedElf { + if (mod.loaded_elf == null) mod.loaded_elf = loadElf(mod, gpa, io); return if (mod.loaded_elf.?) |*elf| elf else |err| err; } - fn loadElf(mod: *Module, gpa: Allocator) Error!LoadedElf { + fn loadElf(mod: *Module, gpa: Allocator, io: Io) Error!LoadedElf { const load_result = if (mod.name.len > 0) res: { var file = std.fs.cwd().openFile(mod.name, .{}) catch return error.MissingDebugInfo; - defer file.close(); + defer file.close(io); break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(mod.name)); } else res: { const path = std.fs.selfExePathAlloc(gpa) catch |err| switch (err) { @@ -335,7 +335,7 @@ const Module = struct { }; defer gpa.free(path); var file = std.fs.cwd().openFile(path, .{}) catch return error.MissingDebugInfo; - defer file.close(); + defer file.close(io); break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(path)); }; diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index dd11b4c8bf..2491cf416c 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -615,12 +615,12 @@ test { } /// Uses `mmap` to map the file at `path` into memory. -fn mapDebugInfoFile(path: []const u8) ![]align(std.heap.page_size_min) const u8 { +fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { const file = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; - defer file.close(); + defer file.close(io); const file_end_pos = file.getEndPos() catch |err| switch (err) { error.Unexpected => |e| return e, diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index 0e923a0f16..557f3901eb 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -207,11 +207,11 @@ const Module = struct { file: fs.File, section_handle: windows.HANDLE, section_view: []const u8, - fn deinit(mf: *const MappedFile) void { + fn deinit(mf: *const MappedFile, io: Io) void { const process_handle = windows.GetCurrentProcess(); assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(mf.section_view.ptr)) == .SUCCESS); windows.CloseHandle(mf.section_handle); - mf.file.close(); + mf.file.close(io); } }; @@ -447,7 +447,7 @@ const Module = struct { error.FileNotFound, error.IsDir => break :pdb null, else => return error.ReadFailed, }; - errdefer pdb_file.close(); + errdefer pdb_file.close(io); const pdb_reader = try arena.create(Io.File.Reader); pdb_reader.* = pdb_file.reader(io, try arena.alloc(u8, 4096)); diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index a3490ed7db..c91056b0ab 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -1,10 +1,12 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("std.zig"); +const Io = std.Io; const mem = std.mem; const testing = std.testing; const elf = std.elf; const windows = std.os.windows; -const native_os = builtin.os.tag; const posix = std.posix; /// Cross-platform dynamic library loading and symbol lookup. @@ -38,8 +40,8 @@ pub const DynLib = struct { } /// Trusts the file. - pub fn close(self: *DynLib) void { - return self.inner.close(); + pub fn close(self: *DynLib, io: Io) void { + return self.inner.close(io); } pub fn lookup(self: *DynLib, comptime T: type, name: [:0]const u8) ?T { @@ -155,23 +157,23 @@ pub const ElfDynLib = struct { dt_gnu_hash: *elf.gnu_hash.Header, }; - fn openPath(path: []const u8) !std.fs.Dir { + fn openPath(path: []const u8, io: Io) !std.fs.Dir { if (path.len == 0) return error.NotDir; var parts = std.mem.tokenizeScalar(u8, path, '/'); var parent = if (path[0] == '/') try std.fs.cwd().openDir("/", .{}) else std.fs.cwd(); while (parts.next()) |part| { const child = try parent.openDir(part, .{}); - parent.close(); + parent.close(io); parent = child; } return parent; } - fn resolveFromSearchPath(search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t { + fn resolveFromSearchPath(io: Io, search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t { var paths = std.mem.tokenizeScalar(u8, search_path, delim); while (paths.next()) |p| { var dir = openPath(p) catch continue; - defer dir.close(); + defer dir.close(io); const fd = posix.openat(dir.fd, file_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true, @@ -181,9 +183,9 @@ pub const ElfDynLib = struct { return null; } - fn resolveFromParent(dir_path: []const u8, file_name: []const u8) ?posix.fd_t { + fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?posix.fd_t { var dir = std.fs.cwd().openDir(dir_path, .{}) catch return null; - defer dir.close(); + defer dir.close(io); return posix.openat(dir.fd, file_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true, @@ -195,7 +197,7 @@ pub const ElfDynLib = struct { // - DT_RPATH of the calling binary is not used as a search path // - DT_RUNPATH of the calling binary is not used as a search path // - /etc/ld.so.cache is not read - fn resolveFromName(path_or_name: []const u8) !posix.fd_t { + fn resolveFromName(io: Io, path_or_name: []const u8) !posix.fd_t { // If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname if (std.mem.findScalarPos(u8, path_or_name, 0, '/')) |_| { return posix.open(path_or_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); @@ -206,21 +208,21 @@ pub const ElfDynLib = struct { std.os.linux.getegid() == std.os.linux.getgid()) { if (posix.getenvZ("LD_LIBRARY_PATH")) |ld_library_path| { - if (resolveFromSearchPath(ld_library_path, path_or_name, ':')) |fd| { + if (resolveFromSearchPath(io, ld_library_path, path_or_name, ':')) |fd| { return fd; } } } // Lastly the directories /lib and /usr/lib are searched (in this exact order) - if (resolveFromParent("/lib", path_or_name)) |fd| return fd; - if (resolveFromParent("/usr/lib", path_or_name)) |fd| return fd; + if (resolveFromParent(io, "/lib", path_or_name)) |fd| return fd; + if (resolveFromParent(io, "/usr/lib", path_or_name)) |fd| return fd; return error.FileNotFound; } /// Trusts the file. Malicious file will be able to execute arbitrary code. - pub fn open(path: []const u8) Error!ElfDynLib { - const fd = try resolveFromName(path); + pub fn open(io: Io, path: []const u8) Error!ElfDynLib { + const fd = try resolveFromName(io, path); defer posix.close(fd); const file: std.fs.File = .{ .handle = fd }; diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 72fab9c7c2..9472e5d2a5 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -227,7 +227,7 @@ pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void { /// 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(absolute_path: []const u8) !void { +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. @@ -236,7 +236,7 @@ pub fn deleteTreeAbsolute(absolute_path: []const u8) !void { }.CannotDeleteRootDirectory; var dir = try cwd().openDir(dirname, .{}); - defer dir.close(); + defer dir.close(io); return dir.deleteTree(path.basename(absolute_path)); } diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 52baa0699d..15b8e9b558 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -178,6 +178,8 @@ fn setupSymlinkAbsolute(target: []const u8, link: []const u8, flags: SymLinkFlag } test "Dir.readLink" { + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { // Create some targets @@ -208,7 +210,7 @@ test "Dir.readLink" { const parent_file = ".." ++ fs.path.sep_str ++ "target.txt"; const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); var subdir = try ctx.dir.makeOpenPath("subdir", .{}); - defer subdir.close(); + defer subdir.close(io); try setupSymlink(subdir, canonical_parent_file, "relative-link.txt", .{}); try testReadLink(subdir, canonical_parent_file, "relative-link.txt"); if (builtin.os.tag == .windows) { @@ -268,6 +270,8 @@ fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void } test "File.stat on a File that is a symlink returns Kind.sym_link" { + const io = testing.io; + // This test requires getting a file descriptor of a symlink which // is not possible on all targets switch (builtin.target.os.tag) { @@ -302,7 +306,7 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { .SecurityDescriptor = null, .SecurityQualityOfService = null, }; - var io: windows.IO_STATUS_BLOCK = undefined; + var io_status_block: windows.IO_STATUS_BLOCK = undefined; const rc = windows.ntdll.NtCreateFile( &handle, .{ @@ -317,7 +321,7 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { }, }, &attr, - &io, + &io_status_block, null, .{ .NORMAL = true }, .VALID_FLAGS, @@ -352,7 +356,7 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { }, else => unreachable, }; - defer symlink.close(); + defer symlink.close(io); const stat = try symlink.stat(); try testing.expectEqual(File.Kind.sym_link, stat.kind); @@ -361,6 +365,8 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { } test "openDir" { + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const allocator = ctx.arena.allocator(); @@ -370,7 +376,7 @@ test "openDir" { for ([_][]const u8{ "", ".", ".." }) |sub_path| { const dir_path = try fs.path.join(allocator, &.{ subdir_path, sub_path }); var dir = try ctx.dir.openDir(dir_path, .{}); - defer dir.close(); + defer dir.close(io); } } }.impl); @@ -393,6 +399,8 @@ test "openDirAbsolute" { if (native_os == .wasi) return error.SkipZigTest; if (native_os == .openbsd) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -404,7 +412,7 @@ test "openDirAbsolute" { // Can open sub_path var tmp_sub = try fs.openDirAbsolute(sub_path, .{}); - defer tmp_sub.close(); + defer tmp_sub.close(io); const sub_ino = (try tmp_sub.stat()).inode; @@ -414,7 +422,7 @@ test "openDirAbsolute" { defer testing.allocator.free(dir_path); var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + defer dir.close(io); const ino = (try dir.stat()).inode; try testing.expectEqual(tmp_ino, ino); @@ -426,7 +434,7 @@ test "openDirAbsolute" { defer testing.allocator.free(dir_path); var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + defer dir.close(io); const ino = (try dir.stat()).inode; try testing.expectEqual(sub_ino, ino); @@ -438,7 +446,7 @@ test "openDirAbsolute" { defer testing.allocator.free(dir_path); var dir = try fs.openDirAbsolute(dir_path, .{}); - defer dir.close(); + defer dir.close(io); const ino = (try dir.stat()).inode; try testing.expectEqual(tmp_ino, ino); @@ -446,13 +454,15 @@ test "openDirAbsolute" { } test "openDir cwd parent '..'" { + const io = testing.io; + var dir = fs.cwd().openDir("..", .{}) catch |err| { if (native_os == .wasi and err == error.PermissionDenied) { return; // This is okay. WASI disallows escaping from the fs sandbox } return err; }; - defer dir.close(); + defer dir.close(io); } test "openDir non-cwd parent '..'" { @@ -461,14 +471,16 @@ test "openDir non-cwd parent '..'" { else => {}, } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var subdir = try tmp.dir.makeOpenPath("subdir", .{}); - defer subdir.close(); + defer subdir.close(io); var dir = try subdir.openDir("..", .{}); - defer dir.close(); + defer dir.close(io); const expected_path = try tmp.dir.realpathAlloc(testing.allocator, "."); defer testing.allocator.free(expected_path); @@ -516,12 +528,14 @@ test "readLinkAbsolute" { } test "Dir.Iterator" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -546,6 +560,8 @@ test "Dir.Iterator" { } test "Dir.Iterator many entries" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); @@ -555,7 +571,7 @@ test "Dir.Iterator many entries" { while (i < num) : (i += 1) { const name = try std.fmt.bufPrint(&buf, "{}", .{i}); const file = try tmp_dir.dir.createFile(name, .{}); - file.close(); + file.close(io); } var arena = ArenaAllocator.init(testing.allocator); @@ -581,12 +597,14 @@ test "Dir.Iterator many entries" { } test "Dir.Iterator twice" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -614,12 +632,14 @@ test "Dir.Iterator twice" { } test "Dir.Iterator reset" { + const io = testing.io; + var tmp_dir = tmpDir(.{ .iterate = true }); defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. const file = try tmp_dir.dir.createFile("some_file", .{}); - file.close(); + file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -650,12 +670,14 @@ test "Dir.Iterator reset" { } test "Dir.Iterator but dir is deleted during iteration" { + const io = testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); // Create directory and setup an iterator for it var subdir = try tmp.dir.makeOpenPath("subdir", .{ .iterate = true }); - defer subdir.close(); + defer subdir.close(io); var iterator = subdir.iterate(); @@ -742,11 +764,13 @@ test "Dir.realpath smoke test" { } test "readFileAlloc" { + const io = testing.io; + var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); var file = try tmp_dir.dir.createFile("test_file", .{ .read = true }); - defer file.close(); + defer file.close(io); const buf1 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); defer testing.allocator.free(buf1); @@ -815,10 +839,12 @@ test "statFile on dangling symlink" { test "directory operations on files" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + const test_file_name = try ctx.transformPath("test_file"); var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); - file.close(); + file.close(io); try testing.expectError(error.PathAlreadyExists, ctx.dir.makeDir(test_file_name)); try testing.expectError(error.NotDir, ctx.dir.openDir(test_file_name, .{})); @@ -833,7 +859,7 @@ test "directory operations on files" { file = try ctx.dir.openFile(test_file_name, .{}); const stat = try file.stat(); try testing.expectEqual(File.Kind.file, stat.kind); - file.close(); + file.close(io); } }.impl); } @@ -842,6 +868,8 @@ test "file operations on directories" { // TODO: fix this test on FreeBSD. https://github.com/ziglang/zig/issues/1759 if (native_os == .freebsd) return error.SkipZigTest; + const io = testing.io; + try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const test_dir_name = try ctx.transformPath("test_dir"); @@ -869,7 +897,7 @@ test "file operations on directories" { if (native_os == .wasi and builtin.link_libc) { // wasmtime unexpectedly succeeds here, see https://github.com/ziglang/zig/issues/20747 const handle = try ctx.dir.openFile(test_dir_name, .{ .mode = .read_write }); - handle.close(); + handle.close(io); } else { // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732 @@ -883,21 +911,23 @@ test "file operations on directories" { // ensure the directory still exists as a sanity check var dir = try ctx.dir.openDir(test_dir_name, .{}); - dir.close(); + dir.close(io); } }.impl); } test "makeOpenPath parent dirs do not exist" { + const io = testing.io; + var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); var dir = try tmp_dir.dir.makeOpenPath("root_dir/parent_dir/some_dir", .{}); - dir.close(); + dir.close(io); // double check that the full directory structure was created var dir_verification = try tmp_dir.dir.openDir("root_dir/parent_dir/some_dir", .{}); - dir_verification.close(); + dir_verification.close(io); } test "deleteDir" { @@ -924,6 +954,7 @@ test "deleteDir" { test "Dir.rename files" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; // Rename on Windows can hit intermittent AccessDenied errors // when certain conditions are true about the host system. // For now, skip this test when the path type is UNC to avoid them. @@ -939,13 +970,13 @@ test "Dir.rename files" { const test_file_name = try ctx.transformPath("test_file"); const renamed_test_file_name = try ctx.transformPath("test_file_renamed"); var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); - file.close(); + file.close(io); try ctx.dir.rename(test_file_name, renamed_test_file_name); // Ensure the file was renamed try testing.expectError(error.FileNotFound, ctx.dir.openFile(test_file_name, .{})); file = try ctx.dir.openFile(renamed_test_file_name, .{}); - file.close(); + file.close(io); // Rename to self succeeds try ctx.dir.rename(renamed_test_file_name, renamed_test_file_name); @@ -953,12 +984,12 @@ test "Dir.rename files" { // Rename to existing file succeeds const existing_file_path = try ctx.transformPath("existing_file"); var existing_file = try ctx.dir.createFile(existing_file_path, .{ .read = true }); - existing_file.close(); + existing_file.close(io); try ctx.dir.rename(renamed_test_file_name, existing_file_path); try testing.expectError(error.FileNotFound, ctx.dir.openFile(renamed_test_file_name, .{})); file = try ctx.dir.openFile(existing_file_path, .{}); - file.close(); + file.close(io); } }.impl); } @@ -966,6 +997,8 @@ test "Dir.rename files" { test "Dir.rename directories" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + // Rename on Windows can hit intermittent AccessDenied errors // when certain conditions are true about the host system. // For now, skip this test when the path type is UNC to avoid them. @@ -985,8 +1018,8 @@ test "Dir.rename directories" { // Put a file in the directory var file = try dir.createFile("test_file", .{ .read = true }); - file.close(); - dir.close(); + file.close(io); + dir.close(io); const test_dir_renamed_again_path = try ctx.transformPath("test_dir_renamed_again"); try ctx.dir.rename(test_dir_renamed_path, test_dir_renamed_again_path); @@ -995,8 +1028,8 @@ test "Dir.rename directories" { try testing.expectError(error.FileNotFound, ctx.dir.openDir(test_dir_renamed_path, .{})); dir = try ctx.dir.openDir(test_dir_renamed_again_path, .{}); file = try dir.openFile("test_file", .{}); - file.close(); - dir.close(); + file.close(io); + dir.close(io); } }.impl); } @@ -1007,6 +1040,8 @@ test "Dir.rename directory onto empty dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; + const test_dir_path = try ctx.transformPath("test_dir"); const target_dir_path = try ctx.transformPath("target_dir_path"); @@ -1017,7 +1052,7 @@ test "Dir.rename directory onto empty dir" { // Ensure the directory was renamed try testing.expectError(error.FileNotFound, ctx.dir.openDir(test_dir_path, .{})); var dir = try ctx.dir.openDir(target_dir_path, .{}); - dir.close(); + dir.close(io); } }.impl); } @@ -1028,6 +1063,7 @@ test "Dir.rename directory onto non-empty dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const test_dir_path = try ctx.transformPath("test_dir"); const target_dir_path = try ctx.transformPath("target_dir_path"); @@ -1035,15 +1071,15 @@ test "Dir.rename directory onto non-empty dir" { var target_dir = try ctx.dir.makeOpenPath(target_dir_path, .{}); var file = try target_dir.createFile("test_file", .{ .read = true }); - file.close(); - target_dir.close(); + file.close(io); + target_dir.close(io); // Rename should fail with PathAlreadyExists if target_dir is non-empty try testing.expectError(error.PathAlreadyExists, ctx.dir.rename(test_dir_path, target_dir_path)); // Ensure the directory was not renamed var dir = try ctx.dir.openDir(test_dir_path, .{}); - dir.close(); + dir.close(io); } }.impl); } @@ -1054,11 +1090,12 @@ test "Dir.rename file <-> dir" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const test_file_path = try ctx.transformPath("test_file"); const test_dir_path = try ctx.transformPath("test_dir"); var file = try ctx.dir.createFile(test_file_path, .{ .read = true }); - file.close(); + file.close(io); try ctx.dir.makeDir(test_dir_path); try testing.expectError(error.IsDir, ctx.dir.rename(test_file_path, test_dir_path)); try testing.expectError(error.NotDir, ctx.dir.rename(test_dir_path, test_file_path)); @@ -1067,6 +1104,8 @@ test "Dir.rename file <-> dir" { } test "rename" { + const io = testing.io; + var tmp_dir1 = tmpDir(.{}); defer tmp_dir1.cleanup(); @@ -1077,19 +1116,21 @@ test "rename" { const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; var file = try tmp_dir1.dir.createFile(test_file_name, .{ .read = true }); - file.close(); + file.close(io); try fs.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name); // ensure the file was renamed try testing.expectError(error.FileNotFound, tmp_dir1.dir.openFile(test_file_name, .{})); file = try tmp_dir2.dir.openFile(renamed_test_file_name, .{}); - file.close(); + file.close(io); } test "renameAbsolute" { if (native_os == .wasi) return error.SkipZigTest; if (native_os == .openbsd) return error.SkipZigTest; + const io = testing.io; + var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); @@ -1109,7 +1150,7 @@ test "renameAbsolute" { const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; var file = try tmp_dir.dir.createFile(test_file_name, .{ .read = true }); - file.close(); + file.close(io); try fs.renameAbsolute( try fs.path.join(allocator, &.{ base_path, test_file_name }), try fs.path.join(allocator, &.{ base_path, renamed_test_file_name }), @@ -1120,7 +1161,7 @@ test "renameAbsolute" { file = try tmp_dir.dir.openFile(renamed_test_file_name, .{}); const stat = try file.stat(); try testing.expectEqual(File.Kind.file, stat.kind); - file.close(); + file.close(io); // Renaming directories const test_dir_name = "test_dir"; @@ -1134,14 +1175,16 @@ test "renameAbsolute" { // ensure the directory was renamed try testing.expectError(error.FileNotFound, tmp_dir.dir.openDir(test_dir_name, .{})); var dir = try tmp_dir.dir.openDir(renamed_test_dir_name, .{}); - dir.close(); + dir.close(io); } test "openSelfExe" { if (native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + const self_exe_file = try std.fs.openSelfExe(.{}); - self_exe_file.close(); + self_exe_file.close(io); } test "selfExePath" { @@ -1155,13 +1198,15 @@ test "selfExePath" { } test "deleteTree does not follow symlinks" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); try tmp.dir.makePath("b"); { var a = try tmp.dir.makeOpenPath("a", .{}); - defer a.close(); + defer a.close(io); try setupSymlink(a, "../b", "b", .{ .is_directory = true }); } @@ -1257,27 +1302,31 @@ test "makePath but sub_path contains pre-existing file" { try testing.expectError(error.NotDir, tmp.dir.makePath("foo/bar/baz")); } -fn expectDir(dir: Dir, path: []const u8) !void { +fn expectDir(io: Io, dir: Dir, path: []const u8) !void { var d = try dir.openDir(path, .{}); - d.close(); + d.close(io); } test "makepath existing directories" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); try tmp.dir.makeDir("A"); var tmpA = try tmp.dir.openDir("A", .{}); - defer tmpA.close(); + defer tmpA.close(io); try tmpA.makeDir("B"); const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; try tmp.dir.makePath(testPath); - try expectDir(tmp.dir, testPath); + try expectDir(io, tmp.dir, testPath); } test "makepath through existing valid symlink" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -1286,10 +1335,12 @@ test "makepath through existing valid symlink" { try tmp.dir.makePath("working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); - try expectDir(tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); + try expectDir(io, tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); } test "makepath relative walks" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -1305,21 +1356,23 @@ test "makepath relative walks" { .windows => { // On Windows, .. is resolved before passing the path to NtCreateFile, // meaning everything except `first/C` drops out. - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); + try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); try testing.expectError(error.FileNotFound, tmp.dir.access("second", .{})); try testing.expectError(error.FileNotFound, tmp.dir.access("third", .{})); }, else => { - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "A"); - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "B"); - try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); - try expectDir(tmp.dir, "second"); - try expectDir(tmp.dir, "third"); + try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "A"); + try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "B"); + try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); + try expectDir(io, tmp.dir, "second"); + try expectDir(io, tmp.dir, "third"); }, } } test "makepath ignores '.'" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -1337,14 +1390,14 @@ test "makepath ignores '.'" { try tmp.dir.makePath(dotPath); - try expectDir(tmp.dir, expectedPath); + try expectDir(io, tmp.dir, expectedPath); } -fn testFilenameLimits(iterable_dir: Dir, maxed_filename: []const u8) !void { +fn testFilenameLimits(io: Io, iterable_dir: Dir, maxed_filename: []const u8) !void { // setup, create a dir and a nested file both with maxed filenames, and walk the dir { var maxed_dir = try iterable_dir.makeOpenPath(maxed_filename, .{}); - defer maxed_dir.close(); + defer maxed_dir.close(io); try maxed_dir.writeFile(.{ .sub_path = maxed_filename, .data = "" }); @@ -1364,6 +1417,8 @@ fn testFilenameLimits(iterable_dir: Dir, maxed_filename: []const u8) !void { } test "max file name component lengths" { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1371,16 +1426,16 @@ test "max file name component lengths" { // U+FFFF is the character with the largest code point that is encoded as a single // UTF-16 code unit, so Windows allows for NAME_MAX of them. const maxed_windows_filename = ("\u{FFFF}".*) ** windows.NAME_MAX; - try testFilenameLimits(tmp.dir, &maxed_windows_filename); + try testFilenameLimits(io, tmp.dir, &maxed_windows_filename); } else if (native_os == .wasi) { // On WASI, the maxed filename depends on the host OS, so in order for this test to // work on any host, we need to use a length that will work for all platforms // (i.e. the minimum max_name_bytes of all supported platforms). const maxed_wasi_filename = [_]u8{'1'} ** 255; - try testFilenameLimits(tmp.dir, &maxed_wasi_filename); + try testFilenameLimits(io, tmp.dir, &maxed_wasi_filename); } else { const maxed_ascii_filename = [_]u8{'1'} ** std.fs.max_name_bytes; - try testFilenameLimits(tmp.dir, &maxed_ascii_filename); + try testFilenameLimits(io, tmp.dir, &maxed_ascii_filename); } } @@ -1399,7 +1454,7 @@ test "writev, readv" { var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); - defer src_file.close(); + defer src_file.close(io); var writer = src_file.writerStreaming(&.{}); @@ -1429,7 +1484,7 @@ test "pwritev, preadv" { var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); - defer src_file.close(); + defer src_file.close(io); var writer = src_file.writer(&.{}); @@ -1459,7 +1514,7 @@ test "setEndPos" { const file_name = "afile.txt"; try tmp.dir.writeFile(.{ .sub_path = file_name, .data = "ninebytes" }); const f = try tmp.dir.openFile(file_name, .{ .mode = .read_write }); - defer f.close(); + defer f.close(io); const initial_size = try f.getEndPos(); var buffer: [32]u8 = undefined; @@ -1522,21 +1577,21 @@ test "sendfile" { try tmp.dir.makePath("os_test_tmp"); var dir = try tmp.dir.openDir("os_test_tmp", .{}); - defer dir.close(); + defer dir.close(io); const line1 = "line1\n"; const line2 = "second line\n"; var vecs = [_][]const u8{ line1, line2 }; var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); - defer src_file.close(); + defer src_file.close(io); { var fw = src_file.writer(&.{}); try fw.interface.writeVecAll(&vecs); } var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); - defer dest_file.close(); + defer dest_file.close(io); const header1 = "header1\n"; const header2 = "second header\n"; @@ -1569,15 +1624,15 @@ test "sendfile with buffered data" { try tmp.dir.makePath("os_test_tmp"); var dir = try tmp.dir.openDir("os_test_tmp", .{}); - defer dir.close(); + defer dir.close(io); var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); - defer src_file.close(); + defer src_file.close(io); try src_file.writeAll("AAAABBBB"); var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); - defer dest_file.close(); + defer dest_file.close(io); var src_buffer: [32]u8 = undefined; var file_reader = src_file.reader(io, &src_buffer); @@ -1659,10 +1714,11 @@ test "open file with exclusive nonblocking lock twice" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - defer file1.close(); + defer file1.close(io); const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); @@ -1675,10 +1731,11 @@ test "open file with shared and exclusive nonblocking lock" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); const file1 = try ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); - defer file1.close(); + defer file1.close(io); const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); @@ -1691,10 +1748,11 @@ test "open file with exclusive and shared nonblocking lock" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); - defer file1.close(); + defer file1.close(io); const file2 = ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); @@ -1707,10 +1765,11 @@ test "open file with exclusive lock twice, make sure second lock waits" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("file_lock_test.txt"); const file = try ctx.dir.createFile(filename, .{ .lock = .exclusive }); - errdefer file.close(); + errdefer file.close(io); const S = struct { fn checkFn(dir: *fs.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { @@ -1718,7 +1777,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { const file1 = try dir.createFile(path, .{ .lock = .exclusive }); locked.set(); - file1.close(); + file1.close(io); } }; @@ -1739,7 +1798,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { try testing.expectError(error.Timeout, locked.timedWait(10 * std.time.ns_per_ms)); // Release the file lock which should unlock the thread to lock it and set the locked event. - file.close(); + file.close(io); locked.wait(); } }.impl); @@ -1748,6 +1807,8 @@ test "open file with exclusive lock twice, make sure second lock waits" { test "open file with exclusive nonblocking lock twice (absolute paths)" { if (native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var random_bytes: [12]u8 = undefined; std.crypto.random.bytes(&random_bytes); @@ -1774,18 +1835,19 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { .lock = .exclusive, .lock_nonblocking = true, }); - file1.close(); + file1.close(io); try testing.expectError(error.WouldBlock, file2); } test "read from locked file" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const filename = try ctx.transformPath("read_lock_file_test.txt"); { const f = try ctx.dir.createFile(filename, .{ .read = true }); - defer f.close(); + defer f.close(io); var buffer: [1]u8 = undefined; _ = try f.read(&buffer); } @@ -1794,9 +1856,9 @@ test "read from locked file" { .read = true, .lock = .exclusive, }); - defer f.close(); + defer f.close(io); const f2 = try ctx.dir.openFile(filename, .{}); - defer f2.close(); + defer f2.close(io); var buffer: [1]u8 = undefined; if (builtin.os.tag == .windows) { try std.testing.expectError(error.LockViolation, f2.read(&buffer)); @@ -1809,6 +1871,8 @@ test "read from locked file" { } test "walker" { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1857,13 +1921,15 @@ test "walker" { }; // make sure that the entry.dir is the containing dir var entry_dir = try entry.dir.openDir(entry.basename, .{}); - defer entry_dir.close(); + defer entry_dir.close(io); num_walked += 1; } try testing.expectEqual(expected_paths.kvs.len, num_walked); } test "selective walker, skip entries that start with ." { + const io = testing.io; + var tmp = tmpDir(.{ .iterate = true }); defer tmp.cleanup(); @@ -1923,7 +1989,7 @@ test "selective walker, skip entries that start with ." { // make sure that the entry.dir is the containing dir var entry_dir = try entry.dir.openDir(entry.basename, .{}); - defer entry_dir.close(); + defer entry_dir.close(io); num_walked += 1; } try testing.expectEqual(expected_paths.kvs.len, num_walked); @@ -1968,16 +2034,16 @@ test "'.' and '..' in fs.Dir functions" { try ctx.dir.makeDir(subdir_path); try ctx.dir.access(subdir_path, .{}); var created_subdir = try ctx.dir.openDir(subdir_path, .{}); - created_subdir.close(); + created_subdir.close(io); const created_file = try ctx.dir.createFile(file_path, .{}); - created_file.close(); + created_file.close(io); try ctx.dir.access(file_path, .{}); try ctx.dir.copyFile(file_path, ctx.dir, copy_path, .{}); try ctx.dir.rename(copy_path, rename_path); const renamed_file = try ctx.dir.openFile(rename_path, .{}); - renamed_file.close(); + renamed_file.close(io); try ctx.dir.deleteFile(rename_path); try ctx.dir.writeFile(.{ .sub_path = update_path, .data = "something" }); @@ -1994,6 +2060,8 @@ test "'.' and '..' in absolute functions" { if (native_os == .wasi) return error.SkipZigTest; if (native_os == .openbsd) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -2007,11 +2075,11 @@ test "'.' and '..' in absolute functions" { try fs.makeDirAbsolute(subdir_path); try fs.accessAbsolute(subdir_path, .{}); var created_subdir = try fs.openDirAbsolute(subdir_path, .{}); - created_subdir.close(); + created_subdir.close(io); const created_file_path = try fs.path.join(allocator, &.{ subdir_path, "../file" }); const created_file = try fs.createFileAbsolute(created_file_path, .{}); - created_file.close(); + created_file.close(io); try fs.accessAbsolute(created_file_path, .{}); const copied_file_path = try fs.path.join(allocator, &.{ subdir_path, "../copy" }); @@ -2019,7 +2087,7 @@ test "'.' and '..' in absolute functions" { 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, .{}); - renamed_file.close(); + renamed_file.close(io); try fs.deleteFileAbsolute(renamed_file_path); try fs.deleteDirAbsolute(subdir_path); @@ -2029,11 +2097,13 @@ test "chmod" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const file = try tmp.dir.createFile("test_file", .{ .mode = 0o600 }); - defer file.close(); + defer file.close(io); try testing.expectEqual(@as(File.Mode, 0o600), (try file.stat()).mode & 0o7777); try file.chmod(0o644); @@ -2041,7 +2111,7 @@ test "chmod" { try tmp.dir.makeDir("test_dir"); var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); - defer dir.close(); + defer dir.close(io); try dir.chmod(0o700); try testing.expectEqual(@as(File.Mode, 0o700), (try dir.stat()).mode & 0o7777); @@ -2051,17 +2121,19 @@ test "chown" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const file = try tmp.dir.createFile("test_file", .{}); - defer file.close(); + defer file.close(io); try file.chown(null, null); try tmp.dir.makeDir("test_dir"); var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true }); - defer dir.close(); + defer dir.close(io); try dir.chown(null, null); } @@ -2157,7 +2229,7 @@ test "read file non vectored" { const contents = "hello, world!\n"; const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + defer file.close(io); { var file_writer: std.fs.File.Writer = .init(file, &.{}); try file_writer.interface.writeAll(contents); @@ -2189,7 +2261,7 @@ test "seek keeping partial buffer" { const contents = "0123456789"; const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); - defer file.close(); + defer file.close(io); { var file_writer: std.fs.File.Writer = .init(file, &.{}); try file_writer.interface.writeAll(contents); @@ -2231,7 +2303,7 @@ test "seekBy" { try tmp_dir.dir.writeFile(.{ .sub_path = "blah.txt", .data = "let's test seekBy" }); const f = try tmp_dir.dir.openFile("blah.txt", .{ .mode = .read_only }); - defer f.close(); + defer f.close(io); var reader = f.readerStreaming(io, &.{}); try reader.seekBy(2); @@ -2250,7 +2322,7 @@ test "seekTo flushes buffered data" { const contents = "data"; const file = try tmp.dir.createFile("seek.bin", .{ .read = true }); - defer file.close(); + defer file.close(io); { var buf: [16]u8 = undefined; var file_writer = std.fs.File.writer(file, &buf); @@ -2277,9 +2349,9 @@ test "File.Writer sendfile with buffered contents" { { try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" }); const in = try tmp_dir.dir.openFile("a", .{}); - defer in.close(); + defer in.close(io); const out = try tmp_dir.dir.createFile("b", .{}); - defer out.close(); + defer out.close(io); var in_buf: [2]u8 = undefined; var in_r = in.reader(io, &in_buf); @@ -2294,7 +2366,7 @@ test "File.Writer sendfile with buffered contents" { } var check = try tmp_dir.dir.openFile("b", .{}); - defer check.close(); + defer check.close(io); var check_buf: [4]u8 = undefined; var check_r = check.reader(io, &check_buf); try testing.expectEqualStrings("abcd", try check_r.interface.take(4)); diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index 10ab23f476..7f8c9827ef 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -1473,6 +1473,8 @@ pub const ConnectUnixError = Allocator.Error || std.posix.SocketError || error{N /// /// This function is threadsafe. pub fn connectUnix(client: *Client, path: []const u8) ConnectUnixError!*Connection { + const io = client.io; + if (client.connection_pool.findConnection(.{ .host = path, .port = 0, @@ -1485,7 +1487,7 @@ pub fn connectUnix(client: *Client, path: []const u8) ConnectUnixError!*Connecti conn.* = .{ .data = undefined }; const stream = try Io.net.connectUnixSocket(path); - errdefer stream.close(); + errdefer stream.close(io); conn.data = .{ .stream = stream, diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index c927dab376..e4a5bd3738 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -1,13 +1,16 @@ const IoUring = @This(); -const std = @import("std"); + const builtin = @import("builtin"); +const is_linux = builtin.os.tag == .linux; + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const mem = std.mem; const net = std.Io.net; const posix = std.posix; const linux = std.os.linux; const testing = std.testing; -const is_linux = builtin.os.tag == .linux; const page_size_min = std.heap.page_size_min; fd: linux.fd_t = -1, @@ -1975,6 +1978,8 @@ test "readv" { test "writev/fsync/readv" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(4, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -1987,7 +1992,7 @@ test "writev/fsync/readv" { const path = "test_io_uring_writev_fsync_readv"; const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); + defer file.close(io); const fd = file.handle; const buffer_write = [_]u8{42} ** 128; @@ -2045,6 +2050,8 @@ test "writev/fsync/readv" { test "write/read" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(2, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2056,7 +2063,7 @@ test "write/read" { defer tmp.cleanup(); const path = "test_io_uring_write_read"; const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); + defer file.close(io); const fd = file.handle; const buffer_write = [_]u8{97} ** 20; @@ -2092,6 +2099,8 @@ test "write/read" { test "splice/read" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(4, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2102,12 +2111,12 @@ test "splice/read" { var tmp = std.testing.tmpDir(.{}); const path_src = "test_io_uring_splice_src"; const file_src = try tmp.dir.createFile(path_src, .{ .read = true, .truncate = true }); - defer file_src.close(); + defer file_src.close(io); const fd_src = file_src.handle; const path_dst = "test_io_uring_splice_dst"; const file_dst = try tmp.dir.createFile(path_dst, .{ .read = true, .truncate = true }); - defer file_dst.close(); + defer file_dst.close(io); const fd_dst = file_dst.handle; const buffer_write = [_]u8{97} ** 20; @@ -2163,6 +2172,8 @@ test "splice/read" { test "write_fixed/read_fixed" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(2, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2175,7 +2186,7 @@ test "write_fixed/read_fixed" { const path = "test_io_uring_write_read_fixed"; const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); - defer file.close(); + defer file.close(io); const fd = file.handle; var raw_buffers: [2][11]u8 = undefined; @@ -2282,6 +2293,8 @@ test "openat" { test "close" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2294,7 +2307,7 @@ test "close" { const path = "test_io_uring_close"; const file = try tmp.dir.createFile(path, .{}); - errdefer file.close(); + errdefer file.close(io); const sqe_close = try ring.close(0x44444444, file.handle); try testing.expectEqual(linux.IORING_OP.CLOSE, sqe_close.opcode); @@ -2313,6 +2326,8 @@ test "close" { test "accept/connect/send/recv" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2321,7 +2336,7 @@ test "accept/connect/send/recv" { defer ring.deinit(); const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); + defer socket_test_harness.close(io); const buffer_send = [_]u8{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; @@ -2573,6 +2588,8 @@ test "timeout_remove" { test "accept/connect/recv/link_timeout" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2581,7 +2598,7 @@ test "accept/connect/recv/link_timeout" { defer ring.deinit(); const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); + defer socket_test_harness.close(io); var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; @@ -2622,6 +2639,8 @@ test "accept/connect/recv/link_timeout" { test "fallocate" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2634,7 +2653,7 @@ test "fallocate" { const path = "test_io_uring_fallocate"; const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + defer file.close(io); try testing.expectEqual(@as(u64, 0), (try file.stat()).size); @@ -2668,6 +2687,8 @@ test "fallocate" { test "statx" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2679,7 +2700,7 @@ test "statx" { defer tmp.cleanup(); const path = "test_io_uring_statx"; const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + defer file.close(io); try testing.expectEqual(@as(u64, 0), (try file.stat()).size); @@ -2725,6 +2746,8 @@ test "statx" { test "accept/connect/recv/cancel" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2733,7 +2756,7 @@ test "accept/connect/recv/cancel" { defer ring.deinit(); const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); + defer socket_test_harness.close(io); var buffer_recv = [_]u8{ 0, 1, 0, 1, 0 }; @@ -2929,6 +2952,8 @@ test "shutdown" { test "renameat" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -2945,7 +2970,7 @@ test "renameat" { // Write old file with data const old_file = try tmp.dir.createFile(old_path, .{ .truncate = true, .mode = 0o666 }); - defer old_file.close(); + defer old_file.close(io); try old_file.writeAll("hello"); // Submit renameat @@ -2987,6 +3012,8 @@ test "renameat" { test "unlinkat" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -3002,7 +3029,7 @@ test "unlinkat" { // Write old file with data const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + defer file.close(io); // Submit unlinkat @@ -3083,6 +3110,8 @@ test "mkdirat" { test "symlinkat" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -3097,7 +3126,7 @@ test "symlinkat" { const link_path = "test_io_uring_symlinkat_link"; const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + defer file.close(io); // Submit symlinkat @@ -3131,6 +3160,8 @@ test "symlinkat" { test "linkat" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -3147,7 +3178,7 @@ test "linkat" { // Write file with data const first_file = try tmp.dir.createFile(first_path, .{ .truncate = true, .mode = 0o666 }); - defer first_file.close(); + defer first_file.close(io); try first_file.writeAll("hello"); // Submit linkat @@ -3407,6 +3438,8 @@ test "remove_buffers" { test "provide_buffers: accept/connect/send/recv" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -3443,7 +3476,7 @@ test "provide_buffers: accept/connect/send/recv" { } const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); + defer socket_test_harness.close(io); // Do 4 send on the socket @@ -3696,6 +3729,8 @@ test "accept multishot" { test "accept/connect/send_zc/recv" { try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 }); + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -3704,7 +3739,7 @@ test "accept/connect/send_zc/recv" { defer ring.deinit(); const socket_test_harness = try createSocketTestHarness(&ring); - defer socket_test_harness.close(); + defer socket_test_harness.close(io); const buffer_send = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; var buffer_recv = [_]u8{0} ** 10; @@ -4105,6 +4140,8 @@ inline fn skipKernelLessThan(required: std.SemanticVersion) !void { test BufferGroup { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + // Init IoUring var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, @@ -4132,7 +4169,7 @@ test BufferGroup { // Create client/server fds const fds = try createSocketTestHarness(&ring); - defer fds.close(); + defer fds.close(io); const data = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; // Client sends data @@ -4170,6 +4207,8 @@ test BufferGroup { test "ring mapped buffers recv" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -4196,7 +4235,7 @@ test "ring mapped buffers recv" { // create client/server fds const fds = try createSocketTestHarness(&ring); - defer fds.close(); + defer fds.close(io); // for random user_data in sqe/cqe var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); @@ -4259,6 +4298,8 @@ test "ring mapped buffers recv" { test "ring mapped buffers multishot recv" { if (!is_linux) return error.SkipZigTest; + const io = testing.io; + var ring = IoUring.init(16, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, @@ -4285,7 +4326,7 @@ test "ring mapped buffers multishot recv" { // create client/server fds const fds = try createSocketTestHarness(&ring); - defer fds.close(); + defer fds.close(io); // for random user_data in sqe/cqe var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed); diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 7399907477..39606ddfac 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -12,12 +12,14 @@ const fs = std.fs; test "fallocate" { if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30220 + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const path = "test_fallocate"; const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); - defer file.close(); + defer file.close(io); try expect((try file.stat()).size == 0); @@ -77,12 +79,14 @@ test "timer" { } test "statx" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); var buf: linux.Statx = undefined; switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, .BASIC_STATS, &buf))) { @@ -111,12 +115,14 @@ test "user and group ids" { } test "fadvise" { + const io = std.testing.io; + var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const tmp_file_name = "temp_posix_fadvise.txt"; var file = try tmp.dir.createFile(tmp_file_name, .{}); - defer file.close(); + defer file.close(io); var buf: [2048]u8 = undefined; try file.writeAll(&buf); diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 3bb5e64c73..8889e50ea3 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -148,6 +148,8 @@ test "linkat with different directories" { else => return error.SkipZigTest, } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -163,10 +165,10 @@ test "linkat with different directories" { try posix.linkat(tmp.dir.fd, target_name, subdir.fd, link_name, 0); const efd = try tmp.dir.openFile(target_name, .{}); - defer efd.close(); + defer efd.close(io); const nfd = try subdir.openFile(link_name, .{}); - defer nfd.close(); + defer nfd.close(io); { const eino, _ = try getLinkInfo(efd.handle); @@ -381,6 +383,8 @@ test "mmap" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -413,7 +417,7 @@ test "mmap" { // Create a file used for testing mmap() calls with a file descriptor { const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + defer file.close(io); var stream = file.writer(&.{}); @@ -426,7 +430,7 @@ test "mmap" { // Map the whole file { const file = try tmp.dir.openFile(test_out_file, .{}); - defer file.close(); + defer file.close(io); const data = try posix.mmap( null, @@ -451,7 +455,7 @@ test "mmap" { // Map the upper half of the file { const file = try tmp.dir.openFile(test_out_file, .{}); - defer file.close(); + defer file.close(io); const data = try posix.mmap( null, @@ -476,13 +480,15 @@ test "fcntl" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const test_out_file = "os_tmp_test"; const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + defer file.close(io); // Note: The test assumes createFile opens the file with CLOEXEC { @@ -526,12 +532,14 @@ test "fsync" { else => return error.SkipZigTest, } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); const test_out_file = "os_tmp_test"; const file = try tmp.dir.createFile(test_out_file, .{}); - defer file.close(); + defer file.close(io); try posix.fsync(file.handle); try posix.fdatasync(file.handle); @@ -646,22 +654,24 @@ test "dup & dup2" { else => return error.SkipZigTest, } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); { var file = try tmp.dir.createFile("os_dup_test", .{}); - defer file.close(); + defer file.close(io); var duped = std.fs.File{ .handle = try posix.dup(file.handle) }; - defer duped.close(); + defer duped.close(io); try duped.writeAll("dup"); // Tests aren't run in parallel so using the next fd shouldn't be an issue. const new_fd = duped.handle + 1; try posix.dup2(file.handle, new_fd); var dup2ed = std.fs.File{ .handle = new_fd }; - defer dup2ed.close(); + defer dup2ed.close(io); try dup2ed.writeAll("dup2"); } @@ -687,11 +697,13 @@ test "getppid" { test "writev longer than IOV_MAX" { if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var file = try tmp.dir.createFile("pwritev", .{}); - defer file.close(); + defer file.close(io); const iovecs = [_]posix.iovec_const{.{ .base = "a", .len = 1 }} ** (posix.IOV_MAX + 1); const amt = try file.writev(&iovecs); @@ -709,12 +721,14 @@ test "POSIX file locking with fcntl" { return error.SkipZigTest; } + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); // Create a temporary lock file var file = try tmp.dir.createFile("lock", .{ .read = true }); - defer file.close(); + defer file.close(io); try file.setEndPos(2); const fd = file.handle; @@ -905,21 +919,25 @@ test "timerfd" { } test "isatty" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var file = try tmp.dir.createFile("foo", .{}); - defer file.close(); + defer file.close(io); try expectEqual(posix.isatty(file.handle), false); } test "pread with empty buffer" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var file = try tmp.dir.createFile("pread_empty", .{ .read = true }); - defer file.close(); + defer file.close(io); const bytes = try a.alloc(u8, 0); defer a.free(bytes); @@ -929,11 +947,13 @@ test "pread with empty buffer" { } test "write with empty buffer" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var file = try tmp.dir.createFile("write_empty", .{}); - defer file.close(); + defer file.close(io); const bytes = try a.alloc(u8, 0); defer a.free(bytes); @@ -943,11 +963,13 @@ test "write with empty buffer" { } test "pwrite with empty buffer" { + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); var file = try tmp.dir.createFile("pwrite_empty", .{}); - defer file.close(); + defer file.close(io); const bytes = try a.alloc(u8, 0); defer a.free(bytes); diff --git a/lib/std/process.zig b/lib/std/process.zig index a0a26c766f..a8dede6ad4 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1,12 +1,14 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); +const native_os = builtin.os.tag; + +const std = @import("std.zig"); +const Io = std.Io; const fs = std.fs; const mem = std.mem; const math = std.math; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const assert = std.debug.assert; const testing = std.testing; -const native_os = builtin.os.tag; const posix = std.posix; const windows = std.os.windows; const unicode = std.unicode; @@ -1571,9 +1573,9 @@ 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(name: []const u8) !UserInfo { +pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo { const file = try std.fs.openFileAbsolute("/etc/passwd", .{}); - defer file.close(); + defer file.close(io); var buffer: [4096]u8 = undefined; var file_reader = file.reader(&buffer); return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) { diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index 6dad72df44..be3026ff10 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -4,6 +4,7 @@ const builtin = @import("builtin"); const native_os = builtin.os.tag; const std = @import("../std.zig"); +const Io = std.Io; const unicode = std.unicode; const fs = std.fs; const process = std.process; @@ -277,17 +278,17 @@ pub fn spawnAndWait(self: *ChildProcess) SpawnError!Term { } /// Forcibly terminates child process and then cleans up all resources. -pub fn kill(self: *ChildProcess) !Term { +pub fn kill(self: *ChildProcess, io: Io) !Term { if (native_os == .windows) { - return self.killWindows(1); + return self.killWindows(io, 1); } else { - return self.killPosix(); + return self.killPosix(io); } } -pub fn killWindows(self: *ChildProcess, exit_code: windows.UINT) !Term { +pub fn killWindows(self: *ChildProcess, io: Io, exit_code: windows.UINT) !Term { if (self.term) |term| { - self.cleanupStreams(); + self.cleanupStreams(io); return term; } @@ -303,20 +304,20 @@ pub fn killWindows(self: *ChildProcess, exit_code: windows.UINT) !Term { }, else => return err, }; - try self.waitUnwrappedWindows(); + try self.waitUnwrappedWindows(io); return self.term.?; } -pub fn killPosix(self: *ChildProcess) !Term { +pub fn killPosix(self: *ChildProcess, io: Io) !Term { if (self.term) |term| { - self.cleanupStreams(); + self.cleanupStreams(io); return term; } posix.kill(self.id, posix.SIG.TERM) catch |err| switch (err) { error.ProcessNotFound => return error.AlreadyTerminated, else => return err, }; - self.waitUnwrappedPosix(); + self.waitUnwrappedPosix(io); return self.term.?; } @@ -354,15 +355,15 @@ pub fn waitForSpawn(self: *ChildProcess) SpawnError!void { } /// Blocks until child process terminates and then cleans up all resources. -pub fn wait(self: *ChildProcess) WaitError!Term { +pub fn wait(self: *ChildProcess, io: Io) WaitError!Term { try self.waitForSpawn(); // report spawn errors if (self.term) |term| { - self.cleanupStreams(); + self.cleanupStreams(io); return term; } switch (native_os) { - .windows => try self.waitUnwrappedWindows(), - else => self.waitUnwrappedPosix(), + .windows => try self.waitUnwrappedWindows(io), + else => self.waitUnwrappedPosix(io), } self.id = undefined; return self.term.?; @@ -474,7 +475,7 @@ pub fn run(args: struct { }; } -fn waitUnwrappedWindows(self: *ChildProcess) WaitError!void { +fn waitUnwrappedWindows(self: *ChildProcess, io: Io) WaitError!void { const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false); self.term = @as(SpawnError!Term, x: { @@ -492,11 +493,11 @@ fn waitUnwrappedWindows(self: *ChildProcess) WaitError!void { posix.close(self.id); posix.close(self.thread_handle); - self.cleanupStreams(); + self.cleanupStreams(io); return result; } -fn waitUnwrappedPosix(self: *ChildProcess) void { +fn waitUnwrappedPosix(self: *ChildProcess, io: Io) void { const res: posix.WaitPidResult = res: { if (self.request_resource_usage_statistics) { switch (native_os) { @@ -527,7 +528,7 @@ fn waitUnwrappedPosix(self: *ChildProcess) void { break :res posix.waitpid(self.id, 0); }; const status = res.status; - self.cleanupStreams(); + self.cleanupStreams(io); self.handleWaitResult(status); } @@ -535,17 +536,17 @@ fn handleWaitResult(self: *ChildProcess, status: u32) void { self.term = statusToTerm(status); } -fn cleanupStreams(self: *ChildProcess) void { +fn cleanupStreams(self: *ChildProcess, io: Io) void { if (self.stdin) |*stdin| { - stdin.close(); + stdin.close(io); self.stdin = null; } if (self.stdout) |*stdout| { - stdout.close(); + stdout.close(io); self.stdout = null; } if (self.stderr) |*stderr| { - stderr.close(); + stderr.close(io); self.stderr = null; } } diff --git a/lib/std/tar.zig b/lib/std/tar.zig index bf96aed35c..d861314fec 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -16,6 +16,7 @@ //! pax reference: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13 const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const testing = std.testing; @@ -302,7 +303,7 @@ pub const FileKind = enum { /// Iterator over entries in the tar file represented by reader. pub const Iterator = struct { - reader: *std.Io.Reader, + reader: *Io.Reader, diagnostics: ?*Diagnostics = null, // buffers for heeader and file attributes @@ -328,7 +329,7 @@ pub const Iterator = struct { /// Iterates over files in tar archive. /// `next` returns each file in tar archive. - pub fn init(reader: *std.Io.Reader, options: Options) Iterator { + pub fn init(reader: *Io.Reader, options: Options) Iterator { return .{ .reader = reader, .diagnostics = options.diagnostics, @@ -473,7 +474,7 @@ pub const Iterator = struct { return null; } - pub fn streamRemaining(it: *Iterator, file: File, w: *std.Io.Writer) std.Io.Reader.StreamError!void { + pub fn streamRemaining(it: *Iterator, file: File, w: *Io.Writer) Io.Reader.StreamError!void { try it.reader.streamExact64(w, file.size); it.unread_file_bytes = 0; } @@ -499,14 +500,14 @@ const pax_max_size_attr_len = 64; pub const PaxIterator = struct { size: usize, // cumulative size of all pax attributes - reader: *std.Io.Reader, + reader: *Io.Reader, const Self = @This(); const Attribute = struct { kind: PaxAttributeKind, len: usize, // length of the attribute value - reader: *std.Io.Reader, // reader positioned at value start + reader: *Io.Reader, // reader positioned at value start // Copies pax attribute value into destination buffer. // Must be called with destination buffer of size at least Attribute.len. @@ -573,13 +574,13 @@ pub const PaxIterator = struct { } // Checks that each record ends with new line. - fn validateAttributeEnding(reader: *std.Io.Reader) !void { + fn validateAttributeEnding(reader: *Io.Reader) !void { if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd; } }; /// Saves tar file content to the file systems. -pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOptions) !void { +pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOptions) !void { var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; var file_contents_buffer: [1024]u8 = undefined; @@ -610,7 +611,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOp }, .file => { if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| { - defer fs_file.close(); + defer fs_file.close(io); var file_writer = fs_file.writer(&file_contents_buffer); try it.streamRemaining(file, &file_writer.interface); try file_writer.interface.flush(); @@ -637,7 +638,7 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOp } } -fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8, mode: std.fs.File.Mode) !std.fs.File { +fn createDirAndFile(dir: Io.Dir, file_name: []const u8, mode: Io.File.Mode) !Io.File { const fs_file = dir.createFile(file_name, .{ .exclusive = true, .mode = mode }) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { @@ -651,7 +652,7 @@ fn createDirAndFile(dir: std.fs.Dir, file_name: []const u8, mode: std.fs.File.Mo } // Creates a symbolic link at path `file_name` which points to `link_name`. -fn createDirAndSymlink(dir: std.fs.Dir, link_name: []const u8, file_name: []const u8) !void { +fn createDirAndSymlink(dir: Io.Dir, link_name: []const u8, file_name: []const u8) !void { dir.symLink(link_name, file_name, .{}) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { @@ -783,7 +784,7 @@ test PaxIterator { var buffer: [1024]u8 = undefined; outer: for (cases) |case| { - var reader: std.Io.Reader = .fixed(case.data); + var reader: Io.Reader = .fixed(case.data); var it: PaxIterator = .{ .size = case.data.len, .reader = &reader, @@ -874,13 +875,15 @@ test "header parse mode" { } test "create file and symlink" { + const io = testing.io; + var root = testing.tmpDir(.{}); defer root.cleanup(); var file = try createDirAndFile(root.dir, "file1", default_mode); - file.close(); + file.close(io); file = try createDirAndFile(root.dir, "a/b/c/file2", default_mode); - file.close(); + file.close(io); createDirAndSymlink(root.dir, "a/b/c/file2", "symlink1") catch |err| { // On Windows when developer mode is not enabled @@ -892,7 +895,7 @@ test "create file and symlink" { // Danglink symlnik, file created later try createDirAndSymlink(root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); file = try createDirAndFile(root.dir, "g/h/i/file4", default_mode); - file.close(); + file.close(io); } test Iterator { @@ -916,7 +919,7 @@ test Iterator { // example/empty/ const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); // User provided buffers to the iterator var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; @@ -942,7 +945,7 @@ test Iterator { .file => { try testing.expectEqualStrings("example/a/file", file.name); var buf: [16]u8 = undefined; - var w: std.Io.Writer = .fixed(&buf); + var w: Io.Writer = .fixed(&buf); try it.streamRemaining(file, &w); try testing.expectEqualStrings("content\n", w.buffered()); }, @@ -955,6 +958,7 @@ test Iterator { } test pipeToFileSystem { + const io = testing.io; // Example tar file is created from this tree structure: // $ tree example // example @@ -975,14 +979,14 @@ test pipeToFileSystem { // example/empty/ const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); defer tmp.cleanup(); const dir = tmp.dir; // Save tar from reader to the file system `dir` - pipeToFileSystem(dir, &reader, .{ + pipeToFileSystem(io, dir, &reader, .{ .mode_mode = .ignore, .strip_components = 1, .exclude_empty_directories = true, @@ -1005,8 +1009,9 @@ test pipeToFileSystem { } test "pipeToFileSystem root_dir" { + const io = testing.io; const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); // with strip_components = 1 { @@ -1015,7 +1020,7 @@ test "pipeToFileSystem root_dir" { var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 1, .diagnostics = &diagnostics, }) catch |err| { @@ -1037,7 +1042,7 @@ test "pipeToFileSystem root_dir" { var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 0, .diagnostics = &diagnostics, }) catch |err| { @@ -1053,43 +1058,46 @@ test "pipeToFileSystem root_dir" { } test "findRoot with single file archive" { + const io = testing.io; const data = @embedFile("tar/testdata/22752.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics }); + try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); try testing.expectEqualStrings("", diagnostics.root_dir); } test "findRoot without explicit root dir" { + const io = testing.io; const data = @embedFile("tar/testdata/19820.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics }); + try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); try testing.expectEqualStrings("root", diagnostics.root_dir); } test "pipeToFileSystem strip_components" { + const io = testing.io; const data = @embedFile("tar/testdata/example.tar"); - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); defer tmp.cleanup(); var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 3, .diagnostics = &diagnostics, }) catch |err| { @@ -1110,10 +1118,10 @@ fn normalizePath(bytes: []u8) []u8 { return bytes; } -const default_mode = std.fs.File.default_mode; +const default_mode = Io.File.default_mode; // File system mode based on tar header mode and mode_mode options. -fn fileMode(mode: u32, options: PipeOptions) std.fs.File.Mode { +fn fileMode(mode: u32, options: PipeOptions) Io.File.Mode { if (!std.fs.has_executable_bit or options.mode_mode == .ignore) return default_mode; @@ -1139,16 +1147,17 @@ test fileMode { test "executable bit" { if (!std.fs.has_executable_bit) return error.SkipZigTest; + const io = testing.io; const S = std.posix.S; const data = @embedFile("tar/testdata/example.tar"); for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| { - var reader: std.Io.Reader = .fixed(data); + var reader: Io.Reader = .fixed(data); var tmp = testing.tmpDir(.{ .follow_symlinks = false }); //defer tmp.cleanup(); - pipeToFileSystem(tmp.dir, &reader, .{ + pipeToFileSystem(io, tmp.dir, &reader, .{ .strip_components = 1, .exclude_empty_directories = true, .mode_mode = opt, diff --git a/lib/std/tar/test.zig b/lib/std/tar/test.zig index 780e2b844c..b3fbd8f4b3 100644 --- a/lib/std/tar/test.zig +++ b/lib/std/tar/test.zig @@ -424,6 +424,7 @@ test "insufficient buffer in Header name filed" { } test "should not overwrite existing file" { + const io = testing.io; // Starting from this folder structure: // $ tree root // root @@ -469,17 +470,18 @@ test "should not overwrite existing file" { defer root.cleanup(); try testing.expectError( error.PathAlreadyExists, - tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }), + tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }), ); // Unpack with strip_components = 0 should pass r = .fixed(data); var root2 = std.testing.tmpDir(.{}); defer root2.cleanup(); - try tar.pipeToFileSystem(root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 }); + try tar.pipeToFileSystem(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 }); } test "case sensitivity" { + const io = testing.io; // Mimicking issue #18089, this tar contains, same file name in two case // sensitive name version. Should fail on case insensitive file systems. // @@ -495,7 +497,7 @@ test "case sensitivity" { var root = std.testing.tmpDir(.{}); defer root.cleanup(); - tar.pipeToFileSystem(root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| { + tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| { // on case insensitive fs we fail on overwrite existing file try testing.expectEqual(error.PathAlreadyExists, err); return; diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 186cafad59..63131d771c 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -613,9 +613,9 @@ pub const TmpDir = struct { const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); pub fn cleanup(self: *TmpDir) void { - self.dir.close(); + self.dir.close(io); self.parent_dir.deleteTree(&self.sub_path) catch {}; - self.parent_dir.close(); + self.parent_dir.close(io); self.* = undefined; } }; @@ -629,7 +629,7 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir { const cwd = std.fs.cwd(); var cache_dir = cwd.makeOpenPath(".zig-cache", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(); + defer cache_dir.close(io); const parent_dir = cache_dir.makeOpenPath("tmp", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); const dir = parent_dir.makeOpenPath(&sub_path, opts) catch diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index 2ab4e48570..c8bde2ab02 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -1,4 +1,18 @@ //! See the render function implementation for documentation of the fields. +const LibCInstallation = @This(); + +const builtin = @import("builtin"); +const is_darwin = builtin.target.os.tag.isDarwin(); +const is_windows = builtin.target.os.tag == .windows; +const is_haiku = builtin.target.os.tag == .haiku; + +const std = @import("std"); +const Io = std.Io; +const Target = std.Target; +const fs = std.fs; +const Allocator = std.mem.Allocator; +const Path = std.Build.Cache.Path; +const log = std.log.scoped(.libc_installation); include_dir: ?[]const u8 = null, sys_include_dir: ?[]const u8 = null, @@ -157,6 +171,7 @@ pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { pub const FindNativeOptions = struct { allocator: Allocator, + io: Io, target: *const std.Target, /// If enabled, will print human-friendly errors to stderr. @@ -165,29 +180,32 @@ pub const FindNativeOptions = struct { /// Finds the default, native libc. pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { + const gpa = args.allocator; + const io = args.io; + var self: LibCInstallation = .{}; if (is_darwin and args.target.os.tag.isDarwin()) { - if (!std.zig.system.darwin.isSdkInstalled(args.allocator)) + if (!std.zig.system.darwin.isSdkInstalled(gpa)) return error.DarwinSdkNotFound; - const sdk = std.zig.system.darwin.getSdk(args.allocator, args.target) orelse + const sdk = std.zig.system.darwin.getSdk(gpa, args.target) orelse return error.DarwinSdkNotFound; - defer args.allocator.free(sdk); + defer gpa.free(sdk); - self.include_dir = try fs.path.join(args.allocator, &.{ + self.include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include", }); - self.sys_include_dir = try fs.path.join(args.allocator, &.{ + self.sys_include_dir = try fs.path.join(gpa, &.{ sdk, "usr/include", }); return self; } else if (is_windows) { - const sdk = std.zig.WindowsSdk.find(args.allocator, args.target.cpu.arch) catch |err| switch (err) { + const sdk = std.zig.WindowsSdk.find(gpa, io, args.target.cpu.arch) catch |err| switch (err) { error.NotFound => return error.WindowsSdkNotFound, error.PathTooLong => return error.WindowsSdkNotFound, error.OutOfMemory => return error.OutOfMemory, }; - defer sdk.free(args.allocator); + defer sdk.free(gpa); try self.findNativeMsvcIncludeDir(args, sdk); try self.findNativeMsvcLibDir(args, sdk); @@ -197,16 +215,16 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { } else if (is_haiku) { try self.findNativeIncludeDirPosix(args); try self.findNativeGccDirHaiku(args); - self.crt_dir = try args.allocator.dupeZ(u8, "/system/develop/lib"); + self.crt_dir = try gpa.dupeZ(u8, "/system/develop/lib"); } else if (builtin.target.os.tag == .illumos) { // There is only one libc, and its headers/libraries are always in the same spot. - self.include_dir = try args.allocator.dupeZ(u8, "/usr/include"); - self.sys_include_dir = try args.allocator.dupeZ(u8, "/usr/include"); - self.crt_dir = try args.allocator.dupeZ(u8, "/usr/lib/64"); + self.include_dir = try gpa.dupeZ(u8, "/usr/include"); + self.sys_include_dir = try gpa.dupeZ(u8, "/usr/include"); + self.crt_dir = try gpa.dupeZ(u8, "/usr/lib/64"); } else if (std.process.can_spawn) { try self.findNativeIncludeDirPosix(args); switch (builtin.target.os.tag) { - .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try args.allocator.dupeZ(u8, "/usr/lib"), + .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try gpa.dupeZ(u8, "/usr/lib"), .linux => try self.findNativeCrtDirPosix(args), else => {}, } @@ -229,6 +247,7 @@ pub fn deinit(self: *LibCInstallation, allocator: Allocator) void { fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { const allocator = args.allocator; + const io = args.io; // Detect infinite loops. var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { @@ -326,7 +345,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F else => return error.FileSystem, }; - defer search_dir.close(); + defer search_dir.close(io); if (self.include_dir == null) { if (search_dir.access(include_dir_example_file, .{})) |_| { @@ -361,6 +380,7 @@ fn findNativeIncludeDirWindows( sdk: std.zig.WindowsSdk, ) FindError!void { const allocator = args.allocator; + const io = args.io; var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); @@ -380,7 +400,7 @@ fn findNativeIncludeDirWindows( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); dir.access("stdlib.h", .{}) catch |err| switch (err) { error.FileNotFound => continue, @@ -400,6 +420,7 @@ fn findNativeCrtDirWindows( sdk: std.zig.WindowsSdk, ) FindError!void { const allocator = args.allocator; + const io = args.io; var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); @@ -427,7 +448,7 @@ fn findNativeCrtDirWindows( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); dir.access("ucrt.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, @@ -467,6 +488,7 @@ fn findNativeKernel32LibDir( sdk: std.zig.WindowsSdk, ) FindError!void { const allocator = args.allocator; + const io = args.io; var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); @@ -494,7 +516,7 @@ fn findNativeKernel32LibDir( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); dir.access("kernel32.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, @@ -513,6 +535,7 @@ fn findNativeMsvcIncludeDir( sdk: std.zig.WindowsSdk, ) FindError!void { const allocator = args.allocator; + const io = args.io; const msvc_lib_dir = sdk.msvc_lib_dir orelse return error.LibCStdLibHeaderNotFound; const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; @@ -529,7 +552,7 @@ fn findNativeMsvcIncludeDir( else => return error.FileSystem, }; - defer dir.close(); + defer dir.close(io); dir.access("vcruntime.h", .{}) catch |err| switch (err) { error.FileNotFound => return error.LibCStdLibHeaderNotFound, @@ -1015,17 +1038,3 @@ pub fn resolveCrtPaths( }, } } - -const LibCInstallation = @This(); -const std = @import("std"); -const builtin = @import("builtin"); -const Target = std.Target; -const fs = std.fs; -const Allocator = std.mem.Allocator; -const Path = std.Build.Cache.Path; - -const is_darwin = builtin.target.os.tag.isDarwin(); -const is_windows = builtin.target.os.tag == .windows; -const is_haiku = builtin.target.os.tag == .haiku; - -const log = std.log.scoped(.libc_installation); diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index 89d608633c..a7b16e1bed 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -1,7 +1,10 @@ const WindowsSdk = @This(); const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; windows10sdk: ?Installation, windows81sdk: ?Installation, @@ -20,7 +23,7 @@ const product_version_max_length = version_major_minor_max_length + ".65535".len /// Find path and version of Windows 10 SDK and Windows 8.1 SDK, and find path to MSVC's `lib/` directory. /// Caller owns the result's fields. /// After finishing work, call `free(allocator)`. -pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk { +pub fn find(allocator: Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, NotFound, PathTooLong }!WindowsSdk { if (builtin.os.tag != .windows) return error.NotFound; //note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed @@ -58,7 +61,7 @@ pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutO }; } -pub fn free(sdk: WindowsSdk, allocator: std.mem.Allocator) void { +pub fn free(sdk: WindowsSdk, allocator: Allocator) void { if (sdk.windows10sdk) |*w10sdk| { w10sdk.free(allocator); } @@ -75,7 +78,7 @@ pub fn free(sdk: WindowsSdk, allocator: std.mem.Allocator) void { /// Caller owns result. fn iterateAndFilterByVersion( iterator: *std.fs.Dir.Iterator, - allocator: std.mem.Allocator, + allocator: Allocator, prefix: []const u8, ) error{OutOfMemory}![][]const u8 { const Version = struct { @@ -174,7 +177,7 @@ const RegistryWtf8 = struct { /// Get string from registry. /// Caller owns result. - pub fn getString(reg: RegistryWtf8, allocator: std.mem.Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 { + pub fn getString(reg: RegistryWtf8, allocator: Allocator, subkey: []const u8, value_name: []const u8) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]u8 { const subkey_wtf16le: [:0]const u16 = subkey_wtf16le: { var subkey_wtf16le_buf: [RegistryWtf16Le.key_name_max_len]u16 = undefined; const subkey_wtf16le_len: usize = std.unicode.wtf8ToWtf16Le(subkey_wtf16le_buf[0..], subkey) catch unreachable; @@ -282,7 +285,7 @@ const RegistryWtf16Le = struct { } /// Get string ([:0]const u16) from registry. - fn getString(reg: RegistryWtf16Le, allocator: std.mem.Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 { + fn getString(reg: RegistryWtf16Le, allocator: Allocator, subkey_wtf16le: [:0]const u16, value_name_wtf16le: [:0]const u16) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }![]const u16 { var actual_type: windows.ULONG = undefined; // Calculating length to allocate @@ -416,7 +419,7 @@ pub const Installation = struct { /// Caller owns the result's fields. /// After finishing work, call `free(allocator)`. fn find( - allocator: std.mem.Allocator, + allocator: Allocator, roots_key: RegistryWtf8, roots_subkey: []const u8, prefix: []const u8, @@ -437,7 +440,8 @@ pub const Installation = struct { } fn findFromRoot( - allocator: std.mem.Allocator, + allocator: Allocator, + io: Io, roots_key: RegistryWtf8, roots_subkey: []const u8, prefix: []const u8, @@ -478,7 +482,7 @@ pub const Installation = struct { error.NameTooLong => return error.PathTooLong, else => return error.InstallationNotFound, }; - defer sdk_lib_dir.close(); + defer sdk_lib_dir.close(io); var iterator = sdk_lib_dir.iterate(); const versions = try iterateAndFilterByVersion(&iterator, allocator, prefix); @@ -495,7 +499,7 @@ pub const Installation = struct { } fn findFromInstallationFolder( - allocator: std.mem.Allocator, + allocator: Allocator, version_key_name: []const u8, ) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation { var key_name_buf: [RegistryWtf16Le.key_name_max_len]u8 = undefined; @@ -597,14 +601,14 @@ pub const Installation = struct { return (reg_value == 1); } - fn free(install: Installation, allocator: std.mem.Allocator) void { + fn free(install: Installation, allocator: Allocator) void { allocator.free(install.path); allocator.free(install.version); } }; const MsvcLibDir = struct { - fn findInstancesDirViaSetup(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaSetup(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup"; const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, @@ -629,7 +633,7 @@ const MsvcLibDir = struct { return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDirViaCLSID(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaCLSID(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}"; const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, @@ -665,7 +669,7 @@ const MsvcLibDir = struct { return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDir(allocator: std.mem.Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDir(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { // First, try getting the packages cache path from the registry. // This only seems to exist when the path is different from the default. method1: { @@ -748,13 +752,13 @@ const MsvcLibDir = struct { /// /// The logic in this function is intended to match what ISetupConfiguration does /// under-the-hood, as verified using Procmon. - fn findViaCOM(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaCOM(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { // Typically `%PROGRAMDATA%\Microsoft\VisualStudio\Packages\_Instances` // This will contain directories with names of instance IDs like 80a758ca, // which will contain `state.json` files that have the version and // installation directory. var instances_dir = try findInstancesDir(allocator); - defer instances_dir.close(); + defer instances_dir.close(io); var state_subpath_buf: [std.fs.max_name_bytes + 32]u8 = undefined; var latest_version_lib_dir: std.ArrayList(u8) = .empty; @@ -791,7 +795,7 @@ const MsvcLibDir = struct { const installation_path = parsed.value.object.get("installationPath") orelse continue; if (installation_path != .string) continue; - const lib_dir_path = libDirFromInstallationPath(allocator, installation_path.string, arch) catch |err| switch (err) { + const lib_dir_path = libDirFromInstallationPath(allocator, io, installation_path.string, arch) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.PathNotFound => continue, }; @@ -806,7 +810,12 @@ const MsvcLibDir = struct { return latest_version_lib_dir.toOwnedSlice(allocator); } - fn libDirFromInstallationPath(allocator: std.mem.Allocator, installation_path: []const u8, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn libDirFromInstallationPath( + allocator: Allocator, + io: Io, + installation_path: []const u8, + arch: std.Target.Cpu.Arch, + ) error{ OutOfMemory, PathNotFound }![]const u8 { var lib_dir_buf = try std.array_list.Managed(u8).initCapacity(allocator, installation_path.len + 64); errdefer lib_dir_buf.deinit(); @@ -837,7 +846,7 @@ const MsvcLibDir = struct { else => unreachable, }); - if (!verifyLibDir(lib_dir_buf.items)) { + if (!verifyLibDir(io, lib_dir_buf.items)) { return error.PathNotFound; } @@ -845,7 +854,7 @@ const MsvcLibDir = struct { } // https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#editing-the-registry-for-a-visual-studio-instance - fn findViaRegistry(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaRegistry(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { // %localappdata%\Microsoft\VisualStudio\ // %appdata%\Local\Microsoft\VisualStudio\ @@ -859,7 +868,7 @@ const MsvcLibDir = struct { var visualstudio_folder = std.fs.openDirAbsolute(visualstudio_folder_path, .{ .iterate = true, }) catch return error.PathNotFound; - defer visualstudio_folder.close(); + defer visualstudio_folder.close(io); var iterator = visualstudio_folder.iterate(); break :vs_versions try iterateAndFilterByVersion(&iterator, allocator, ""); @@ -926,14 +935,14 @@ const MsvcLibDir = struct { }; errdefer allocator.free(msvc_dir); - if (!verifyLibDir(msvc_dir)) { + if (!verifyLibDir(io, msvc_dir)) { return error.PathNotFound; } return msvc_dir; } - fn findViaVs7Key(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { + fn findViaVs7Key(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, PathNotFound }![]const u8 { var base_path: std.array_list.Managed(u8) = base_path: { try_env: { var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { @@ -989,7 +998,7 @@ const MsvcLibDir = struct { else => unreachable, }); - if (!verifyLibDir(base_path.items)) { + if (!verifyLibDir(io, base_path.items)) { return error.PathNotFound; } @@ -997,11 +1006,11 @@ const MsvcLibDir = struct { return full_path; } - fn verifyLibDir(lib_dir_path: []const u8) bool { + fn verifyLibDir(io: Io, lib_dir_path: []const u8) bool { std.debug.assert(std.fs.path.isAbsolute(lib_dir_path)); // should be already handled in `findVia*` var dir = std.fs.openDirAbsolute(lib_dir_path, .{}) catch return false; - defer dir.close(); + defer dir.close(io); const stat = dir.statFile("vcruntime.lib") catch return false; if (stat.kind != .file) @@ -1012,12 +1021,12 @@ const MsvcLibDir = struct { /// Find path to MSVC's `lib/` directory. /// Caller owns the result. - pub fn find(allocator: std.mem.Allocator, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 { - const full_path = MsvcLibDir.findViaCOM(allocator, arch) catch |err1| switch (err1) { + pub fn find(allocator: Allocator, io: Io, arch: std.Target.Cpu.Arch) error{ OutOfMemory, MsvcLibDirNotFound }![]const u8 { + const full_path = MsvcLibDir.findViaCOM(allocator, io, arch) catch |err1| switch (err1) { error.OutOfMemory => return error.OutOfMemory, - error.PathNotFound => MsvcLibDir.findViaRegistry(allocator, arch) catch |err2| switch (err2) { + error.PathNotFound => MsvcLibDir.findViaRegistry(allocator, io, arch) catch |err2| switch (err2) { error.OutOfMemory => return error.OutOfMemory, - error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator, arch) catch |err3| switch (err3) { + error.PathNotFound => MsvcLibDir.findViaVs7Key(allocator, io, arch) catch |err3| switch (err3) { error.OutOfMemory => return error.OutOfMemory, error.PathNotFound => return error.MsvcLibDirNotFound, }, diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 587ac82c70..9a52ae2c81 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1,14 +1,17 @@ +const builtin = @import("builtin"); +const Builder = @This(); + const std = @import("../../std.zig"); +const Io = std.Io; const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const bitcode_writer = @import("bitcode_writer.zig"); -const Builder = @This(); -const builtin = @import("builtin"); const DW = std.dwarf; -const ir = @import("ir.zig"); const log = std.log.scoped(.llvm); const Writer = std.Io.Writer; +const bitcode_writer = @import("bitcode_writer.zig"); +const ir = @import("ir.zig"); + gpa: Allocator, strip: bool, @@ -9579,11 +9582,11 @@ pub fn dump(b: *Builder) void { b.printToFile(stderr, &buffer) catch {}; } -pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void { +pub fn printToFilePath(b: *Builder, io: Io, dir: std.fs.Dir, path: []const u8) !void { var buffer: [4000]u8 = undefined; - const file = try dir.createFile(path, .{}); - defer file.close(); - try b.printToFile(file, &buffer); + const file = try dir.createFile(io, path, .{}); + defer file.close(io); + try b.printToFile(io, file, &buffer); } pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void { diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 290cd8d388..4f0c11797d 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -847,7 +847,7 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { error.Unexpected => |e| return e, error.Canceled => |e| return e, }; - defer file.close(); + defer file.close(io); // Empirically, glibc 2.34 libc.so .dynstr section is 32441 bytes on my system. var buffer: [8000]u8 = undefined; @@ -1051,7 +1051,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ else => |e| return e, }; var is_elf_file = false; - defer if (!is_elf_file) file.close(); + defer if (!is_elf_file) file.close(io); file_reader = .initAdapted(file, io, &file_reader_buffer); file_name = undefined; // it aliases file_reader_buffer diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig index 6b4f0cf6f9..668e5a1d99 100644 --- a/lib/std/zig/system/linux.zig +++ b/lib/std/zig/system/linux.zig @@ -447,7 +447,7 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { var file = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) { else => return null, }; - defer file.close(); + defer file.close(io); var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long. var file_reader = file.reader(io, &buffer); diff --git a/lib/std/zip.zig b/lib/std/zip.zig index 583377e00a..c2dbaf5b81 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -554,17 +554,19 @@ pub const Iterator = struct { return; } + const io = stream.io; + const out_file = blk: { if (std.fs.path.dirname(filename)) |dirname| { var parent_dir = try dest.makeOpenPath(dirname, .{}); - defer parent_dir.close(); + defer parent_dir.close(io); const basename = std.fs.path.basename(filename); break :blk try parent_dir.createFile(basename, .{ .exclusive = true }); } break :blk try dest.createFile(filename, .{ .exclusive = true }); }; - defer out_file.close(); + defer out_file.close(io); var out_file_buffer: [1024]u8 = undefined; var file_writer = out_file.writer(&out_file_buffer); const local_data_file_offset: u64 = diff --git a/src/Compilation.zig b/src/Compilation.zig index 931a0b2d14..df64dee19f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -721,13 +721,13 @@ pub const Directories = struct { /// This may be the same as `global_cache`. local_cache: Cache.Directory, - pub fn deinit(dirs: *Directories) void { + pub fn deinit(dirs: *Directories, io: Io) void { // The local and global caches could be the same. const close_local = dirs.local_cache.handle.fd != dirs.global_cache.handle.fd; - dirs.global_cache.handle.close(); - if (close_local) dirs.local_cache.handle.close(); - dirs.zig_lib.handle.close(); + dirs.global_cache.handle.close(io); + if (close_local) dirs.local_cache.handle.close(io); + dirs.zig_lib.handle.close(io); } /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for @@ -1105,7 +1105,7 @@ pub const CObject = struct { if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0; const file = fs.cwd().openFile(file_name, .{}) catch break :source_line 0; - defer file.close(); + defer file.close(io); var buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &buffer); file_reader.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0; @@ -1180,7 +1180,7 @@ pub const CObject = struct { var buffer: [1024]u8 = undefined; const file = try fs.cwd().openFile(path, .{}); - defer file.close(); + defer file.close(io); var file_reader = file.reader(io, &buffer); var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface }); defer bc.deinit(); @@ -1617,13 +1617,13 @@ const CacheUse = union(CacheMode) { } }; - fn deinit(cu: CacheUse) void { + fn deinit(cu: CacheUse, io: Io) void { switch (cu) { .none => |none| { assert(none.tmp_artifact_directory == null); }, .incremental => |incremental| { - incremental.artifact_directory.handle.close(); + incremental.artifact_directory.handle.close(io); }, .whole => |whole| { assert(whole.tmp_artifact_directory == null); @@ -2113,7 +2113,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, cache.addPrefix(options.dirs.zig_lib); cache.addPrefix(options.dirs.local_cache); cache.addPrefix(options.dirs.global_cache); - errdefer cache.manifest_dir.close(); + errdefer cache.manifest_dir.close(io); // This is shared hasher state common to zig source and all C source files. cache.hash.addBytes(build_options.version); @@ -2157,7 +2157,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, var local_zir_dir = options.dirs.local_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = zir_sub_dir, .err = err } }); }; - errdefer local_zir_dir.close(); + errdefer local_zir_dir.close(io); const local_zir_cache: Cache.Directory = .{ .handle = local_zir_dir, .path = try options.dirs.local_cache.join(arena, &.{zir_sub_dir}), @@ -2165,7 +2165,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, var global_zir_dir = options.dirs.global_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .global, .sub = zir_sub_dir, .err = err } }); }; - errdefer global_zir_dir.close(); + errdefer global_zir_dir.close(io); const global_zir_cache: Cache.Directory = .{ .handle = global_zir_dir, .path = try options.dirs.global_cache.join(arena, &.{zir_sub_dir}), @@ -2436,7 +2436,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, var artifact_dir = options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = artifact_sub_dir, .err = err } }); }; - errdefer artifact_dir.close(); + errdefer artifact_dir.close(io); const artifact_directory: Cache.Directory = .{ .handle = artifact_dir, .path = try options.dirs.local_cache.join(arena, &.{artifact_sub_dir}), @@ -2689,6 +2689,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, pub fn destroy(comp: *Compilation) void { const gpa = comp.gpa; + const io = comp.io; if (comp.bin_file) |lf| lf.destroy(); if (comp.zcu) |zcu| zcu.deinit(); @@ -2760,7 +2761,7 @@ pub fn destroy(comp: *Compilation) void { comp.clearMiscFailures(); - comp.cache_parent.manifest_dir.close(); + comp.cache_parent.manifest_dir.close(io); } pub fn clearMiscFailures(comp: *Compilation) void { @@ -2791,10 +2792,12 @@ pub fn hotCodeSwap( } fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void { + const io = comp.io; + switch (comp.cache_use) { .none => |none| { if (none.tmp_artifact_directory) |*tmp_dir| { - tmp_dir.handle.close(); + tmp_dir.handle.close(io); none.tmp_artifact_directory = null; if (dev.env == .bootstrap) { // zig1 uses `CacheMode.none`, but it doesn't need to know how to delete @@ -2834,7 +2837,7 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void { comp.bin_file = null; } if (whole.tmp_artifact_directory) |*tmp_dir| { - tmp_dir.handle.close(); + tmp_dir.handle.close(io); whole.tmp_artifact_directory = null; const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| { @@ -3152,7 +3155,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // the file handle and re-open it in the follow up call to // `makeWritable`. if (lf.file) |f| { - f.close(); + f.close(io); lf.file = null; if (lf.closeDebugInfo()) break :w .lf_and_debug; @@ -3165,7 +3168,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // Rename the temporary directory into place. // Close tmp dir and link.File to avoid open handle during rename. - whole.tmp_artifact_directory.?.handle.close(); + whole.tmp_artifact_directory.?.handle.close(io); whole.tmp_artifact_directory = null; const s = fs.path.sep_str; const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); @@ -5258,6 +5261,7 @@ fn workerDocsCopy(comp: *Compilation) void { fn docsCopyFallible(comp: *Compilation) anyerror!void { const zcu = comp.zcu orelse return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{}); + const io = comp.io; const docs_path = comp.resolveEmitPath(comp.emit_docs.?); var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| { @@ -5267,7 +5271,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { .{ docs_path, @errorName(err) }, ); }; - defer out_dir.close(); + defer out_dir.close(io); for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| { const basename = fs.path.basename(sub_path); @@ -5287,7 +5291,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { .{ docs_path, @errorName(err) }, ); }; - defer tar_file.close(); + defer tar_file.close(io); var buffer: [1024]u8 = undefined; var tar_file_writer = tar_file.writer(&buffer); @@ -5331,7 +5335,7 @@ fn docsCopyModule( } catch |err| { return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {t}", .{ root.fmt(comp), err }); }; - defer mod_dir.close(); + defer mod_dir.close(io); var walker = try mod_dir.walk(comp.gpa); defer walker.deinit(); @@ -5355,7 +5359,7 @@ fn docsCopyModule( root.fmt(comp), entry.path, err, }); }; - defer file.close(); + defer file.close(io); const stat = try file.stat(); var file_reader: fs.File.Reader = .initSize(file.adaptToNewApi(), io, &buffer, stat.size); @@ -5510,7 +5514,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU ); return error.AlreadyReported; }; - defer out_dir.close(); + defer out_dir.close(io); crt_file.full_object_path.root_dir.handle.copyFile( crt_file.full_object_path.sub_path, @@ -5693,7 +5697,7 @@ pub fn translateC( const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; const cache_dir = comp.dirs.local_cache.handle; var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{}); - defer cache_tmp_dir.close(); + defer cache_tmp_dir.close(io); const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); const source_path = switch (source) { @@ -6268,7 +6272,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr // so we need a temporary filename. const out_obj_path = try comp.tmpFilePath(arena, o_basename); var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); - defer zig_cache_tmp_dir.close(); + defer zig_cache_tmp_dir.close(io); const out_diag_path = if (comp.clang_passthrough_mode or !ext.clangSupportsDiagnostics()) null @@ -6433,7 +6437,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + defer o_dir.close(io); const tmp_basename = fs.path.basename(out_obj_path); try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename); break :blk digest; @@ -6477,8 +6481,6 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const tracy_trace = trace(@src()); defer tracy_trace.end(); - const io = comp.io; - const src_path = switch (win32_resource.src) { .rc => |rc_src| rc_src.src_path, .manifest => |src_path| src_path, @@ -6487,6 +6489,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 log.debug("updating win32 resource: {s}", .{src_path}); + const io = comp.io; + var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -6522,7 +6526,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const o_sub_path = try fs.path.join(arena, &.{ "o", &digest }); var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + defer o_dir.close(io); const in_rc_path = try comp.dirs.local_cache.join(comp.gpa, &.{ o_sub_path, rc_basename, @@ -6610,7 +6614,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const digest = if (try man.hit()) man.final() else blk: { var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); - defer zig_cache_tmp_dir.close(); + defer zig_cache_tmp_dir.close(io); const res_filename = try std.fmt.allocPrint(arena, "{s}.res", .{rc_basename_noext}); @@ -6681,7 +6685,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + defer o_dir.close(io); const tmp_basename = fs.path.basename(out_res_path); try fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename); break :blk digest; diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 9b7c83cc39..58f970abe5 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -513,7 +513,7 @@ fn runResource( break :handle dir; }, }; - defer tmp_directory.handle.close(); + defer tmp_directory.handle.close(io); // Fetch and unpack a resource into a temporary directory. var unpack_result = try unpackResource(f, resource, uri_path, tmp_directory); @@ -523,7 +523,7 @@ fn runResource( // Apply btrfs workaround if needed. Reopen tmp_directory. if (native_os == .linux and f.job_queue.work_around_btrfs_bug) { // https://github.com/ziglang/zig/issues/17095 - pkg_path.root_dir.handle.close(); + pkg_path.root_dir.handle.close(io); pkg_path.root_dir.handle = cache_root.handle.makeOpenPath(tmp_dir_sub_path, .{ .iterate = true, }) catch @panic("btrfs workaround failed"); @@ -885,7 +885,7 @@ const Resource = union(enum) { file: fs.File.Reader, http_request: HttpRequest, git: Git, - dir: fs.Dir, + dir: Io.Dir, const Git = struct { session: git.Session, @@ -908,7 +908,7 @@ const Resource = union(enum) { .git => |*git_resource| { git_resource.fetch_stream.deinit(); }, - .dir => |*dir| dir.close(), + .dir => |*dir| dir.close(io), } resource.* = undefined; } @@ -1247,13 +1247,14 @@ fn unpackResource( } } -fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: *Io.Reader) RunError!UnpackResult { +fn unpackTarball(f: *Fetch, out_dir: Io.Dir, reader: *Io.Reader) RunError!UnpackResult { const eb = &f.error_bundle; const arena = f.arena.allocator(); + const io = f.job_queue.io; var diagnostics: std.tar.Diagnostics = .{ .allocator = arena }; - std.tar.pipeToFileSystem(out_dir, reader, .{ + std.tar.pipeToFileSystem(io, out_dir, reader, .{ .diagnostics = &diagnostics, .strip_components = 0, .mode_mode = .ignore, @@ -1280,7 +1281,7 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: *Io.Reader) RunError!Unpack fn unzip( f: *Fetch, - out_dir: fs.Dir, + out_dir: Io.Dir, reader: *Io.Reader, ) error{ ReadFailed, OutOfMemory, Canceled, FetchFailed }!UnpackResult { // We write the entire contents to a file first because zip files @@ -1314,7 +1315,7 @@ fn unzip( ), }; }; - defer zip_file.close(); + defer zip_file.close(io); var zip_file_buffer: [4096]u8 = undefined; var zip_file_reader = b: { var zip_file_writer = zip_file.writer(&zip_file_buffer); @@ -1349,7 +1350,7 @@ fn unzip( return .{ .root_dir = diagnostics.root_dir }; } -fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!UnpackResult { +fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!UnpackResult { const io = f.job_queue.io; const arena = f.arena.allocator(); // TODO don't try to get a gpa from an arena. expose this dependency higher up @@ -1363,9 +1364,9 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U // directory, since that isn't relevant for fetching a package. { var pack_dir = try out_dir.makeOpenPath(".git", .{}); - defer pack_dir.close(); + defer pack_dir.close(io); var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); - defer pack_file.close(); + defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = b: { var pack_file_writer = pack_file.writer(&pack_file_buffer); @@ -1376,7 +1377,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U }; var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); - defer index_file.close(); + defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); { @@ -1393,7 +1394,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U try repository.init(gpa, object_format, &pack_file_reader, &index_file_reader); defer repository.deinit(); var diagnostics: git.Diagnostics = .{ .allocator = arena }; - try repository.checkout(out_dir, resource.want_oid, &diagnostics); + try repository.checkout(io, out_dir, resource.want_oid, &diagnostics); if (diagnostics.errors.items.len > 0) { try res.allocErrors(arena, diagnostics.errors.items.len, "unable to unpack packfile"); @@ -1411,7 +1412,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U return res; } -fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void { +fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void { const gpa = f.arena.child_allocator; // Recursive directory copy. var it = try dir.walk(gpa); @@ -1451,7 +1452,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void } } -pub fn renameTmpIntoCache(cache_dir: fs.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { +pub fn renameTmpIntoCache(cache_dir: Io.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { assert(dest_dir_sub_path[1] == fs.path.sep); var handled_missing_dir = false; while (true) { @@ -1660,15 +1661,15 @@ fn dumpHashInfo(all_files: []const *const HashedFile) !void { try w.flush(); } -fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile) void { +fn workerHashFile(dir: Io.Dir, hashed_file: *HashedFile) void { hashed_file.failure = hashFileFallible(dir, hashed_file); } -fn workerDeleteFile(dir: fs.Dir, deleted_file: *DeletedFile) void { +fn workerDeleteFile(dir: Io.Dir, deleted_file: *DeletedFile) void { deleted_file.failure = deleteFileFallible(dir, deleted_file); } -fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void { +fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Error!void { var buf: [8000]u8 = undefined; var hasher = Package.Hash.Algo.init(.{}); hasher.update(hashed_file.normalized_path); @@ -1677,7 +1678,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void switch (hashed_file.kind) { .file => { var file = try dir.openFile(hashed_file.fs_path, .{}); - defer file.close(); + defer file.close(io); // Hard-coded false executable bit: https://github.com/ziglang/zig/issues/17463 hasher.update(&.{ 0, 0 }); var file_header: FileHeader = .{}; @@ -1707,7 +1708,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void hashed_file.size = file_size; } -fn deleteFileFallible(dir: fs.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { +fn deleteFileFallible(dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { try dir.deleteFile(deleted_file.fs_path); } @@ -1724,8 +1725,8 @@ const DeletedFile = struct { failure: Error!void, const Error = - fs.Dir.DeleteFileError || - fs.Dir.DeleteDirError; + Io.Dir.DeleteFileError || + Io.Dir.DeleteDirError; }; const HashedFile = struct { @@ -1741,7 +1742,7 @@ const HashedFile = struct { fs.File.ReadError || fs.File.StatError || fs.File.ChmodError || - fs.Dir.ReadLinkError; + Io.Dir.ReadLinkError; const Kind = enum { file, link }; @@ -2074,7 +2075,7 @@ test "tarball with duplicate paths" { defer tmp.cleanup(); const tarball_name = "duplicate_paths.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2107,7 +2108,7 @@ test "tarball with excluded duplicate paths" { defer tmp.cleanup(); const tarball_name = "duplicate_paths_excluded.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2153,7 +2154,7 @@ test "tarball without root folder" { defer tmp.cleanup(); const tarball_name = "no_root.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2186,7 +2187,7 @@ test "set executable bit based on file content" { defer tmp.cleanup(); const tarball_name = "executables.tar.gz"; - try saveEmbedFile(tarball_name, tmp.dir); + try saveEmbedFile(io, tarball_name, tmp.dir); const tarball_path = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); defer gpa.free(tarball_path); @@ -2210,7 +2211,7 @@ test "set executable bit based on file content" { ); var out = try fb.packageDir(); - defer out.close(); + defer out.close(io); const S = std.posix.S; // expect executable bit not set try std.testing.expect((try out.statFile("file1")).mode & S.IXUSR == 0); @@ -2231,11 +2232,11 @@ test "set executable bit based on file content" { // -rwxrwxr-x 1 17 Apr script_with_shebang_without_exec_bit } -fn saveEmbedFile(comptime tarball_name: []const u8, dir: fs.Dir) !void { +fn saveEmbedFile(io: Io, comptime tarball_name: []const u8, dir: Io.Dir) !void { //const tarball_name = "duplicate_paths_excluded.tar.gz"; const tarball_content = @embedFile("Fetch/testdata/" ++ tarball_name); var tmp_file = try dir.createFile(tarball_name, .{}); - defer tmp_file.close(); + defer tmp_file.close(io); try tmp_file.writeAll(tarball_content); } @@ -2250,7 +2251,7 @@ const TestFetchBuilder = struct { self: *TestFetchBuilder, allocator: std.mem.Allocator, io: Io, - cache_parent_dir: std.fs.Dir, + cache_parent_dir: std.Io.Dir, path_or_url: []const u8, ) !*Fetch { const cache_dir = try cache_parent_dir.makeOpenPath("zig-global-cache", .{}); @@ -2301,14 +2302,15 @@ const TestFetchBuilder = struct { } fn deinit(self: *TestFetchBuilder) void { + const io = self.job_queue.io; self.fetch.deinit(); self.job_queue.deinit(); self.fetch.prog_node.end(); - self.global_cache_directory.handle.close(); + self.global_cache_directory.handle.close(io); self.http_client.deinit(); } - fn packageDir(self: *TestFetchBuilder) !fs.Dir { + fn packageDir(self: *TestFetchBuilder) !Io.Dir { const root = self.fetch.package_root; return try root.root_dir.handle.openDir(root.sub_path, .{ .iterate = true }); } @@ -2316,8 +2318,10 @@ const TestFetchBuilder = struct { // Test helper, asserts thet package dir constains expected_files. // expected_files must be sorted. fn expectPackageFiles(self: *TestFetchBuilder, expected_files: []const []const u8) !void { + const io = self.job_queue.io; + var package_dir = try self.packageDir(); - defer package_dir.close(); + defer package_dir.close(io); var actual_files: std.ArrayList([]u8) = .empty; defer actual_files.deinit(std.testing.allocator); diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index a2ea870c3f..864865bd19 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -213,6 +213,7 @@ pub const Repository = struct { /// Checks out the repository at `commit_oid` to `worktree`. pub fn checkout( repository: *Repository, + io: Io, worktree: std.fs.Dir, commit_oid: Oid, diagnostics: *Diagnostics, @@ -223,12 +224,13 @@ pub const Repository = struct { if (commit_object.type != .commit) return error.NotACommit; break :tree_oid try getCommitTree(repository.odb.format, commit_object.data); }; - try repository.checkoutTree(worktree, tree_oid, "", diagnostics); + try repository.checkoutTree(io, worktree, tree_oid, "", diagnostics); } /// Checks out the tree at `tree_oid` to `worktree`. fn checkoutTree( repository: *Repository, + io: Io, dir: std.fs.Dir, tree_oid: Oid, current_path: []const u8, @@ -253,10 +255,10 @@ pub const Repository = struct { .directory => { try dir.makeDir(entry.name); var subdir = try dir.openDir(entry.name, .{}); - defer subdir.close(); + defer subdir.close(io); const sub_path = try std.fs.path.join(repository.odb.allocator, &.{ current_path, entry.name }); defer repository.odb.allocator.free(sub_path); - try repository.checkoutTree(subdir, entry.oid, sub_path, diagnostics); + try repository.checkoutTree(io, subdir, entry.oid, sub_path, diagnostics); }, .file => { try repository.odb.seekOid(entry.oid); @@ -271,7 +273,7 @@ pub const Repository = struct { } }); continue; }; - defer file.close(); + defer file.close(io); try file.writeAll(file_object.data); }, .symlink => { @@ -1583,14 +1585,14 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u var git_dir = testing.tmpDir(.{}); defer git_dir.cleanup(); var pack_file = try git_dir.dir.createFile("testrepo.pack", .{ .read = true }); - defer pack_file.close(); + defer pack_file.close(io); try pack_file.writeAll(testrepo_pack); var pack_file_buffer: [2000]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true }); - defer index_file.close(); + defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); try indexPack(testing.allocator, format, &pack_file_reader, &index_file_writer); @@ -1621,7 +1623,7 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; defer diagnostics.deinit(); - try repository.checkout(worktree.dir, commit_id, &diagnostics); + try repository.checkout(io, worktree.dir, commit_id, &diagnostics); try testing.expect(diagnostics.errors.items.len == 0); const expected_files: []const []const u8 = &.{ @@ -1713,20 +1715,20 @@ pub fn main() !void { const format = std.meta.stringToEnum(Oid.Format, args[1]) orelse return error.InvalidFormat; var pack_file = try std.fs.cwd().openFile(args[2], .{}); - defer pack_file.close(); + defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); const commit = try Oid.parse(format, args[3]); var worktree = try std.fs.cwd().makeOpenPath(args[4], .{}); - defer worktree.close(); + defer worktree.close(io); var git_dir = try worktree.makeOpenPath(".git", .{}); - defer git_dir.close(); + defer git_dir.close(io); std.debug.print("Starting index...\n", .{}); var index_file = try git_dir.createFile("idx", .{ .read = true }); - defer index_file.close(); + defer index_file.close(io); var index_file_buffer: [4096]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); try indexPack(allocator, format, &pack_file_reader, &index_file_writer); @@ -1738,7 +1740,7 @@ pub fn main() !void { defer repository.deinit(); var diagnostics: Diagnostics = .{ .allocator = allocator }; defer diagnostics.deinit(); - try repository.checkout(worktree, commit, &diagnostics); + try repository.checkout(io, worktree, commit, &diagnostics); for (diagnostics.errors.items) |err| { std.debug.print("Diagnostic: {}\n", .{err}); diff --git a/src/Zcu.zig b/src/Zcu.zig index 137b4d8b59..58d884afe3 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1078,7 +1078,7 @@ pub const File = struct { const dir, const sub_path = file.path.openInfo(zcu.comp.dirs); break :f try dir.openFile(sub_path, .{}); }; - defer f.close(); + defer f.close(io); const stat = f.stat() catch |err| switch (err) { error.Streaming => { @@ -2813,8 +2813,8 @@ pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { pub fn deinit(zcu: *Zcu) void { const comp = zcu.comp; - const gpa = comp.gpa; const io = comp.io; + const gpa = zcu.gpa; { const pt: Zcu.PerThread = .activate(zcu, .main); defer pt.deactivate(); @@ -2835,8 +2835,8 @@ pub fn deinit(zcu: *Zcu) void { } zcu.embed_table.deinit(gpa); - zcu.local_zir_cache.handle.close(); - zcu.global_zir_cache.handle.close(); + zcu.local_zir_cache.handle.close(io); + zcu.global_zir_cache.handle.close(io); for (zcu.failed_analysis.values()) |value| value.destroy(gpa); for (zcu.failed_codegen.values()) |value| value.destroy(gpa); @@ -2900,7 +2900,7 @@ pub fn deinit(zcu: *Zcu) void { if (zcu.resolved_references) |*r| r.deinit(gpa); - if (zcu.comp.debugIncremental()) { + if (comp.debugIncremental()) { zcu.incremental_debug_state.deinit(gpa); } } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 2ad5bac01c..d2ca004058 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -96,7 +96,7 @@ pub fn updateFile( const dir, const sub_path = file.path.openInfo(comp.dirs); break :f try dir.openFile(sub_path, .{}); }; - defer source_file.close(); + defer source_file.close(io); const stat = try source_file.stat(); @@ -215,7 +215,7 @@ pub fn updateFile( else => |e| return e, // Retryable errors are handled at callsite. }; }; - defer cache_file.close(); + defer cache_file.close(io); // Under `--time-report`, ignore cache hits; do the work anyway for those juicy numbers. const ignore_hit = comp.time_report != null; @@ -2468,7 +2468,7 @@ fn updateEmbedFileInner( const dir, const sub_path = ef.path.openInfo(zcu.comp.dirs); break :f try dir.openFile(sub_path, .{}); }; - defer file.close(); + defer file.close(io); const stat: Cache.File.Stat = .fromFs(try file.stat()); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5dc55b74f6..cb4fe0459f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -799,6 +799,7 @@ pub const Object = struct { pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ LinkFailure, OutOfMemory }!void { const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const diags = &comp.link_diags; { @@ -979,7 +980,7 @@ pub const Object = struct { if (options.pre_bc_path) |path| { var file = std.fs.cwd().createFile(path, .{}) catch |err| return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); - defer file.close(); + defer file.close(io); const ptr: [*]const u8 = @ptrCast(bitcode.ptr); file.writeAll(ptr[0..(bitcode.len * 4)]) catch |err| @@ -992,7 +993,7 @@ pub const Object = struct { if (options.post_bc_path) |path| { var file = std.fs.cwd().createFile(path, .{}) catch |err| return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); - defer file.close(); + defer file.close(io); const ptr: [*]const u8 = @ptrCast(bitcode.ptr); file.writeAll(ptr[0..(bitcode.len * 4)]) catch |err| diff --git a/src/fmt.zig b/src/fmt.zig index 80925200d6..907c7885ad 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -187,7 +187,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! // On Windows, statFile does not work for directories error.IsDir => dir: { var dir = try fs.cwd().openDir(file_path, .{}); - defer dir.close(); + defer dir.close(io); break :dir try dir.stat(); }, else => |e| return e, @@ -222,8 +222,10 @@ fn fmtPathDir( parent_dir: fs.Dir, parent_sub_path: []const u8, ) !void { + const io = fmt.io; + var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); - defer dir.close(); + defer dir.close(io); const stat = try dir.stat(); if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; @@ -262,7 +264,7 @@ fn fmtPathFile( const source_file = try dir.openFile(sub_path, .{}); var file_closed = false; - errdefer if (!file_closed) source_file.close(); + errdefer if (!file_closed) source_file.close(io); const stat = try source_file.stat(); @@ -280,7 +282,7 @@ fn fmtPathFile( }; defer gpa.free(source_code); - source_file.close(); + source_file.close(io); file_closed = true; // Add to set after no longer possible to get error.IsDir. diff --git a/src/introspect.zig b/src/introspect.zig index 8467b566c6..9b6797e7d8 100644 --- a/src/introspect.zig +++ b/src/introspect.zig @@ -1,18 +1,21 @@ -const std = @import("std"); const builtin = @import("builtin"); +const build_options = @import("build_options"); + +const std = @import("std"); +const Io = std.Io; const mem = std.mem; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const os = std.os; const fs = std.fs; const Cache = std.Build.Cache; + const Compilation = @import("Compilation.zig"); const Package = @import("Package.zig"); -const build_options = @import("build_options"); /// Returns the sub_path that worked, or `null` if none did. /// The path of the returned Directory is relative to `base`. /// The handle of the returned Directory is open. -fn testZigInstallPrefix(base_dir: fs.Dir) ?Cache.Directory { +fn testZigInstallPrefix(io: Io, base_dir: Io.Dir) ?Cache.Directory { const test_index_file = "std" ++ fs.path.sep_str ++ "std.zig"; zig_dir: { @@ -20,31 +23,31 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Cache.Directory { const lib_zig = "lib" ++ fs.path.sep_str ++ "zig"; var test_zig_dir = base_dir.openDir(lib_zig, .{}) catch break :zig_dir; const file = test_zig_dir.openFile(test_index_file, .{}) catch { - test_zig_dir.close(); + test_zig_dir.close(io); break :zig_dir; }; - file.close(); + file.close(io); return .{ .handle = test_zig_dir, .path = lib_zig }; } // Try lib/std/std.zig var test_zig_dir = base_dir.openDir("lib", .{}) catch return null; const file = test_zig_dir.openFile(test_index_file, .{}) catch { - test_zig_dir.close(); + test_zig_dir.close(io); return null; }; - file.close(); + file.close(io); return .{ .handle = test_zig_dir, .path = "lib" }; } /// Both the directory handle and the path are newly allocated resources which the caller now owns. -pub fn findZigLibDir(gpa: Allocator) !Cache.Directory { +pub fn findZigLibDir(gpa: Allocator, io: Io) !Cache.Directory { const cwd_path = try getResolvedCwd(gpa); defer gpa.free(cwd_path); const self_exe_path = try fs.selfExePathAlloc(gpa); defer gpa.free(self_exe_path); - return findZigLibDirFromSelfExe(gpa, cwd_path, self_exe_path); + return findZigLibDirFromSelfExe(gpa, io, cwd_path, self_exe_path); } /// Like `std.process.getCwdAlloc`, but also resolves the path with `std.fs.path.resolve`. This @@ -73,6 +76,7 @@ pub fn getResolvedCwd(gpa: Allocator) error{ /// Both the directory handle and the path are newly allocated resources which the caller now owns. pub fn findZigLibDirFromSelfExe( allocator: Allocator, + io: Io, /// The return value of `getResolvedCwd`. /// Passed as an argument to avoid pointlessly repeating the call. cwd_path: []const u8, @@ -82,9 +86,9 @@ pub fn findZigLibDirFromSelfExe( var cur_path: []const u8 = self_exe_path; while (fs.path.dirname(cur_path)) |dirname| : (cur_path = dirname) { var base_dir = cwd.openDir(dirname, .{}) catch continue; - defer base_dir.close(); + defer base_dir.close(io); - const sub_directory = testZigInstallPrefix(base_dir) orelse continue; + const sub_directory = testZigInstallPrefix(io, base_dir) orelse continue; const p = try fs.path.join(allocator, &.{ dirname, sub_directory.path.? }); defer allocator.free(p); diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index afeb5b3282..8c5e0afe4b 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -449,7 +449,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); @@ -480,7 +480,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index 64d0fdbeac..bec20ff3d4 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -684,7 +684,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); @@ -715,7 +715,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index b3c018996a..005696e1fc 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -262,7 +262,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); cache.hash.addBytes(build_options.version); cache.hash.addOptionalBytes(comp.dirs.zig_lib.path); @@ -297,7 +297,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { const digest = man.final(); const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); var o_dir = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); + defer o_dir.close(io); const aro = @import("aro"); var diagnostics: aro.Diagnostics = .{ @@ -377,7 +377,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { { const lib_final_file = try o_dir.createFile(final_lib_basename, .{ .truncate = true }); - defer lib_final_file.close(); + defer lib_final_file.close(io); var buffer: [1024]u8 = undefined; var file_writer = lib_final_file.writer(&buffer); try implib.writeCoffArchive(gpa, &file_writer.interface, members); diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index 8d35e3bd71..67e6a2f903 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -390,7 +390,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); - defer cache.manifest_dir.close(); + defer cache.manifest_dir.close(io); var man = cache.obtain(); defer man.deinit(); @@ -421,7 +421,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; - defer o_directory.handle.close(); + defer o_directory.handle.close(io); const abilists_contents = man.files.keys()[abilists_index].contents.?; const metadata = try loadMetaData(gpa, abilists_contents); diff --git a/src/link.zig b/src/link.zig index 6ac96504c7..ef095987c9 100644 --- a/src/link.zig +++ b/src/link.zig @@ -687,7 +687,7 @@ pub const File = struct { .lld => assert(base.file == null), .elf => if (base.file) |f| { dev.check(.elf_linker); - f.close(); + f.close(io); base.file = null; if (base.child_pid) |pid| { @@ -701,7 +701,7 @@ pub const File = struct { }, .macho, .wasm => if (base.file) |f| { dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker }); - f.close(); + f.close(io); base.file = null; if (base.child_pid) |pid| { @@ -866,8 +866,9 @@ pub const File = struct { } pub fn destroy(base: *File) void { + const io = base.comp.io; base.releaseLock(); - if (base.file) |f| f.close(); + if (base.file) |f| f.close(io); switch (base.tag) { .plan9 => unreachable, inline else => |tag| { @@ -1060,9 +1061,10 @@ pub const File = struct { /// Opens a path as an object file and parses it into the linker. fn openLoadObject(base: *File, path: Path) anyerror!void { if (base.tag == .lld) return; + const io = base.comp.io; const diags = &base.comp.link_diags; - const input = try openObjectInput(diags, path); - errdefer input.object.file.close(); + const input = try openObjectInput(io, diags, path); + errdefer input.object.file.close(io); try loadInput(base, input); } @@ -1070,21 +1072,22 @@ pub const File = struct { /// If `query` is non-null, allows GNU ld scripts. fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void { if (base.tag == .lld) return; + const io = base.comp.io; if (opt_query) |query| { - const archive = try openObject(path, query.must_link, query.hidden); - errdefer archive.file.close(); + const archive = try openObject(io, path, query.must_link, query.hidden); + errdefer archive.file.close(io); loadInput(base, .{ .archive = archive }) catch |err| switch (err) { error.BadMagic, error.UnexpectedEndOfFile => { if (base.tag != .elf and base.tag != .elf2) return err; try loadGnuLdScript(base, path, query, archive.file); - archive.file.close(); + archive.file.close(io); return; }, else => return err, }; } else { - const archive = try openObject(path, false, false); - errdefer archive.file.close(); + const archive = try openObject(io, path, false, false); + errdefer archive.file.close(io); try loadInput(base, .{ .archive = archive }); } } @@ -1093,13 +1096,14 @@ pub const File = struct { /// Handles GNU ld scripts. fn openLoadDso(base: *File, path: Path, query: UnresolvedInput.Query) anyerror!void { if (base.tag == .lld) return; - const dso = try openDso(path, query.needed, query.weak, query.reexport); - errdefer dso.file.close(); + const io = base.comp.io; + const dso = try openDso(io, path, query.needed, query.weak, query.reexport); + errdefer dso.file.close(io); loadInput(base, .{ .dso = dso }) catch |err| switch (err) { error.BadMagic, error.UnexpectedEndOfFile => { if (base.tag != .elf and base.tag != .elf2) return err; try loadGnuLdScript(base, path, query, dso.file); - dso.file.close(); + dso.file.close(io); return; }, else => return err, @@ -1735,6 +1739,7 @@ pub fn hashInputs(man: *Cache.Manifest, link_inputs: []const Input) !void { pub fn resolveInputs( gpa: Allocator, arena: Allocator, + io: Io, target: *const std.Target, /// This function mutates this array but does not take ownership. /// Allocated with `gpa`. @@ -1784,6 +1789,7 @@ pub fn resolveInputs( for (lib_directories) |lib_directory| switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1810,6 +1816,7 @@ pub fn resolveInputs( for (lib_directories) |lib_directory| switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1837,6 +1844,7 @@ pub fn resolveInputs( switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1855,6 +1863,7 @@ pub fn resolveInputs( switch (try resolveLibInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &checked_paths, @@ -1886,6 +1895,7 @@ pub fn resolveInputs( if (try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -1903,6 +1913,7 @@ pub fn resolveInputs( switch ((try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -1930,6 +1941,7 @@ pub fn resolveInputs( if (try resolvePathInput( gpa, arena, + io, unresolved_inputs, resolved_inputs, &ld_script_bytes, @@ -1969,6 +1981,7 @@ const fatal = std.process.fatal; fn resolveLibInput( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated via `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated via `gpa`. @@ -1998,7 +2011,7 @@ fn resolveLibInput( error.FileNotFound => break :tbd, else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2013,7 +2026,7 @@ fn resolveLibInput( }), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ + switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ .path = test_path, .query = name_query.query, }, link_mode, color)) { @@ -2036,7 +2049,7 @@ fn resolveLibInput( test_path, @errorName(e), }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2052,7 +2065,7 @@ fn resolveLibInput( error.FileNotFound => break :mingw, else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); } @@ -2087,6 +2100,7 @@ fn finishResolveLibInput( fn resolvePathInput( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated with `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated with `gpa`. @@ -2098,12 +2112,12 @@ fn resolvePathInput( color: std.zig.Color, ) Allocator.Error!?ResolveLibInputResult { switch (Compilation.classifyFileExt(pq.path.sub_path)) { - .static_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color), - .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), + .static_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color), + .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), .object => { var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err| fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) }); - errdefer file.close(); + errdefer file.close(io); try resolved_inputs.append(gpa, .{ .object = .{ .path = pq.path, .file = file, @@ -2115,7 +2129,7 @@ fn resolvePathInput( .res => { var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err| fatal("failed to open windows resource {f}: {s}", .{ pq.path, @errorName(err) }); - errdefer file.close(); + errdefer file.close(io); try resolved_inputs.append(gpa, .{ .res = .{ .path = pq.path, .file = file, @@ -2129,6 +2143,7 @@ fn resolvePathInput( fn resolvePathInputLib( gpa: Allocator, arena: Allocator, + io: Io, /// Allocated with `gpa`. unresolved_inputs: *std.ArrayList(UnresolvedInput), /// Allocated with `gpa`. @@ -2155,7 +2170,7 @@ fn resolvePathInputLib( @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e), }), }; - errdefer file.close(); + errdefer file.close(io); try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{ std.fmt.alt(test_path, .formatEscapeChar), @errorName(err), @@ -2223,7 +2238,7 @@ fn resolvePathInputLib( } }); } } - file.close(); + file.close(io); return .ok; } @@ -2233,13 +2248,13 @@ fn resolvePathInputLib( @tagName(link_mode), test_path, @errorName(e), }), }; - errdefer file.close(); + errdefer file.close(io); return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); } -pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object { +pub fn openObject(io: Io, path: Path, must_link: bool, hidden: bool) !Input.Object { var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - errdefer file.close(); + errdefer file.close(io); return .{ .path = path, .file = file, @@ -2248,9 +2263,9 @@ pub fn openObject(path: Path, must_link: bool, hidden: bool) !Input.Object { }; } -pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso { +pub fn openDso(io: Io, path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso { var file = try path.root_dir.handle.openFile(path.sub_path, .{}); - errdefer file.close(); + errdefer file.close(io); return .{ .path = path, .file = file, @@ -2260,20 +2275,20 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso }; } -pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input { - return .{ .object = openObject(path, false, false) catch |err| { +pub fn openObjectInput(io: Io, diags: *Diags, path: Path) error{LinkFailure}!Input { + return .{ .object = openObject(io, path, false, false) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } -pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input { - return .{ .archive = openObject(path, must_link, hidden) catch |err| { +pub fn openArchiveInput(io: Io, diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input { + return .{ .archive = openObject(io, path, must_link, hidden) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } -pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input { - return .{ .dso = openDso(path, needed, weak, reexport) catch |err| { +pub fn openDsoInput(io: Io, diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input { + return .{ .dso = openDso(io, path, needed, weak, reexport) catch |err| { return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) }); } }; } diff --git a/src/link/C.zig b/src/link/C.zig index ce48e85851..04c92443e5 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -124,6 +124,7 @@ pub fn createEmpty( emit: Path, options: link.File.OpenOptions, ) !*C { + const io = comp.io; const target = &comp.root_mod.resolved_target.result; assert(target.ofmt == .c); const optimize_mode = comp.root_mod.optimize_mode; @@ -139,7 +140,7 @@ pub fn createEmpty( // Truncation is done on `flush`. .truncate = false, }); - errdefer file.close(); + errdefer file.close(io); const c_file = try arena.create(C); @@ -763,6 +764,7 @@ pub fn flushEmitH(zcu: *Zcu) !void { if (true) return; // emit-h is regressed const emit_h = zcu.emit_h orelse return; + const io = zcu.comp.io; // We collect a list of buffers to write, and write them all at once with pwritev 😎 const num_buffers = emit_h.decl_table.count() + 1; @@ -795,7 +797,7 @@ pub fn flushEmitH(zcu: *Zcu) !void { // make it easier on the file system by doing 1 reallocation instead of two. .truncate = false, }); - defer file.close(); + defer file.close(io); try file.setEndPos(file_size); try file.pwritevAll(all_buffers.items, 0); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 69acbe034b..ae7d631f09 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -406,10 +406,12 @@ pub fn open( } pub fn deinit(self: *Elf) void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; for (self.file_handles.items) |fh| { - fh.close(); + fh.close(io); } self.file_handles.deinit(gpa); diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 2345090482..66b032e0a9 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -1628,7 +1628,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err| log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) }); { - defer rsp_file.close(); + defer rsp_file.close(io); var rsp_file_buffer: [1024]u8 = undefined; var rsp_file_writer = rsp_file.writer(&rsp_file_buffer); const rsp_writer = &rsp_file_writer.interface; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 2c4ffd6632..471465cea1 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -267,14 +267,16 @@ pub fn open( } pub fn deinit(self: *MachO) void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; + const io = comp.io; if (self.d_sym) |*d_sym| { d_sym.deinit(); } for (self.file_handles.items) |handle| { - handle.close(); + handle.close(io); } self.file_handles.deinit(gpa); @@ -3257,8 +3259,10 @@ const InitMetadataOptions = struct { }; pub fn closeDebugInfo(self: *MachO) bool { + const comp = self.base.comp; + const io = comp.io; const d_sym = &(self.d_sym orelse return false); - d_sym.file.?.close(); + d_sym.file.?.close(io); d_sym.file = null; return true; } @@ -3269,7 +3273,9 @@ pub fn reopenDebugInfo(self: *MachO) !void { assert(!self.base.comp.config.use_llvm); assert(self.base.comp.config.debug_format == .dwarf); - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const io = comp.io; + const gpa = comp.gpa; const sep = fs.path.sep_str; const d_sym_path = try std.fmt.allocPrint( gpa, @@ -3279,7 +3285,7 @@ pub fn reopenDebugInfo(self: *MachO) !void { defer gpa.free(d_sym_path); var d_sym_bundle = try self.base.emit.root_dir.handle.makeOpenPath(d_sym_path, .{}); - defer d_sym_bundle.close(); + defer d_sym_bundle.close(io); self.d_sym.?.file = try d_sym_bundle.createFile(fs.path.basename(self.base.emit.sub_path), .{ .truncate = false, diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 5d7b9b88c3..8a97f2844f 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -1,5 +1,28 @@ +const DebugSymbols = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const fs = std.fs; +const log = std.log.scoped(.link_dsym); +const macho = std.macho; +const makeStaticString = MachO.makeStaticString; +const math = std.math; +const mem = std.mem; +const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; + +const link = @import("../../link.zig"); +const MachO = @import("../MachO.zig"); +const StringTable = @import("../StringTable.zig"); +const Type = @import("../../Type.zig"); +const trace = @import("../../tracy.zig").trace; +const load_commands = @import("load_commands.zig"); +const padToIdeal = MachO.padToIdeal; + +io: Io, allocator: Allocator, -file: ?fs.File, +file: ?Io.File, symtab_cmd: macho.symtab_command = .{}, uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, @@ -208,7 +231,8 @@ pub fn flush(self: *DebugSymbols, macho_file: *MachO) !void { pub fn deinit(self: *DebugSymbols) void { const gpa = self.allocator; - if (self.file) |file| file.close(); + const io = self.io; + if (self.file) |file| file.close(io); self.segments.deinit(gpa); self.sections.deinit(gpa); self.relocs.deinit(gpa); @@ -443,25 +467,3 @@ pub fn getSection(self: DebugSymbols, sect: u8) macho.section_64 { assert(sect < self.sections.items.len); return self.sections.items[sect]; } - -const DebugSymbols = @This(); - -const std = @import("std"); -const build_options = @import("build_options"); -const assert = std.debug.assert; -const fs = std.fs; -const link = @import("../../link.zig"); -const load_commands = @import("load_commands.zig"); -const log = std.log.scoped(.link_dsym); -const macho = std.macho; -const makeStaticString = MachO.makeStaticString; -const math = std.math; -const mem = std.mem; -const padToIdeal = MachO.padToIdeal; -const trace = @import("../../tracy.zig").trace; -const Writer = std.Io.Writer; - -const Allocator = mem.Allocator; -const MachO = @import("../MachO.zig"); -const StringTable = @import("../StringTable.zig"); -const Type = @import("../../Type.zig"); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 92307ec40c..160e6cdcc6 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3032,7 +3032,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { const io = wasm.base.comp.io; const gc_sections = wasm.base.gc_sections; - defer obj.file.close(); + defer obj.file.close(io); var file_reader = obj.file.reader(io, &.{}); @@ -3060,7 +3060,7 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void { const io = wasm.base.comp.io; const gc_sections = wasm.base.gc_sections; - defer obj.file.close(); + defer obj.file.close(io); var file_reader = obj.file.reader(io, &.{}); diff --git a/src/main.zig b/src/main.zig index a897f2a847..3ca64881f8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -328,21 +328,21 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { .prepend_global_cache_path = true, }); } else if (mem.eql(u8, cmd, "init")) { - return cmdInit(gpa, arena, cmd_args); + return cmdInit(gpa, arena, io, cmd_args); } else if (mem.eql(u8, cmd, "targets")) { dev.check(.targets_command); const host = std.zig.resolveTargetQueryOrFatal(io, .{}); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); - try @import("print_targets.zig").cmdTargets(arena, cmd_args, &stdout_writer.interface, &host); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); + try @import("print_targets.zig").cmdTargets(arena, io, cmd_args, &stdout_writer.interface, &host); return stdout_writer.interface.flush(); } else if (mem.eql(u8, cmd, "version")) { dev.check(.version_command); - try fs.File.stdout().writeAll(build_options.version ++ "\n"); + try Io.File.stdout().writeAll(build_options.version ++ "\n"); return; } else if (mem.eql(u8, cmd, "env")) { dev.check(.env_command); const host = std.zig.resolveTargetQueryOrFatal(io, .{}); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); try @import("print_env.zig").cmdEnv( arena, &stdout_writer.interface, @@ -358,10 +358,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { }); } else if (mem.eql(u8, cmd, "zen")) { dev.check(.zen_command); - return fs.File.stdout().writeAll(info_zen); + return Io.File.stdout().writeAll(info_zen); } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) { dev.check(.help_command); - return fs.File.stdout().writeAll(usage); + return Io.File.stdout().writeAll(usage); } else if (mem.eql(u8, cmd, "ast-check")) { return cmdAstCheck(arena, io, cmd_args); } else if (mem.eql(u8, cmd, "detect-cpu")) { @@ -698,7 +698,7 @@ const Emit = union(enum) { yes: []const u8, const OutputToCacheReason = enum { listen, @"zig run", @"zig test" }; - fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit { + fn resolve(io: Io, emit: Emit, default_basename: []const u8, output_to_cache: ?OutputToCacheReason) Compilation.CreateOptions.Emit { return switch (emit) { .no => .no, .yes_default_path => if (output_to_cache != null) .yes_cache else .{ .yes_path = default_basename }, @@ -716,7 +716,7 @@ const Emit = union(enum) { var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; - dir.close(); + dir.close(io); } break :e .{ .yes_path = path }; }, @@ -1034,7 +1034,7 @@ fn buildOutputType( }; } else if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_build_generic); + try Io.File.stdout().writeAll(usage_build_generic); return cleanExit(); } else if (mem.eql(u8, arg, "--")) { if (arg_mode == .run) { @@ -2834,9 +2834,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-V")) { warn("ignoring request for supported emulations: unimplemented", .{}); } else if (mem.eql(u8, arg, "-v")) { - try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); + try Io.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); } else if (mem.eql(u8, arg, "--version")) { - try fs.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); + try Io.File.stdout().writeAll("zig ld " ++ build_options.version ++ "\n"); process.exit(0); } else { fatal("unsupported linker arg: {s}", .{arg}); @@ -3251,8 +3251,8 @@ fn buildOutputType( } } - var cleanup_emit_bin_dir: ?fs.Dir = null; - defer if (cleanup_emit_bin_dir) |*dir| dir.close(); + var cleanup_emit_bin_dir: ?Io.Dir = null; + defer if (cleanup_emit_bin_dir) |*dir| dir.close(io); // For `zig run` and `zig test`, we don't want to put the binary in the cwd by default. So, if // the binary is requested with no explicit path (as is the default), we emit to the cache. @@ -3307,7 +3307,7 @@ fn buildOutputType( var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; - dir.close(); + dir.close(io); } break :emit .{ .yes_path = path }; }, @@ -3390,7 +3390,7 @@ fn buildOutputType( // will be a hash of its contents — so multiple invocations of // `zig cc -` will result in the same temp file name. var f = try dirs.local_cache.handle.createFile(dump_path, .{}); - defer f.close(); + defer f.close(io); // Re-using the hasher from Cache, since the functional requirements // for the hashing algorithm here and in the cache are the same. @@ -3399,7 +3399,7 @@ fn buildOutputType( var file_writer = f.writer(&.{}); var buffer: [1000]u8 = undefined; var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer); - var stdin_reader = fs.File.stdin().readerStreaming(io, &.{}); + var stdin_reader = Io.File.stdin().readerStreaming(io, &.{}); _ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) { error.WriteFailed => fatal("failed to write {s}: {t}", .{ dump_path, file_writer.err.? }), else => fatal("failed to pipe stdin to {s}: {t}", .{ dump_path, err }), @@ -3630,13 +3630,13 @@ fn buildOutputType( if (show_builtin) { const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config); const source = try builtin_opts.generate(arena); - return fs.File.stdout().writeAll(source); + return Io.File.stdout().writeAll(source); } switch (listen) { .none => {}, .stdio => { - var stdin_reader = fs.File.stdin().reader(io, &stdin_buffer); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); try serve( comp, &stdin_reader.interface, @@ -4034,6 +4034,7 @@ fn createModule( link.resolveInputs( gpa, arena, + io, target, &unresolved_link_inputs, &create_module.link_inputs, @@ -4689,8 +4690,8 @@ fn cmdTranslateC( @errorName(err), }); }; - defer zig_file.close(); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + defer zig_file.close(io); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); var file_reader = zig_file.reader(io, &.{}); _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited); try stdout_writer.interface.flush(); @@ -4728,7 +4729,7 @@ const usage_init = \\ ; -fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { +fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !void { dev.check(.init_command); var template: enum { example, minimal } = .example; @@ -4740,7 +4741,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { if (mem.eql(u8, arg, "-m") or mem.eql(u8, arg, "--minimal")) { template = .minimal; } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_init); + try Io.File.stdout().writeAll(usage_init); return cleanExit(); } else { fatal("unrecognized parameter: '{s}'", .{arg}); @@ -4759,7 +4760,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { switch (template) { .example => { - var templates = findTemplates(gpa, arena); + var templates = findTemplates(gpa, arena, io); defer templates.deinit(); const s = fs.path.sep_str; @@ -4789,7 +4790,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { return cleanExit(); }, .minimal => { - writeSimpleTemplateFile(Package.Manifest.basename, + writeSimpleTemplateFile(io, Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "0.0.1", @@ -4806,7 +4807,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { else => fatal("failed to create '{s}': {s}", .{ Package.Manifest.basename, @errorName(err) }), error.PathAlreadyExists => fatal("refusing to overwrite '{s}'", .{Package.Manifest.basename}), }; - writeSimpleTemplateFile(Package.build_zig_basename, + writeSimpleTemplateFile(io, Package.build_zig_basename, \\const std = @import("std"); \\ \\pub fn build(b: *std.Build) void {{ @@ -5203,8 +5204,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) .parent = root_mod, }); - var cleanup_build_dir: ?fs.Dir = null; - defer if (cleanup_build_dir) |*dir| dir.close(); + var cleanup_build_dir: ?Io.Dir = null; + defer if (cleanup_build_dir) |*dir| dir.close(io); if (dev.env.supports(.fetch_command)) { const fetch_prog_node = root_prog_node.start("Fetch Packages", 0); @@ -5296,6 +5297,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) try job_queue.createDependenciesSource(&source_buf); const deps_mod = try createDependenciesModule( arena, + io, source_buf.items, root_mod, dirs, @@ -5357,6 +5359,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) } } else try createEmptyDependenciesModule( arena, + io, root_mod, dirs, config, @@ -5623,7 +5626,7 @@ fn jitCmd( defer comp.destroy(); if (options.server) { - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); var server: std.zig.Server = .{ .out = &stdout_writer.interface, .in = undefined, // won't be receiving messages @@ -6156,7 +6159,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_ast_check); + try Io.File.stdout().writeAll(usage_ast_check); return cleanExit(); } else if (mem.eql(u8, arg, "-t")) { want_output_text = true; @@ -6187,9 +6190,9 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { break :file fs.cwd().openFile(p, .{}) catch |err| { fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; - } else fs.File.stdin(); - defer if (zig_source_path != null) f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + } else Io.File.stdin(); + defer if (zig_source_path != null) f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| { fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; @@ -6207,7 +6210,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const tree = try Ast.parse(arena, source, mode); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); const stdout_bw = &stdout_writer.interface; switch (mode) { .zig => { @@ -6330,7 +6333,7 @@ fn cmdDetectCpu(io: Io, args: []const []const u8) !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(detect_cpu_usage); + try Io.File.stdout().writeAll(detect_cpu_usage); return cleanExit(); } else if (mem.eql(u8, arg, "--llvm")) { use_llvm = true; @@ -6422,7 +6425,7 @@ fn detectNativeCpuWithLLVM( } fn printCpu(cpu: std.Target.Cpu) !void { - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); const stdout_bw = &stdout_writer.interface; if (cpu.model.llvm_name) |llvm_name| { @@ -6471,7 +6474,7 @@ fn cmdDumpLlvmInts( const dl = tm.createTargetDataLayout(); const context = llvm.Context.create(); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); const stdout_bw = &stdout_writer.interface; for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| { const int_type = context.intType(bits); @@ -6494,10 +6497,10 @@ fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void { var f = fs.cwd().openFile(cache_file, .{}) catch |err| { fatal("unable to open zir cache file for dumping '{s}': {s}", .{ cache_file, @errorName(err) }); }; - defer f.close(); + defer f.close(io); const zir = try Zcu.loadZirCache(arena, io, f); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); const stdout_bw = &stdout_writer.interface; { const instruction_bytes = zir.instructions.len * @@ -6540,16 +6543,16 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { const old_source = source: { var f = fs.cwd().openFile(old_source_path, .{}) catch |err| fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); - defer f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + defer f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); }; const new_source = source: { var f = fs.cwd().openFile(new_source_path, .{}) catch |err| fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); - defer f.close(); - var file_reader: fs.File.Reader = f.reader(io, &stdin_buffer); + defer f.close(io); + var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); }; @@ -6581,7 +6584,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map); - var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); const stdout_bw = &stdout_writer.interface; { try stdout_bw.print("Instruction mappings:\n", .{}); @@ -6912,7 +6915,7 @@ fn cmdFetch( const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_fetch); + try Io.File.stdout().writeAll(usage_fetch); return cleanExit(); } else if (mem.eql(u8, arg, "--global-cache-dir")) { if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); @@ -6958,7 +6961,7 @@ fn cmdFetch( .path = p, }; }; - defer global_cache_directory.handle.close(); + defer global_cache_directory.handle.close(io); var job_queue: Package.Fetch.JobQueue = .{ .io = io, @@ -7021,7 +7024,7 @@ fn cmdFetch( const name = switch (save) { .no => { - var stdout = fs.File.stdout().writerStreaming(&stdout_buffer); + var stdout = Io.File.stdout().writerStreaming(&stdout_buffer); try stdout.interface.print("{s}\n", .{package_hash_slice}); try stdout.interface.flush(); return cleanExit(); @@ -7043,7 +7046,7 @@ fn cmdFetch( // The name to use in case the manifest file needs to be created now. const init_root_name = fs.path.basename(build_root.directory.path orelse cwd_path); - var manifest, var ast = try loadManifest(gpa, arena, .{ + var manifest, var ast = try loadManifest(gpa, arena, io, .{ .root_name = try sanitizeExampleName(arena, init_root_name), .dir = build_root.directory.handle, .color = color, @@ -7168,6 +7171,7 @@ fn cmdFetch( fn createEmptyDependenciesModule( arena: Allocator, + io: Io, main_mod: *Package.Module, dirs: Compilation.Directories, global_options: Compilation.Config, @@ -7176,6 +7180,7 @@ fn createEmptyDependenciesModule( try Package.Fetch.JobQueue.createEmptyDependenciesSource(&source); _ = try createDependenciesModule( arena, + io, source.items, main_mod, dirs, @@ -7187,6 +7192,7 @@ fn createEmptyDependenciesModule( /// build runner to obtain via `@import("@dependencies")`. fn createDependenciesModule( arena: Allocator, + io: Io, source: []const u8, main_mod: *Package.Module, dirs: Compilation.Directories, @@ -7198,7 +7204,7 @@ fn createDependenciesModule( const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); { var tmp_dir = try dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}); - defer tmp_dir.close(); + defer tmp_dir.close(io); try tmp_dir.writeFile(.{ .sub_path = basename, .data = source }); } @@ -7232,10 +7238,10 @@ fn createDependenciesModule( const BuildRoot = struct { directory: Cache.Directory, build_zig_basename: []const u8, - cleanup_build_dir: ?fs.Dir, + cleanup_build_dir: ?Io.Dir, - fn deinit(br: *BuildRoot) void { - if (br.cleanup_build_dir) |*dir| dir.close(); + fn deinit(br: *BuildRoot, io: Io) void { + if (br.cleanup_build_dir) |*dir| dir.close(io); br.* = undefined; } }; @@ -7304,13 +7310,14 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { const LoadManifestOptions = struct { root_name: []const u8, - dir: fs.Dir, + dir: Io.Dir, color: Color, }; fn loadManifest( gpa: Allocator, arena: Allocator, + io: Io, options: LoadManifestOptions, ) !struct { Package.Manifest, Ast } { const manifest_bytes = while (true) { @@ -7322,7 +7329,7 @@ fn loadManifest( 0, ) catch |err| switch (err) { error.FileNotFound => { - writeSimpleTemplateFile(Package.Manifest.basename, + writeSimpleTemplateFile(io, Package.Manifest.basename, \\.{{ \\ .name = .{s}, \\ .version = "{s}", @@ -7374,12 +7381,12 @@ fn loadManifest( const Templates = struct { zig_lib_directory: Cache.Directory, - dir: fs.Dir, + dir: Io.Dir, buffer: std.array_list.Managed(u8), - fn deinit(templates: *Templates) void { - templates.zig_lib_directory.handle.close(); - templates.dir.close(); + fn deinit(templates: *Templates, io: Io) void { + templates.zig_lib_directory.handle.close(io); + templates.dir.close(io); templates.buffer.deinit(); templates.* = undefined; } @@ -7387,7 +7394,7 @@ const Templates = struct { fn write( templates: *Templates, arena: Allocator, - out_dir: fs.Dir, + out_dir: Io.Dir, root_name: []const u8, template_path: []const u8, fingerprint: Package.Fingerprint, @@ -7435,23 +7442,23 @@ const Templates = struct { }); } }; -fn writeSimpleTemplateFile(file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { +fn writeSimpleTemplateFile(io: Io, file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { const f = try fs.cwd().createFile(file_name, .{ .exclusive = true }); - defer f.close(); + defer f.close(io); var buf: [4096]u8 = undefined; var fw = f.writer(&buf); try fw.interface.print(fmt, args); try fw.interface.flush(); } -fn findTemplates(gpa: Allocator, arena: Allocator) Templates { +fn findTemplates(gpa: Allocator, arena: Allocator, io: Io) Templates { const cwd_path = introspect.getResolvedCwd(arena) catch |err| { fatal("unable to get cwd: {s}", .{@errorName(err)}); }; const self_exe_path = fs.selfExePathAlloc(arena) catch |err| { fatal("unable to find self exe path: {s}", .{@errorName(err)}); }; - var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, cwd_path, self_exe_path) catch |err| { + var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, io, cwd_path, self_exe_path) catch |err| { fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); }; diff --git a/src/print_targets.zig b/src/print_targets.zig index d9118b901b..2f80187de1 100644 --- a/src/print_targets.zig +++ b/src/print_targets.zig @@ -12,6 +12,7 @@ const introspect = @import("introspect.zig"); pub fn cmdTargets( allocator: Allocator, + io: Io, args: []const []const u8, out: *std.Io.Writer, native_target: *const Target, @@ -20,7 +21,7 @@ pub fn cmdTargets( var zig_lib_directory = introspect.findZigLibDir(allocator) catch |err| { fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)}); }; - defer zig_lib_directory.handle.close(); + defer zig_lib_directory.handle.close(io); defer allocator.free(zig_lib_directory.path.?); const abilists_contents = zig_lib_directory.handle.readFileAlloc( -- cgit v1.2.3 From 3204fb756980c19b7a95534acdd7a1bba837fbc3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 6 Dec 2025 17:23:07 -0800 Subject: update all occurrences of std.fs.File to std.Io.File --- lib/compiler/aro/aro/Compilation.zig | 4 +- lib/compiler/aro/aro/Driver.zig | 15 +++---- lib/compiler/aro/aro/Preprocessor.zig | 3 +- lib/compiler/aro/backend/Assembly.zig | 3 +- lib/compiler/aro/main.zig | 3 +- lib/compiler/build_runner.zig | 6 +-- lib/compiler/libc.zig | 3 +- lib/compiler/objcopy.zig | 13 +++--- lib/compiler/reduce.zig | 3 +- lib/compiler/resinator/cli.zig | 3 +- lib/compiler/resinator/errors.zig | 8 ++-- lib/compiler/resinator/main.zig | 10 ++--- lib/compiler/resinator/utils.zig | 4 +- lib/compiler/test_runner.zig | 10 ++--- lib/compiler/translate-c/main.zig | 13 +++--- lib/std/Build.zig | 6 +-- lib/std/Build/Step.zig | 2 +- lib/std/Build/Step/ObjCopy.zig | 2 +- lib/std/Build/Step/Run.zig | 21 +++++----- lib/std/Io.zig | 2 +- lib/std/Io/Writer.zig | 9 ++-- lib/std/Io/test.zig | 2 +- lib/std/Io/tty.zig | 7 ++-- lib/std/Progress.zig | 18 ++++---- lib/std/Random/benchmark.zig | 6 ++- lib/std/Thread.zig | 4 +- lib/std/crypto/Certificate/Bundle.zig | 8 ++-- lib/std/crypto/Certificate/Bundle/macos.zig | 2 +- lib/std/crypto/benchmark.zig | 8 ++-- lib/std/debug.zig | 6 +-- lib/std/debug/ElfFile.zig | 4 +- lib/std/debug/Info.zig | 2 +- lib/std/debug/Pdb.zig | 2 +- lib/std/debug/SelfInfo/Windows.zig | 2 +- lib/std/debug/simple_panic.zig | 2 +- lib/std/dynamic_library.zig | 2 +- lib/std/fs/test.zig | 8 ++-- lib/std/hash/benchmark.zig | 5 ++- lib/std/http.zig | 2 +- lib/std/pdb.zig | 2 +- lib/std/posix/test.zig | 18 ++++---- lib/std/process/Child.zig | 4 +- lib/std/unicode/throughput_test.zig | 6 +-- lib/std/zig/Zir.zig | 8 ++-- lib/std/zig/Zoir.zig | 15 +++---- lib/std/zig/llvm/Builder.zig | 4 +- lib/std/zig/perf_test.zig | 3 +- lib/std/zip.zig | 5 ++- src/Compilation.zig | 4 +- src/Package/Fetch.zig | 16 +++---- src/Package/Fetch/git.zig | 22 +++++----- src/Zcu.zig | 8 ++-- src/Zcu/PerThread.zig | 6 +-- src/fmt.zig | 16 +++---- src/link.zig | 20 ++++----- src/link/Dwarf.zig | 53 ++++++++++++----------- src/link/Elf.zig | 5 ++- src/link/Elf/Object.zig | 65 +++++++++++++++-------------- src/link/Elf/SharedObject.zig | 37 ++++++++-------- src/link/Elf/file.zig | 35 ++++++++-------- src/link/Elf2.zig | 46 ++++++++++---------- src/link/MachO.zig | 23 +++++----- src/link/MachO/CodeSignature.zig | 8 ++-- src/link/MachO/fat.zig | 12 +++--- src/link/MachO/file.zig | 3 +- src/link/MachO/hasher.zig | 22 +++++----- src/link/MachO/uuid.zig | 19 ++++----- src/link/MappedFile.zig | 25 ++++++----- src/link/Wasm.zig | 5 ++- src/link/tapi.zig | 10 ++--- 70 files changed, 399 insertions(+), 359 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 9fb8123146..06b27c33bb 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -1646,7 +1646,7 @@ fn addSourceFromPathExtra(comp: *Compilation, path: []const u8, kind: Source.Kin return comp.addSourceFromFile(file, path, kind); } -pub fn addSourceFromFile(comp: *Compilation, file: std.fs.File, path: []const u8, kind: Source.Kind) !Source { +pub fn addSourceFromFile(comp: *Compilation, file: Io.File, path: []const u8, kind: Source.Kind) !Source { const contents = try comp.getFileContents(file, .unlimited); errdefer comp.gpa.free(contents); return comp.addSourceFromOwnedBuffer(path, contents, kind); @@ -1980,7 +1980,7 @@ fn getPathContents(comp: *Compilation, path: []const u8, limit: Io.Limit) ![]u8 return comp.getFileContents(file, limit); } -fn getFileContents(comp: *Compilation, file: std.fs.File, limit: Io.Limit) ![]u8 { +fn getFileContents(comp: *Compilation, file: Io.File, limit: Io.Limit) ![]u8 { var file_buf: [4096]u8 = undefined; var file_reader = file.reader(comp.io, &file_buf); diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index 888ade2be4..f933e3ce52 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const process = std.process; @@ -1061,7 +1062,7 @@ pub fn printDiagnosticsStats(d: *Driver) void { } } -pub fn detectConfig(d: *Driver, file: std.fs.File) std.Io.tty.Config { +pub fn detectConfig(d: *Driver, file: Io.File) std.Io.tty.Config { if (d.diagnostics.color == false) return .no_color; const force_color = d.diagnostics.color == true; @@ -1109,7 +1110,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_ defer macro_buf.deinit(d.comp.gpa); var stdout_buf: [256]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); if (parseArgs(d, &stdout.interface, ¯o_buf, args) catch |er| switch (er) { error.WriteFailed => return d.fatal("failed to write to stdout: {s}", .{errorDescription(er)}), error.OutOfMemory => return error.OutOfMemory, @@ -1329,7 +1330,7 @@ fn processSource( d.comp.cwd.createFile(path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, errorDescription(er) }) else - std.fs.File.stdout(); + Io.File.stdout(); defer if (dep_file_name != null) file.close(io); var file_writer = file.writer(&writer_buf); @@ -1354,7 +1355,7 @@ fn processSource( d.comp.cwd.createFile(some, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) }) else - std.fs.File.stdout(); + Io.File.stdout(); defer if (d.output_name != null) file.close(io); var file_writer = file.writer(&writer_buf); @@ -1369,7 +1370,7 @@ fn processSource( defer tree.deinit(); if (d.verbose_ast) { - var stdout = std.fs.File.stdout().writer(&writer_buf); + var stdout = Io.File.stdout().writer(&writer_buf); tree.dump(d.detectConfig(stdout.file), &stdout.interface) catch {}; } @@ -1433,7 +1434,7 @@ fn processSource( defer ir.deinit(gpa); if (d.verbose_ir) { - var stdout = std.fs.File.stdout().writer(&writer_buf); + var stdout = Io.File.stdout().writer(&writer_buf); ir.dump(gpa, d.detectConfig(stdout.file), &stdout.interface) catch {}; } @@ -1499,7 +1500,7 @@ pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compil if (d.verbose_linker_args) { var stdout_buf: [4096]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); dumpLinkerArgs(&stdout.interface, argv.items) catch { return d.fatal("unable to dump linker args: {s}", .{errorDescription(stdout.err.?)}); }; diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig index 6bd1206aff..d47727cbf0 100644 --- a/lib/compiler/aro/aro/Preprocessor.zig +++ b/lib/compiler/aro/aro/Preprocessor.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const assert = std.debug.assert; @@ -1068,7 +1069,7 @@ fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); var stderr_buf: [4096]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(&stderr_buf); const w = &stderr.interface; w.print("{s}:{d}:{d}: ", .{ source.path, line_col.line_no, line_col.col }) catch return; diff --git a/lib/compiler/aro/backend/Assembly.zig b/lib/compiler/aro/backend/Assembly.zig index d0d14bdd77..80143bf97f 100644 --- a/lib/compiler/aro/backend/Assembly.zig +++ b/lib/compiler/aro/backend/Assembly.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; data: []const u8, @@ -11,7 +12,7 @@ pub fn deinit(self: *const Assembly, gpa: Allocator) void { gpa.free(self.text); } -pub fn writeToFile(self: Assembly, file: std.fs.File) !void { +pub fn writeToFile(self: Assembly, file: Io.File) !void { var file_writer = file.writer(&.{}); var buffers = [_][]const u8{ self.data, self.text }; diff --git a/lib/compiler/aro/main.zig b/lib/compiler/aro/main.zig index d3655e43da..66c8add4a3 100644 --- a/lib/compiler/aro/main.zig +++ b/lib/compiler/aro/main.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const Allocator = mem.Allocator; const mem = std.mem; const process = std.process; @@ -50,7 +51,7 @@ pub fn main() u8 { defer gpa.free(aro_name); var stderr_buf: [1024]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(&stderr_buf); var diagnostics: Diagnostics = .{ .output = .{ .to_writer = .{ .color = .detect(stderr.file), diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 2c8d71e3e2..6e0e2d8eca 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -7,7 +7,7 @@ const assert = std.debug.assert; const fmt = std.fmt; const mem = std.mem; const process = std.process; -const File = std.fs.File; +const File = std.Io.File; const Step = std.Build.Step; const Watch = std.Build.Watch; const WebServer = std.Build.WebServer; @@ -1845,9 +1845,9 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { } var stdio_buffer_allocation: [256]u8 = undefined; -var stdout_writer_allocation: std.fs.File.Writer = undefined; +var stdout_writer_allocation: Io.File.Writer = undefined; fn initStdoutWriter() *Writer { - stdout_writer_allocation = std.fs.File.stdout().writerStreaming(&stdio_buffer_allocation); + stdout_writer_allocation = Io.File.stdout().writerStreaming(&stdio_buffer_allocation); return &stdout_writer_allocation.interface; } diff --git a/lib/compiler/libc.zig b/lib/compiler/libc.zig index a18a7a0e06..142b87062e 100644 --- a/lib/compiler/libc.zig +++ b/lib/compiler/libc.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const LibCInstallation = std.zig.LibCInstallation; @@ -39,7 +40,7 @@ pub fn main() !void { var input_file: ?[]const u8 = null; var target_arch_os_abi: []const u8 = "native"; var print_includes: bool = false; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; { var i: usize = 2; diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 1608c121b1..c360ea8df0 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -1,12 +1,13 @@ const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; const mem = std.mem; const fs = std.fs; const elf = std.elf; const Allocator = std.mem.Allocator; -const File = std.fs.File; +const File = std.Io.File; const assert = std.debug.assert; - const fatal = std.process.fatal; const Server = std.zig.Server; @@ -56,7 +57,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void fatal("unexpected positional argument: '{s}'", .{arg}); } } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - return std.fs.File.stdout().writeAll(usage); + return Io.File.stdout().writeAll(usage); } else if (mem.eql(u8, arg, "-O") or mem.eql(u8, arg, "--output-target")) { i += 1; if (i >= args.len) fatal("expected another argument after '{s}'", .{arg}); @@ -177,7 +178,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void } }; - const mode = if (out_fmt != .elf or only_keep_debug) fs.File.default_mode else stat.mode; + const mode = if (out_fmt != .elf or only_keep_debug) Io.File.default_mode else stat.mode; var output_file = try fs.cwd().createFile(output, .{ .mode = mode }); defer output_file.close(io); @@ -221,8 +222,8 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void try out.end(); if (listen) { - var stdin_reader = fs.File.stdin().reader(io, &stdin_buffer); - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); var server = try Server.init(.{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index 28305e801b..bbd3d172b4 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -68,7 +69,7 @@ pub fn main() !void { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - const stdout = std.fs.File.stdout(); + const stdout = Io.File.stdout(); try stdout.writeAll(usage); return std.process.cleanExit(); } else if (mem.eql(u8, arg, "--")) { diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index ffaa62e7ca..17da5c7b75 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const code_pages = @import("code_pages.zig"); const SupportedCodePage = code_pages.SupportedCodePage; const lang = @import("lang.zig"); @@ -169,7 +170,7 @@ pub const Options = struct { coff_options: cvtres.CoffOptions = .{}, pub const IoSource = union(enum) { - stdio: std.fs.File, + stdio: Io.File, filename: []const u8, }; pub const AutoIncludes = enum { any, msvc, gnu, none }; diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 8509aa610f..61fd00e683 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -169,9 +169,9 @@ pub const ErrorDetails = struct { filename_string_index: FilenameStringIndex, pub const FilenameStringIndex = std.meta.Int(.unsigned, 32 - @bitSizeOf(FileOpenErrorEnum)); - pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError || std.fs.File.StatError); + pub const FileOpenErrorEnum = std.meta.FieldEnum(Io.File.OpenError || Io.File.StatError); - pub fn enumFromError(err: (std.fs.File.OpenError || std.fs.File.StatError)) FileOpenErrorEnum { + pub fn enumFromError(err: (Io.File.OpenError || Io.File.StatError)) FileOpenErrorEnum { return switch (err) { inline else => |e| @field(ErrorDetails.FileOpenError.FileOpenErrorEnum, @errorName(e)), }; @@ -1094,8 +1094,8 @@ const CorrespondingLines = struct { last_byte: u8 = 0, at_eof: bool = false, span: SourceMappings.CorrespondingSpan, - file: std.fs.File, - file_reader: std.fs.File.Reader, + file: Io.File, + file_reader: Io.File.Reader, code_page: SupportedCodePage, pub fn init( diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index 42308a8987..e171d8199c 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -45,7 +45,7 @@ pub fn main() !void { } var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; var error_handler: ErrorHandler = switch (zig_integration) { true => .{ @@ -447,8 +447,8 @@ const IoStream = struct { } pub const Source = union(enum) { - file: std.fs.File, - stdio: std.fs.File, + file: Io.File, + stdio: Io.File, memory: std.ArrayList(u8), /// The source has been closed and any usage of the Source in this state is illegal (except deinit). closed: void, @@ -500,10 +500,10 @@ const IoStream = struct { } pub const Writer = union(enum) { - file: std.fs.File.Writer, + file: Io.File.Writer, allocating: std.Io.Writer.Allocating, - pub const Error = Allocator.Error || std.fs.File.WriteError; + pub const Error = Allocator.Error || Io.File.WriteError; pub fn interface(this: *@This()) *std.Io.Writer { return switch (this.*) { diff --git a/lib/compiler/resinator/utils.zig b/lib/compiler/resinator/utils.zig index f8080539cb..e8565f3af9 100644 --- a/lib/compiler/resinator/utils.zig +++ b/lib/compiler/resinator/utils.zig @@ -32,8 +32,8 @@ pub fn openFileNotDir( cwd: std.fs.Dir, io: Io, path: []const u8, - flags: std.fs.File.OpenFlags, -) (std.fs.File.OpenError || std.fs.File.StatError)!std.fs.File { + flags: Io.File.OpenFlags, +) (Io.File.OpenError || Io.File.StatError)!Io.File { const file = try cwd.openFile(io, path, flags); errdefer file.close(io); // https://github.com/ziglang/zig/issues/5732 diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 72ed3e7677..07a6724ec0 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -74,8 +74,8 @@ pub fn main() void { fn mainServer() !void { @disableInstrumentation(); - var stdin_reader = std.fs.File.stdin().readerStreaming(runner_threaded_io.io(), &stdin_buffer); - var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); + var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io.io(), &stdin_buffer); + var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); var server = try std.zig.Server.init(.{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, @@ -228,7 +228,7 @@ fn mainTerminal() void { .root_name = "Test", .estimated_total_items = test_fn_list.len, }); - const have_tty = std.fs.File.stderr().isTty(); + const have_tty = Io.File.stderr().isTty(); var leaks: usize = 0; for (test_fn_list, 0..) |test_fn, i| { @@ -318,7 +318,7 @@ pub fn log( /// work-in-progress backends can handle it. pub fn mainSimple() anyerror!void { @disableInstrumentation(); - // is the backend capable of calling `std.fs.File.writeAll`? + // is the backend capable of calling `Io.File.writeAll`? const enable_write = switch (builtin.zig_backend) { .stage2_aarch64, .stage2_riscv64 => true, else => false, @@ -334,7 +334,7 @@ pub fn mainSimple() anyerror!void { var failed: u64 = 0; // we don't want to bring in File and Writer if the backend doesn't support it - const stdout = if (enable_write) std.fs.File.stdout() else {}; + const stdout = if (enable_write) Io.File.stdout() else {}; for (builtin.test_functions) |test_fn| { if (enable_write) { diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index 0c72298b30..830c70e424 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const mem = std.mem; const process = std.process; @@ -34,7 +35,7 @@ pub fn main() u8 { } var stderr_buf: [1024]u8 = undefined; - var stderr = std.fs.File.stderr().writer(&stderr_buf); + var stderr = Io.File.stderr().writer(&stderr_buf); var diagnostics: aro.Diagnostics = switch (zig_integration) { false => .{ .output = .{ .to_writer = .{ .color = .detect(stderr.file), @@ -99,7 +100,7 @@ fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostic "translation failure", ); var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); var server: std.zig.Server = .{ .out = &stdout_writer.interface, .in = undefined, @@ -129,13 +130,13 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration args[i] = arg; if (mem.eql(u8, arg, "--help")) { var stdout_buf: [512]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); try stdout.interface.print(usage, .{args[0]}); try stdout.interface.flush(); return; } else if (mem.eql(u8, arg, "--version")) { var stdout_buf: [512]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buf); + var stdout = Io.File.stdout().writer(&stdout_buf); // TODO add version try stdout.interface.writeAll("0.0.0-dev\n"); try stdout.interface.flush(); @@ -228,7 +229,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration d.comp.cwd.createFile(path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, aro.Driver.errorDescription(er) }) else - std.fs.File.stdout(); + Io.File.stdout(); defer if (dep_file_name != null) file.close(io); var file_writer = file.writer(&out_buf); @@ -246,7 +247,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration var close_out_file = false; var out_file_path: []const u8 = ""; - var out_file: std.fs.File = .stdout(); + var out_file: Io.File = .stdout(); defer if (close_out_file) out_file.close(io); if (d.output_name) |path| blk: { diff --git a/lib/std/Build.zig b/lib/std/Build.zig index fcd94ce134..2755b895c2 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1,3 +1,4 @@ +const Build = @This(); const builtin = @import("builtin"); const std = @import("std.zig"); @@ -9,13 +10,12 @@ const panic = std.debug.panic; const assert = debug.assert; const log = std.log; const StringHashMap = std.StringHashMap; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const Target = std.Target; const process = std.process; const EnvMap = std.process.EnvMap; -const File = fs.File; +const File = std.Io.File; const Sha256 = std.crypto.hash.sha2.Sha256; -const Build = @This(); const ArrayList = std.ArrayList; pub const Cache = @import("Build/Cache.zig"); diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index acde47071d..2b1e6d8ace 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -667,7 +667,7 @@ fn clearZigProcess(s: *Step, gpa: Allocator) void { } } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig index b5f058ddfc..4aa1c0a9dc 100644 --- a/lib/std/Build/Step/ObjCopy.zig +++ b/lib/std/Build/Step/ObjCopy.zig @@ -3,7 +3,7 @@ const ObjCopy = @This(); const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; -const File = std.fs.File; +const File = std.Io.File; const InstallDir = std.Build.InstallDir; const Step = std.Build.Step; const elf = std.elf; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index e66e30cc79..1df6f42a35 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1,15 +1,16 @@ -const std = @import("std"); +const Run = @This(); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const Build = std.Build; -const Step = Build.Step; +const Step = std.Build.Step; const fs = std.fs; const mem = std.mem; const process = std.process; -const EnvMap = process.EnvMap; +const EnvMap = std.process.EnvMap; const assert = std.debug.assert; -const Path = Build.Cache.Path; - -const Run = @This(); +const Path = std.Build.Cache.Path; pub const base_id: Step.Id = .run; @@ -2095,7 +2096,7 @@ pub const CachedTestMetadata = struct { } }; -fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { +fn requestNextTest(in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { while (metadata.next_index < metadata.names.len) { const i = metadata.next_index; metadata.next_index += 1; @@ -2114,7 +2115,7 @@ fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Pr } } -fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, @@ -2125,7 +2126,7 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { }; } -fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void { +fn sendRunTestMessage(file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 4, @@ -2140,7 +2141,7 @@ fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: } fn sendRunFuzzTestMessage( - file: std.fs.File, + file: Io.File, index: u32, kind: std.Build.abi.fuzz.LimitKind, amount_or_instance: u64, diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 0727e3efd3..f783718cef 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -528,7 +528,7 @@ pub fn Poller(comptime StreamEnum: type) type { /// Given an enum, returns a struct with fields of that enum, each field /// representing an I/O stream for polling. pub fn PollFiles(comptime StreamEnum: type) type { - return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(std.fs.File), &@splat(.{})); + return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(Io.File), &@splat(.{})); } test { diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 5601293cfb..3f25bc6a26 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -1,7 +1,8 @@ +const Writer = @This(); + const builtin = @import("builtin"); const native_endian = builtin.target.cpu.arch.endian(); -const Writer = @This(); const std = @import("../std.zig"); const assert = std.debug.assert; const Limit = std.Io.Limit; @@ -2837,7 +2838,7 @@ test "discarding sendFile" { const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [256]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, &r_buffer); try file_writer.interface.writeByte('h'); try file_writer.interface.flush(); @@ -2859,7 +2860,7 @@ test "allocating sendFile" { const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [2]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, &r_buffer); try file_writer.interface.writeAll("abcd"); try file_writer.interface.flush(); @@ -2883,7 +2884,7 @@ test sendFileReading { const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [2]u8 = undefined; - var file_writer: std.fs.File.Writer = .init(file, &r_buffer); + var file_writer: File.Writer = .init(file, &r_buffer); try file_writer.interface.writeAll("abcd"); try file_writer.interface.flush(); diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index 9ea2d48ee5..b922acc333 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -10,7 +10,7 @@ const expectError = std.testing.expectError; const DefaultPrng = std.Random.DefaultPrng; const mem = std.mem; const fs = std.fs; -const File = std.fs.File; +const File = std.Io.File; const assert = std.debug.assert; const tmpDir = std.testing.tmpDir; diff --git a/lib/std/Io/tty.zig b/lib/std/Io/tty.zig index 08e0bd71f0..d1f8b576c2 100644 --- a/lib/std/Io/tty.zig +++ b/lib/std/Io/tty.zig @@ -1,9 +1,10 @@ -const std = @import("std"); const builtin = @import("builtin"); -const File = std.fs.File; +const native_os = builtin.os.tag; + +const std = @import("std"); +const File = std.Io.File; const process = std.process; const windows = std.os.windows; -const native_os = builtin.os.tag; pub const Color = enum { black, diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 467d4754ff..d8b22c2db0 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -1,19 +1,21 @@ //! This API is non-allocating, non-fallible, thread-safe, and lock-free. +const Progress = @This(); -const std = @import("std"); const builtin = @import("builtin"); +const is_big_endian = builtin.cpu.arch.endian() == .big; +const is_windows = builtin.os.tag == .windows; + +const std = @import("std"); +const Io = std.Io; const windows = std.os.windows; const testing = std.testing; const assert = std.debug.assert; -const Progress = @This(); const posix = std.posix; -const is_big_endian = builtin.cpu.arch.endian() == .big; -const is_windows = builtin.os.tag == .windows; const Writer = std.Io.Writer; /// `null` if the current node (and its children) should /// not print on update() -terminal: std.fs.File, +terminal: Io.File, terminal_mode: TerminalMode, @@ -472,7 +474,7 @@ pub fn start(options: Options) Node { if (options.disable_printing) { return Node.none; } - const stderr: std.fs.File = .stderr(); + const stderr: Io.File = .stderr(); global_progress.terminal = stderr; if (stderr.enableAnsiEscapeCodes()) |_| { global_progress.terminal_mode = .ansi_escape_codes; @@ -633,8 +635,8 @@ pub fn unlockStdErr() void { /// Protected by `stderr_mutex`. const stderr_writer: *Writer = &stderr_file_writer.interface; /// Protected by `stderr_mutex`. -var stderr_file_writer: std.fs.File.Writer = .{ - .interface = std.fs.File.Writer.initInterface(&.{}), +var stderr_file_writer: Io.File.Writer = .{ + .interface = Io.File.Writer.initInterface(&.{}), .file = if (is_windows) undefined else .stderr(), .mode = .streaming, }; diff --git a/lib/std/Random/benchmark.zig b/lib/std/Random/benchmark.zig index 57dc69051e..97afe23b95 100644 --- a/lib/std/Random/benchmark.zig +++ b/lib/std/Random/benchmark.zig @@ -1,7 +1,9 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const time = std.time; const Timer = time.Timer; const Random = std.Random; @@ -123,7 +125,7 @@ fn mode(comptime x: comptime_int) comptime_int { pub fn main() !void { var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; var buffer: [1024]u8 = undefined; diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 9f532c3bec..8d8e5979df 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -175,7 +175,7 @@ pub const SetNameError = error{ Unsupported, Unexpected, InvalidWtf8, -} || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || posix.WriteError || Io.File.OpenError || std.fmt.BufPrintError; pub fn setName(self: Thread, io: Io, name: []const u8) SetNameError!void { if (name.len > max_name_len) return error.NameTooLong; @@ -293,7 +293,7 @@ pub fn setName(self: Thread, io: Io, name: []const u8) SetNameError!void { pub const GetNameError = error{ Unsupported, Unexpected, -} || posix.PrctlError || posix.ReadError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || posix.ReadError || Io.File.OpenError || std.fmt.BufPrintError; /// 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. diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig index 9541e01db5..1d21918b5c 100644 --- a/lib/std/crypto/Certificate/Bundle.zig +++ b/lib/std/crypto/Certificate/Bundle.zig @@ -171,7 +171,7 @@ fn rescanWindows(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanW cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len); } -pub const AddCertsFromDirPathError = fs.File.OpenError || AddCertsFromDirError; +pub const AddCertsFromDirPathError = Io.File.OpenError || AddCertsFromDirError; pub fn addCertsFromDirPath( cb: *Bundle, @@ -212,7 +212,7 @@ pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, i } } -pub const AddCertsFromFilePathError = fs.File.OpenError || AddCertsFromFileError || Io.Clock.Error; +pub const AddCertsFromFilePathError = Io.File.OpenError || AddCertsFromFileError || Io.Clock.Error; pub fn addCertsFromFilePathAbsolute( cb: *Bundle, @@ -242,8 +242,8 @@ pub fn addCertsFromFilePath( } pub const AddCertsFromFileError = Allocator.Error || - fs.File.GetSeekPosError || - fs.File.ReadError || + Io.File.GetSeekPosError || + Io.File.ReadError || ParseCertError || std.base64.Error || error{ CertificateAuthorityBundleTooBig, MissingEndCertificateMarker, Streaming }; diff --git a/lib/std/crypto/Certificate/Bundle/macos.zig b/lib/std/crypto/Certificate/Bundle/macos.zig index d32f1be8e0..473505ac51 100644 --- a/lib/std/crypto/Certificate/Bundle/macos.zig +++ b/lib/std/crypto/Certificate/Bundle/macos.zig @@ -6,7 +6,7 @@ const mem = std.mem; const Allocator = std.mem.Allocator; const Bundle = @import("../Bundle.zig"); -pub const RescanMacError = Allocator.Error || fs.File.OpenError || fs.File.ReadError || fs.File.SeekError || Bundle.ParseCertError || error{EndOfStream}; +pub const RescanMacError = Allocator.Error || Io.File.OpenError || Io.File.ReadError || Io.File.SeekError || Bundle.ParseCertError || error{EndOfStream}; pub fn rescanMac(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanMacError!void { cb.bytes.clearRetainingCapacity(); diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index 54024f070e..1b71110be5 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -1,10 +1,12 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const mem = std.mem; const time = std.time; -const Timer = time.Timer; +const Timer = std.time.Timer; const crypto = std.crypto; const KiB = 1024; @@ -504,7 +506,7 @@ fn mode(comptime x: comptime_int) comptime_int { pub fn main() !void { // Size of buffer is about size of printed message. var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 0cb96ed593..97741ecb40 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -8,7 +8,7 @@ const posix = std.posix; const fs = std.fs; const testing = std.testing; const Allocator = mem.Allocator; -const File = std.fs.File; +const File = std.Io.File; const windows = std.os.windows; const builtin = @import("builtin"); @@ -575,7 +575,7 @@ pub fn defaultPanic( // A panic happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {}; + File.stderr().writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. } @@ -1596,7 +1596,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex // A segfault happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {}; + File.stderr().writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. } diff --git a/lib/std/debug/ElfFile.zig b/lib/std/debug/ElfFile.zig index 92bcca1bcf..5dbae18130 100644 --- a/lib/std/debug/ElfFile.zig +++ b/lib/std/debug/ElfFile.zig @@ -123,7 +123,7 @@ pub const LoadError = error{ pub fn load( gpa: Allocator, - elf_file: std.fs.File, + elf_file: Io.File, opt_build_id: ?[]const u8, di_search_paths: *const DebugInfoSearchPaths, ) LoadError!ElfFile { @@ -423,7 +423,7 @@ const LoadInnerResult = struct { }; fn loadInner( arena: Allocator, - elf_file: std.fs.File, + elf_file: Io.File, opt_crc: ?u32, ) (LoadError || error{ CrcMismatch, Streaming, Canceled })!LoadInnerResult { const mapped_mem: []align(std.heap.page_size_min) const u8 = mapped: { diff --git a/lib/std/debug/Info.zig b/lib/std/debug/Info.zig index 9268ca0247..da7656e626 100644 --- a/lib/std/debug/Info.zig +++ b/lib/std/debug/Info.zig @@ -27,7 +27,7 @@ coverage: *Coverage, pub const LoadError = error{ MissingDebugInfo, UnsupportedDebugInfo, -} || std.fs.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError; +} || Io.File.OpenError || ElfFile.LoadError || MachOFile.Error || std.debug.Dwarf.ScanError; pub fn load( gpa: Allocator, diff --git a/lib/std/debug/Pdb.zig b/lib/std/debug/Pdb.zig index c10b361f72..3ecfd1b363 100644 --- a/lib/std/debug/Pdb.zig +++ b/lib/std/debug/Pdb.zig @@ -1,5 +1,5 @@ const std = @import("../std.zig"); -const File = std.fs.File; +const File = std.Io.File; const Allocator = std.mem.Allocator; const pdb = std.pdb; const assert = std.debug.assert; diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index 557f3901eb..3af7223293 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -204,7 +204,7 @@ const Module = struct { coff_section_headers: []coff.SectionHeader, const MappedFile = struct { - file: fs.File, + file: Io.File, section_handle: windows.HANDLE, section_view: []const u8, fn deinit(mf: *const MappedFile, io: Io) void { diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig index 45e97777c4..f6ff77e04f 100644 --- a/lib/std/debug/simple_panic.zig +++ b/lib/std/debug/simple_panic.zig @@ -15,7 +15,7 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn { @branchHint(.cold); _ = ra; std.debug.lockStdErr(); - const stderr: std.fs.File = .stderr(); + const stderr: std.Io.File = .stderr(); stderr.writeAll(msg) catch {}; @trap(); } diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index c91056b0ab..ca36d5cbb9 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -225,7 +225,7 @@ pub const ElfDynLib = struct { const fd = try resolveFromName(io, path); defer posix.close(fd); - const file: std.fs.File = .{ .handle = fd }; + const file: Io.File = .{ .handle = fd }; const stat = try file.stat(); const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 15b8e9b558..f770ddd30e 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -12,7 +12,7 @@ const posix = std.posix; const ArenaAllocator = std.heap.ArenaAllocator; const Dir = std.fs.Dir; -const File = std.fs.File; +const File = std.Io.File; const tmpDir = testing.tmpDir; const SymLinkFlags = std.fs.Dir.SymLinkFlags; @@ -2231,7 +2231,7 @@ test "read file non vectored" { const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); defer file.close(io); { - var file_writer: std.fs.File.Writer = .init(file, &.{}); + var file_writer: File.Writer = .init(file, &.{}); try file_writer.interface.writeAll(contents); try file_writer.interface.flush(); } @@ -2263,7 +2263,7 @@ test "seek keeping partial buffer" { const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); defer file.close(io); { - var file_writer: std.fs.File.Writer = .init(file, &.{}); + var file_writer: File.Writer = .init(file, &.{}); try file_writer.interface.writeAll(contents); try file_writer.interface.flush(); } @@ -2325,7 +2325,7 @@ test "seekTo flushes buffered data" { defer file.close(io); { var buf: [16]u8 = undefined; - var file_writer = std.fs.File.writer(file, &buf); + var file_writer = File.writer(file, &buf); try file_writer.interface.writeAll(contents); try file_writer.seekTo(8); diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index a21d6e9ada..6744b87fac 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -1,7 +1,8 @@ // zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig +const builtin = @import("builtin"); const std = @import("std"); -const builtin = @import("builtin"); +const Io = std.Io; const time = std.time; const Timer = time.Timer; const hash = std.hash; @@ -354,7 +355,7 @@ fn mode(comptime x: comptime_int) comptime_int { pub fn main() !void { var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; var buffer: [1024]u8 = undefined; diff --git a/lib/std/http.zig b/lib/std/http.zig index a768372ecc..291e22539b 100644 --- a/lib/std/http.zig +++ b/lib/std/http.zig @@ -2,7 +2,7 @@ const builtin = @import("builtin"); const std = @import("std.zig"); const assert = std.debug.assert; const Writer = std.Io.Writer; -const File = std.fs.File; +const File = std.Io.File; pub const Client = @import("http/Client.zig"); pub const Server = @import("http/Server.zig"); diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig index 36b0e04e5c..7e479de8d4 100644 --- a/lib/std/pdb.zig +++ b/lib/std/pdb.zig @@ -12,7 +12,7 @@ const math = std.math; const mem = std.mem; const coff = std.coff; const fs = std.fs; -const File = std.fs.File; +const File = std.Io.File; const debug = std.debug; const ArrayList = std.ArrayList; diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 8889e50ea3..82fa2c41d1 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -1,20 +1,20 @@ +const builtin = @import("builtin"); +const native_os = builtin.target.os.tag; + const std = @import("../std.zig"); +const Io = std.Io; const posix = std.posix; const testing = std.testing; -const expect = testing.expect; -const expectEqual = testing.expectEqual; -const expectError = testing.expectError; +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; +const expectError = std.testing.expectError; const fs = std.fs; const mem = std.mem; const elf = std.elf; const linux = std.os.linux; - const a = std.testing.allocator; - -const builtin = @import("builtin"); const AtomicRmwOp = std.builtin.AtomicRmwOp; const AtomicOrder = std.builtin.AtomicOrder; -const native_os = builtin.target.os.tag; const tmpDir = std.testing.tmpDir; const AT = posix.AT; @@ -663,14 +663,14 @@ test "dup & dup2" { var file = try tmp.dir.createFile("os_dup_test", .{}); defer file.close(io); - var duped = std.fs.File{ .handle = try posix.dup(file.handle) }; + var duped = Io.File{ .handle = try posix.dup(file.handle) }; defer duped.close(io); try duped.writeAll("dup"); // Tests aren't run in parallel so using the next fd shouldn't be an issue. const new_fd = duped.handle + 1; try posix.dup2(file.handle, new_fd); - var dup2ed = std.fs.File{ .handle = new_fd }; + var dup2ed = Io.File{ .handle = new_fd }; defer dup2ed.close(io); try dup2ed.writeAll("dup2"); } diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index be3026ff10..87d2fe3ba9 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -8,7 +8,7 @@ const Io = std.Io; const unicode = std.unicode; const fs = std.fs; const process = std.process; -const File = std.fs.File; +const File = std.Io.File; const windows = std.os.windows; const linux = std.os.linux; const posix = std.posix; @@ -1055,7 +1055,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { fn writeIntFd(fd: i32, value: ErrInt) !void { var buffer: [8]u8 = undefined; - var fw: std.fs.File.Writer = .initStreaming(.{ .handle = fd }, &buffer); + var fw: File.Writer = .initStreaming(.{ .handle = fd }, &buffer); fw.interface.writeInt(u64, value, .little) catch unreachable; fw.interface.flush() catch return error.SystemResources; } diff --git a/lib/std/unicode/throughput_test.zig b/lib/std/unicode/throughput_test.zig index fd3f46ec58..c02f550a4a 100644 --- a/lib/std/unicode/throughput_test.zig +++ b/lib/std/unicode/throughput_test.zig @@ -1,8 +1,8 @@ const std = @import("std"); +const Io = std.Io; const time = std.time; const unicode = std.unicode; - -const Timer = time.Timer; +const Timer = std.time.Timer; const N = 1_000_000; @@ -41,7 +41,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount { pub fn main() !void { // Size of buffer is about size of printed message. var stdout_buffer: [0x100]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; try stdout.print("short ASCII strings\n", .{}); diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 09c785613f..37ce7b4cfa 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -11,9 +11,11 @@ //! * In the future, possibly inline assembly, which needs to get parsed and //! handled by the codegen backend, and errors reported there. However for now, //! inline assembly is not an exception. +const Zir = @This(); +const builtin = @import("builtin"); const std = @import("std"); -const builtin = @import("builtin"); +const Io = std.Io; const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -21,8 +23,6 @@ const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Ast = std.zig.Ast; -const Zir = @This(); - instructions: std.MultiArrayList(Inst).Slice, /// In order to store references to strings in fewer bytes, we copy all /// string bytes into here. String bytes can be null. It is up to whomever @@ -45,7 +45,7 @@ pub const Header = extern struct { /// it's essentially free to have a zero field here and makes the warning go away, /// making it more likely that following Valgrind warnings will be taken seriously. unused: u32 = 0, - stat_inode: std.fs.File.INode, + stat_inode: Io.File.INode, stat_size: u64, stat_mtime: i128, }; diff --git a/lib/std/zig/Zoir.zig b/lib/std/zig/Zoir.zig index 08a7fc9639..d82b8f1861 100644 --- a/lib/std/zig/Zoir.zig +++ b/lib/std/zig/Zoir.zig @@ -1,6 +1,13 @@ //! Zig Object Intermediate Representation. //! Simplified AST for the ZON (Zig Object Notation) format. //! `ZonGen` converts `Ast` to `Zoir`. +const Zoir = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Ast = std.zig.Ast; nodes: std.MultiArrayList(Node.Repr).Slice, extra: []u32, @@ -25,7 +32,7 @@ pub const Header = extern struct { /// making it more likely that following Valgrind warnings will be taken seriously. unused: u64 = 0, - stat_inode: std.fs.File.INode, + stat_inode: Io.File.INode, stat_size: u64, stat_mtime: i128, @@ -254,9 +261,3 @@ pub const CompileError = extern struct { assert(std.meta.hasUniqueRepresentation(Note)); } }; - -const std = @import("std"); -const assert = std.debug.assert; -const Allocator = std.mem.Allocator; -const Ast = std.zig.Ast; -const Zoir = @This(); diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 9a52ae2c81..9ca0124f4f 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -9578,7 +9578,7 @@ pub fn asmValue( pub fn dump(b: *Builder) void { var buffer: [4000]u8 = undefined; - const stderr: std.fs.File = .stderr(); + const stderr: Io.File = .stderr(); b.printToFile(stderr, &buffer) catch {}; } @@ -9589,7 +9589,7 @@ pub fn printToFilePath(b: *Builder, io: Io, dir: std.fs.Dir, path: []const u8) ! try b.printToFile(io, file, &buffer); } -pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void { +pub fn printToFile(b: *Builder, file: Io.File, buffer: []u8) !void { var fw = file.writer(buffer); try print(b, &fw.interface); try fw.interface.flush(); diff --git a/lib/std/zig/perf_test.zig b/lib/std/zig/perf_test.zig index 1566a15d2d..da3dd42f15 100644 --- a/lib/std/zig/perf_test.zig +++ b/lib/std/zig/perf_test.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Tokenizer = std.zig.Tokenizer; const fmtIntSizeBin = std.fmt.fmtIntSizeBin; @@ -22,7 +23,7 @@ pub fn main() !void { const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float))); var stdout_buffer: [1024]u8 = undefined; - var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); const stdout = &stdout_writer.interface; try stdout.print("parsing speed: {Bi:.2}/s, {Bi:.2} used \n", .{ bytes_per_sec, memory_used }); try stdout.flush(); diff --git a/lib/std/zip.zig b/lib/std/zip.zig index c2dbaf5b81..9588651e7f 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -4,9 +4,10 @@ //! Note that this file uses the abbreviation "cd" for "central directory" const builtin = @import("builtin"); -const std = @import("std"); -const File = std.fs.File; const is_le = builtin.target.cpu.arch.endian() == .little; + +const std = @import("std"); +const File = std.Io.File; const Writer = std.Io.Writer; const Reader = std.Io.Reader; const flate = std.compress.flate; diff --git a/src/Compilation.zig b/src/Compilation.zig index df64dee19f..582c9dff3c 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5325,7 +5325,7 @@ fn docsCopyModule( comp: *Compilation, module: *Package.Module, name: []const u8, - tar_file_writer: *fs.File.Writer, + tar_file_writer: *Io.File.Writer, ) !void { const io = comp.io; const root = module.root; @@ -5361,7 +5361,7 @@ fn docsCopyModule( }; defer file.close(io); const stat = try file.stat(); - var file_reader: fs.File.Reader = .initSize(file.adaptToNewApi(), io, &buffer, stat.size); + var file_reader: Io.File.Reader = .initSize(file.adaptToNewApi(), io, &buffer, stat.size); archiver.writeFileTimestamp(entry.path, &file_reader, stat.mtime) catch |err| { return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive {f}{s}: {t}", .{ diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 58f970abe5..988282097b 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -882,7 +882,7 @@ fn fail(f: *Fetch, msg_tok: std.zig.Ast.TokenIndex, msg_str: u32) RunError { } const Resource = union(enum) { - file: fs.File.Reader, + file: Io.File.Reader, http_request: HttpRequest, git: Git, dir: Io.Dir, @@ -1653,7 +1653,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute fn dumpHashInfo(all_files: []const *const HashedFile) !void { var stdout_buffer: [1024]u8 = undefined; - var stdout_writer: fs.File.Writer = .initStreaming(.stdout(), &stdout_buffer); + var stdout_writer: Io.File.Writer = .initStreaming(.stdout(), &stdout_buffer); const w = &stdout_writer.interface; for (all_files) |hashed_file| { try w.print("{t}: {x}: {s}\n", .{ hashed_file.kind, &hashed_file.hash, hashed_file.normalized_path }); @@ -1712,11 +1712,11 @@ fn deleteFileFallible(dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error try dir.deleteFile(deleted_file.fs_path); } -fn setExecutable(file: fs.File) !void { +fn setExecutable(file: Io.File) !void { if (!std.fs.has_executable_bit) return; const S = std.posix.S; - const mode = fs.File.default_mode | S.IXUSR | S.IXGRP | S.IXOTH; + const mode = Io.File.default_mode | S.IXUSR | S.IXGRP | S.IXOTH; try file.chmod(mode); } @@ -1738,10 +1738,10 @@ const HashedFile = struct { size: u64, const Error = - fs.File.OpenError || - fs.File.ReadError || - fs.File.StatError || - fs.File.ChmodError || + Io.File.OpenError || + Io.File.ReadError || + Io.File.StatError || + Io.File.ChmodError || Io.Dir.ReadLinkError; const Kind = enum { file, link }; diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index 864865bd19..0fca3a0ee3 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -198,8 +198,8 @@ pub const Repository = struct { repo: *Repository, allocator: Allocator, format: Oid.Format, - pack_file: *std.fs.File.Reader, - index_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, + index_file: *Io.File.Reader, ) !void { repo.* = .{ .odb = undefined }; try repo.odb.init(allocator, format, pack_file, index_file); @@ -372,9 +372,9 @@ pub const Repository = struct { /// [pack-format](https://git-scm.com/docs/pack-format). const Odb = struct { format: Oid.Format, - pack_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, index_header: IndexHeader, - index_file: *std.fs.File.Reader, + index_file: *Io.File.Reader, cache: ObjectCache = .{}, allocator: Allocator, @@ -383,8 +383,8 @@ const Odb = struct { odb: *Odb, allocator: Allocator, format: Oid.Format, - pack_file: *std.fs.File.Reader, - index_file: *std.fs.File.Reader, + pack_file: *Io.File.Reader, + index_file: *Io.File.Reader, ) !void { try pack_file.seekTo(0); try index_file.seekTo(0); @@ -1272,8 +1272,8 @@ const IndexEntry = struct { pub fn indexPack( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, - index_writer: *std.fs.File.Writer, + pack: *Io.File.Reader, + index_writer: *Io.File.Writer, ) !void { try pack.seekTo(0); @@ -1372,7 +1372,7 @@ pub fn indexPack( fn indexPackFirstPass( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), pending_deltas: *std.ArrayList(IndexEntry), ) !Oid { @@ -1425,7 +1425,7 @@ fn indexPackFirstPass( fn indexPackHashDelta( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, delta: IndexEntry, index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry), cache: *ObjectCache, @@ -1477,7 +1477,7 @@ fn indexPackHashDelta( fn resolveDeltaChain( allocator: Allocator, format: Oid.Format, - pack: *std.fs.File.Reader, + pack: *Io.File.Reader, base_object: Object, delta_offsets: []const u64, cache: *ObjectCache, diff --git a/src/Zcu.zig b/src/Zcu.zig index 58d884afe3..cd4a8c7783 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1200,7 +1200,7 @@ pub const EmbedFile = struct { /// `.none` means the file was not loaded, so `stat` is undefined. val: InternPool.Index, /// If this is `null` and `val` is `.none`, the file has never been loaded. - err: ?(std.fs.File.OpenError || std.fs.File.StatError || std.fs.File.ReadError || error{UnexpectedEof}), + err: ?(Io.File.OpenError || Io.File.StatError || Io.File.ReadError || error{UnexpectedEof}), stat: Cache.File.Stat, pub const Index = enum(u32) { @@ -2927,7 +2927,7 @@ comptime { } } -pub fn loadZirCache(gpa: Allocator, io: Io, cache_file: std.fs.File) !Zir { +pub fn loadZirCache(gpa: Allocator, io: Io, cache_file: Io.File) !Zir { var buffer: [2000]u8 = undefined; var file_reader = cache_file.reader(io, &buffer); return result: { @@ -2986,7 +2986,7 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *Io.Reader return zir; } -pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.Stat, zir: Zir) (std.fs.File.WriteError || Allocator.Error)!void { +pub fn saveZirCache(gpa: Allocator, cache_file: Io.File, stat: Io.File.Stat, zir: Zir) (Io.File.WriteError || Allocator.Error)!void { const safety_buffer = if (data_has_safety_tag) try gpa.alloc([8]u8, zir.instructions.len) else @@ -3026,7 +3026,7 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S }; } -pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void { +pub fn saveZoirCache(cache_file: Io.File, stat: Io.File.Stat, zoir: Zoir) Io.File.WriteError!void { const header: Zoir.Header = .{ .nodes_len = @intCast(zoir.nodes.len), .extra_len = @intCast(zoir.extra.len), diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index d2ca004058..55d6a3861f 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -118,7 +118,7 @@ pub fn updateFile( const zir_dir = cache_directory.handle; // Determine whether we need to reload the file from disk and redo parsing and AstGen. - var lock: std.fs.File.Lock = switch (file.status) { + var lock: Io.File.Lock = switch (file.status) { .never_loaded, .retryable_failure => lock: { // First, load the cached ZIR code, if any. log.debug("AstGen checking cache: {f} (local={}, digest={s})", .{ @@ -346,8 +346,8 @@ pub fn updateFile( fn loadZirZoirCache( zcu: *Zcu, - cache_file: std.fs.File, - stat: std.fs.File.Stat, + cache_file: Io.File, + stat: Io.File.Stat, file: *Zcu.File, comptime mode: Ast.Mode, ) !enum { success, invalid, truncated, stale } { diff --git a/src/fmt.zig b/src/fmt.zig index 907c7885ad..7bdc24054e 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -37,9 +37,9 @@ const Fmt = struct { arena: Allocator, io: Io, out_buffer: std.Io.Writer.Allocating, - stdout_writer: *fs.File.Writer, + stdout_writer: *Io.File.Writer, - const SeenMap = std.AutoHashMap(fs.File.INode, void); + const SeenMap = std.AutoHashMap(Io.File.INode, void); }; pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !void { @@ -59,7 +59,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - try fs.File.stdout().writeAll(usage_fmt); + try Io.File.stdout().writeAll(usage_fmt); return process.cleanExit(); } else if (mem.eql(u8, arg, "--color")) { if (i + 1 >= args.len) { @@ -99,9 +99,9 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! fatal("cannot use --stdin with positional arguments", .{}); } - const stdin: fs.File = .stdin(); + const stdin: Io.File = .stdin(); var stdio_buffer: [1024]u8 = undefined; - var file_reader: fs.File.Reader = stdin.reader(io, &stdio_buffer); + var file_reader: Io.File.Reader = stdin.reader(io, &stdio_buffer); const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| { fatal("unable to read stdin: {}", .{err}); }; @@ -154,7 +154,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! process.exit(code); } - return fs.File.stdout().writeAll(formatted); + return Io.File.stdout().writeAll(formatted); } if (input_files.items.len == 0) { @@ -162,7 +162,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } var stdout_buffer: [4096]u8 = undefined; - var stdout_writer = fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = Io.File.stdout().writer(&stdout_buffer); var fmt: Fmt = .{ .gpa = gpa, @@ -272,7 +272,7 @@ fn fmtPathFile( return error.IsDir; var read_buffer: [1024]u8 = undefined; - var file_reader: fs.File.Reader = source_file.reader(io, &read_buffer); + var file_reader: Io.File.Reader = source_file.reader(io, &read_buffer); file_reader.size = stat.size; const gpa = fmt.gpa; diff --git a/src/link.zig b/src/link.zig index ef095987c9..d5daf6fca7 100644 --- a/src/link.zig +++ b/src/link.zig @@ -393,7 +393,7 @@ pub const File = struct { comp: *Compilation, emit: Path, - file: ?fs.File, + file: ?Io.File, /// When using the LLVM backend, the emitted object is written to a file with this name. This /// object file then becomes a normal link input to LLD or a self-hosted linker. /// @@ -1110,7 +1110,7 @@ pub const File = struct { }; } - fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void { + fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: Io.File) anyerror!void { const comp = base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; @@ -1238,7 +1238,7 @@ pub const File = struct { pub fn determineMode( output_mode: std.builtin.OutputMode, link_mode: std.builtin.LinkMode, - ) fs.File.Mode { + ) Io.File.Mode { // On common systems with a 0o022 umask, 0o777 will still result in a file created // with 0o755 permissions, but it works appropriately if the system is configured // more leniently. As another data point, C's fopen seems to open files with the @@ -1247,10 +1247,10 @@ pub const File = struct { switch (output_mode) { .Lib => return switch (link_mode) { .dynamic => executable_mode, - .static => fs.File.default_mode, + .static => Io.File.default_mode, }, .Exe => return executable_mode, - .Obj => return fs.File.default_mode, + .Obj => return Io.File.default_mode, } } @@ -1660,19 +1660,19 @@ pub const Input = union(enum) { pub const Object = struct { path: Path, - file: fs.File, + file: Io.File, must_link: bool, hidden: bool, }; pub const Res = struct { path: Path, - file: fs.File, + file: Io.File, }; pub const Dso = struct { path: Path, - file: fs.File, + file: Io.File, needed: bool, weak: bool, reexport: bool, @@ -1694,7 +1694,7 @@ pub const Input = union(enum) { } /// Returns `null` in the case of `dso_exact`. - pub fn pathAndFile(input: Input) ?struct { Path, fs.File } { + pub fn pathAndFile(input: Input) ?struct { Path, Io.File } { return switch (input) { .object, .archive => |obj| .{ obj.path, obj.file }, inline .res, .dso => |x| .{ x.path, x.file }, @@ -2075,7 +2075,7 @@ fn resolveLibInput( fn finishResolveLibInput( resolved_inputs: *std.ArrayList(Input), path: Path, - file: std.fs.File, + file: Io.File, link_mode: std.builtin.LinkMode, query: UnresolvedInput.Query, ) ResolveLibInputResult { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 95f4ca8bbd..cfb02fba38 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,3 +1,24 @@ +const Dwarf = @This(); + +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const DW = std.dwarf; +const Zir = std.zig.Zir; +const assert = std.debug.assert; +const log = std.log.scoped(.dwarf); +const Writer = std.Io.Writer; + +const InternPool = @import("../InternPool.zig"); +const Module = @import("../Package.zig").Module; +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); +const codegen = @import("../codegen.zig"); +const dev = @import("../dev.zig"); +const link = @import("../link.zig"); +const target_info = @import("../target.zig"); + gpa: Allocator, bin_file: *link.File, format: DW.Format, @@ -29,16 +50,16 @@ pub const UpdateError = error{ UnexpectedEndOfFile, } || codegen.GenerateSymbolError || - std.fs.File.OpenError || - std.fs.File.SetEndPosError || - std.fs.File.CopyRangeError || - std.fs.File.PReadError || - std.fs.File.PWriteError; + Io.File.OpenError || + Io.File.SetEndPosError || + Io.File.CopyRangeError || + Io.File.PReadError || + Io.File.PWriteError; pub const FlushError = UpdateError; pub const RelocError = - std.fs.File.PWriteError; + Io.File.PWriteError; pub const AddressSize = enum(u8) { @"32" = 4, @@ -6350,7 +6371,7 @@ const AbbrevCode = enum { }); }; -fn getFile(dwarf: *Dwarf) ?std.fs.File { +fn getFile(dwarf: *Dwarf) ?Io.File { if (dwarf.bin_file.cast(.macho)) |macho_file| if (macho_file.d_sym) |*d_sym| return d_sym.file; return dwarf.bin_file.file; } @@ -6429,21 +6450,3 @@ const force_incremental = false; inline fn incremental(dwarf: Dwarf) bool { return force_incremental or dwarf.bin_file.comp.config.incremental; } - -const Allocator = std.mem.Allocator; -const DW = std.dwarf; -const Dwarf = @This(); -const InternPool = @import("../InternPool.zig"); -const Module = @import("../Package.zig").Module; -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const Zcu = @import("../Zcu.zig"); -const Zir = std.zig.Zir; -const assert = std.debug.assert; -const codegen = @import("../codegen.zig"); -const dev = @import("../dev.zig"); -const link = @import("../link.zig"); -const log = std.log.scoped(.dwarf); -const std = @import("std"); -const target_info = @import("../target.zig"); -const Writer = std.Io.Writer; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ae7d631f09..584a50c7f2 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3651,7 +3651,7 @@ fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index, zig_obje pub fn addFileHandle( gpa: Allocator, file_handles: *std.ArrayList(File.Handle), - handle: fs.File, + handle: Io.File, ) Allocator.Error!File.HandleIndex { try file_handles.append(gpa, handle); return @intCast(file_handles.items.len - 1); @@ -4068,7 +4068,7 @@ fn fmtDumpState(self: *Elf, writer: *std.Io.Writer) std.Io.Writer.Error!void { } /// Caller owns the memory. -pub fn preadAllAlloc(allocator: Allocator, handle: fs.File, offset: u64, size: u64) ![]u8 { +pub fn preadAllAlloc(allocator: Allocator, handle: Io.File, offset: u64, size: u64) ![]u8 { const buffer = try allocator.alloc(u8, math.cast(usize, size) orelse return error.Overflow); errdefer allocator.free(buffer); const amt = try handle.preadAll(buffer, offset); @@ -4460,6 +4460,7 @@ pub fn cast(elf_file: *Elf, comptime T: type, x: anytype) error{LinkFailure}!T { } const std = @import("std"); +const Io = std.Io; const build_options = @import("build_options"); const builtin = @import("builtin"); const assert = std.debug.assert; diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index d51a82b266..c0dde4176a 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -1,3 +1,30 @@ +const Object = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const eh_frame = @import("eh_frame.zig"); +const elf = std.elf; +const fs = std.fs; +const log = std.log.scoped(.link); +const math = std.math; +const mem = std.mem; +const Path = std.Build.Cache.Path; +const Allocator = std.mem.Allocator; + +const Diags = @import("../../link.zig").Diags; +const Archive = @import("Archive.zig"); +const Atom = @import("Atom.zig"); +const AtomList = @import("AtomList.zig"); +const Cie = eh_frame.Cie; +const Elf = @import("../Elf.zig"); +const Fde = eh_frame.Fde; +const File = @import("file.zig").File; +const Merge = @import("Merge.zig"); +const Symbol = @import("Symbol.zig"); +const Alignment = Atom.Alignment; +const riscv = @import("../riscv.zig"); + archive: ?InArchive = null, /// Archive files cannot contain subdirectories, so only the basename is needed /// for output. However, the full path is kept for error reporting. @@ -68,7 +95,7 @@ pub fn parse( diags: *Diags, /// For error reporting purposes only. path: Path, - handle: fs.File, + handle: Io.File, target: *const std.Target, debug_fmt_strip: bool, default_sym_version: elf.Versym, @@ -97,7 +124,7 @@ pub fn parseCommon( gpa: Allocator, diags: *Diags, path: Path, - handle: fs.File, + handle: Io.File, target: *const std.Target, ) !void { const offset = if (self.archive) |ar| ar.offset else 0; @@ -264,7 +291,7 @@ fn initAtoms( gpa: Allocator, diags: *Diags, path: Path, - handle: fs.File, + handle: Io.File, debug_fmt_strip: bool, target: *const std.Target, ) !void { @@ -421,7 +448,7 @@ fn initSymbols( fn parseEhFrame( self: *Object, gpa: Allocator, - handle: fs.File, + handle: Io.File, shndx: u32, target: *const std.Target, ) !void { @@ -1310,7 +1337,7 @@ fn addString(self: *Object, gpa: Allocator, str: []const u8) !u32 { } /// Caller owns the memory. -fn preadShdrContentsAlloc(self: Object, gpa: Allocator, handle: fs.File, index: u32) ![]u8 { +fn preadShdrContentsAlloc(self: Object, gpa: Allocator, handle: Io.File, index: u32) ![]u8 { assert(index < self.shdrs.items.len); const offset = if (self.archive) |ar| ar.offset else 0; const shdr = self.shdrs.items[index]; @@ -1320,7 +1347,7 @@ fn preadShdrContentsAlloc(self: Object, gpa: Allocator, handle: fs.File, index: } /// Caller owns the memory. -fn preadRelocsAlloc(self: Object, gpa: Allocator, handle: fs.File, shndx: u32) ![]align(1) const elf.Elf64_Rela { +fn preadRelocsAlloc(self: Object, gpa: Allocator, handle: Io.File, shndx: u32) ![]align(1) const elf.Elf64_Rela { const raw = try self.preadShdrContentsAlloc(gpa, handle, shndx); const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela)); return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num]; @@ -1552,29 +1579,3 @@ const InArchive = struct { offset: u64, size: u32, }; - -const Object = @This(); - -const std = @import("std"); -const assert = std.debug.assert; -const eh_frame = @import("eh_frame.zig"); -const elf = std.elf; -const fs = std.fs; -const log = std.log.scoped(.link); -const math = std.math; -const mem = std.mem; -const Path = std.Build.Cache.Path; -const Allocator = std.mem.Allocator; - -const Diags = @import("../../link.zig").Diags; -const Archive = @import("Archive.zig"); -const Atom = @import("Atom.zig"); -const AtomList = @import("AtomList.zig"); -const Cie = eh_frame.Cie; -const Elf = @import("../Elf.zig"); -const Fde = eh_frame.Fde; -const File = @import("file.zig").File; -const Merge = @import("Merge.zig"); -const Symbol = @import("Symbol.zig"); -const Alignment = Atom.Alignment; -const riscv = @import("../riscv.zig"); diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 1e17aa34a8..3720fe53d6 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -1,3 +1,20 @@ +const SharedObject = @This(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const elf = std.elf; +const log = std.log.scoped(.elf); +const mem = std.mem; +const Path = std.Build.Cache.Path; +const Stat = std.Build.Cache.File.Stat; +const Allocator = mem.Allocator; + +const Elf = @import("../Elf.zig"); +const File = @import("file.zig").File; +const Symbol = @import("Symbol.zig"); +const Diags = @import("../../link.zig").Diags; + path: Path, index: File.Index, @@ -94,7 +111,7 @@ pub fn parseHeader( gpa: Allocator, diags: *Diags, file_path: Path, - fs_file: std.fs.File, + fs_file: Io.File, stat: Stat, target: *const std.Target, ) !Header { @@ -192,7 +209,7 @@ pub fn parse( gpa: Allocator, /// Moves resources from header. Caller may unconditionally deinit. header: *Header, - fs_file: std.fs.File, + fs_file: Io.File, ) !Parsed { const symtab = if (header.dynsym_sect_index) |index| st: { const shdr = header.sections[index]; @@ -534,19 +551,3 @@ const Format = struct { } } }; - -const SharedObject = @This(); - -const std = @import("std"); -const assert = std.debug.assert; -const elf = std.elf; -const log = std.log.scoped(.elf); -const mem = std.mem; -const Path = std.Build.Cache.Path; -const Stat = std.Build.Cache.File.Stat; -const Allocator = mem.Allocator; - -const Elf = @import("../Elf.zig"); -const File = @import("file.zig").File; -const Symbol = @import("Symbol.zig"); -const Diags = @import("../../link.zig").Diags; diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 50f5159d18..52d3c6e6f0 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -1,3 +1,20 @@ +const std = @import("std"); +const Io = std.Io; +const elf = std.elf; +const log = std.log.scoped(.link); +const Path = std.Build.Cache.Path; +const Allocator = std.mem.Allocator; + +const Archive = @import("Archive.zig"); +const Atom = @import("Atom.zig"); +const Cie = @import("eh_frame.zig").Cie; +const Elf = @import("../Elf.zig"); +const LinkerDefined = @import("LinkerDefined.zig"); +const Object = @import("Object.zig"); +const SharedObject = @import("SharedObject.zig"); +const Symbol = @import("Symbol.zig"); +const ZigObject = @import("ZigObject.zig"); + pub const File = union(enum) { zig_object: *ZigObject, linker_defined: *LinkerDefined, @@ -279,22 +296,6 @@ pub const File = union(enum) { shared_object: SharedObject, }; - pub const Handle = std.fs.File; + pub const Handle = Io.File; pub const HandleIndex = Index; }; - -const std = @import("std"); -const elf = std.elf; -const log = std.log.scoped(.link); -const Path = std.Build.Cache.Path; -const Allocator = std.mem.Allocator; - -const Archive = @import("Archive.zig"); -const Atom = @import("Atom.zig"); -const Cie = @import("eh_frame.zig").Cie; -const Elf = @import("../Elf.zig"); -const LinkerDefined = @import("LinkerDefined.zig"); -const Object = @import("Object.zig"); -const SharedObject = @import("SharedObject.zig"); -const Symbol = @import("Symbol.zig"); -const ZigObject = @import("ZigObject.zig"); diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 7d12ccedb2..e35444bc02 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -1,3 +1,23 @@ +const Elf = @This(); + +const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const log = std.log.scoped(.link); + +const codegen = @import("../codegen.zig"); +const Compilation = @import("../Compilation.zig"); +const InternPool = @import("../InternPool.zig"); +const link = @import("../link.zig"); +const MappedFile = @import("MappedFile.zig"); +const target_util = @import("../target.zig"); +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); + base: link.File, options: link.File.OpenOptions, mf: MappedFile, @@ -1973,8 +1993,8 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index { return lazy_gop.value_ptr.*; } -pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || - std.Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void { +pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError || + Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void { const io = elf.base.comp.io; var buf: [4096]u8 = undefined; switch (input) { @@ -2007,7 +2027,7 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || .dso_exact => |dso_exact| try elf.loadDsoExact(dso_exact.name), } } -fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { +fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { const comp = elf.base.comp; const gpa = comp.gpa; const diags = &comp.link_diags; @@ -2067,7 +2087,7 @@ fn loadObject( elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, - fr: *std.Io.File.Reader, + fr: *Io.File.Reader, fl: MappedFile.Node.FileLocation, ) !void { const comp = elf.base.comp; @@ -2310,7 +2330,7 @@ fn loadObject( }, } } -fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { +fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { const comp = elf.base.comp; const diags = &comp.link_diags; const r = &fr.interface; @@ -3822,19 +3842,3 @@ pub fn printNode( try w.writeByte('\n'); } } - -const assert = std.debug.assert; -const builtin = @import("builtin"); -const codegen = @import("../codegen.zig"); -const Compilation = @import("../Compilation.zig"); -const Elf = @This(); -const InternPool = @import("../InternPool.zig"); -const link = @import("../link.zig"); -const log = std.log.scoped(.link); -const MappedFile = @import("MappedFile.zig"); -const native_endian = builtin.cpu.arch.endian(); -const std = @import("std"); -const target_util = @import("../target.zig"); -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const Zcu = @import("../Zcu.zig"); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 471465cea1..72a49c0c9e 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -890,7 +890,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { _ = try self.addTbd(.fromLinkInput(input), true, fh); } -fn parseFatFile(self: *MachO, file: std.fs.File, path: Path) !?fat.Arch { +fn parseFatFile(self: *MachO, file: Io.File, path: Path) !?fat.Arch { const diags = &self.base.comp.link_diags; const fat_h = fat.readFatHeader(file) catch return null; if (fat_h.magic != macho.FAT_MAGIC and fat_h.magic != macho.FAT_MAGIC_64) return null; @@ -903,7 +903,7 @@ fn parseFatFile(self: *MachO, file: std.fs.File, path: Path) !?fat.Arch { return diags.failParse(path, "missing arch in universal file: expected {s}", .{@tagName(cpu_arch)}); } -pub fn readMachHeader(file: std.fs.File, offset: usize) !macho.mach_header_64 { +pub fn readMachHeader(file: Io.File, offset: usize) !macho.mach_header_64 { var buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined; const nread = try file.preadAll(&buffer, offset); if (nread != buffer.len) return error.InputOutput; @@ -911,7 +911,7 @@ pub fn readMachHeader(file: std.fs.File, offset: usize) !macho.mach_header_64 { return hdr; } -pub fn readArMagic(file: std.fs.File, offset: usize, buffer: *[Archive.SARMAG]u8) ![]const u8 { +pub fn readArMagic(file: Io.File, offset: usize, buffer: *[Archive.SARMAG]u8) ![]const u8 { const nread = try file.preadAll(buffer, offset); if (nread != buffer.len) return error.InputOutput; return buffer[0..Archive.SARMAG]; @@ -3768,7 +3768,7 @@ pub fn getInternalObject(self: *MachO) ?*InternalObject { return self.getFile(index).?.internal; } -pub fn addFileHandle(self: *MachO, file: fs.File) !File.HandleIndex { +pub fn addFileHandle(self: *MachO, file: Io.File) !File.HandleIndex { const gpa = self.base.comp.gpa; const index: File.HandleIndex = @intCast(self.file_handles.items.len); const fh = try self.file_handles.addOne(gpa); @@ -5373,10 +5373,11 @@ const max_distance = (1 << (jump_bits - 1)); const max_allowed_distance = max_distance - 0x500_000; const MachO = @This(); - -const std = @import("std"); const build_options = @import("build_options"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const fs = std.fs; const log = std.log.scoped(.link); @@ -5386,6 +5387,11 @@ const math = std.math; const mem = std.mem; const meta = std.meta; const Writer = std.Io.Writer; +const AtomicBool = std.atomic.Value(bool); +const Cache = std.Build.Cache; +const Hash = std.hash.Wyhash; +const Md5 = std.crypto.hash.Md5; +const Allocator = std.mem.Allocator; const aarch64 = codegen.aarch64.encoding; const bind = @import("MachO/dyld_info/bind.zig"); @@ -5403,11 +5409,8 @@ const trace = @import("../tracy.zig").trace; const synthetic = @import("MachO/synthetic.zig"); const Alignment = Atom.Alignment; -const Allocator = mem.Allocator; const Archive = @import("MachO/Archive.zig"); -const AtomicBool = std.atomic.Value(bool); const Bind = bind.Bind; -const Cache = std.Build.Cache; const CodeSignature = @import("MachO/CodeSignature.zig"); const Compilation = @import("../Compilation.zig"); const DataInCode = synthetic.DataInCode; @@ -5417,14 +5420,12 @@ const ExportTrie = @import("MachO/dyld_info/Trie.zig"); const Path = Cache.Path; const File = @import("MachO/file.zig").File; const GotSection = synthetic.GotSection; -const Hash = std.hash.Wyhash; const Indsymtab = synthetic.Indsymtab; const InternalObject = @import("MachO/InternalObject.zig"); const ObjcStubsSection = synthetic.ObjcStubsSection; const Object = @import("MachO/Object.zig"); const LazyBind = bind.LazyBind; const LaSymbolPtrSection = synthetic.LaSymbolPtrSection; -const Md5 = std.crypto.hash.Md5; const Zcu = @import("../Zcu.zig"); const InternPool = @import("../InternPool.zig"); const Rebase = @import("MachO/dyld_info/Rebase.zig"); diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig index 5bded3b9e3..5f9a9ecac9 100644 --- a/src/link/MachO/CodeSignature.zig +++ b/src/link/MachO/CodeSignature.zig @@ -1,17 +1,19 @@ const CodeSignature = @This(); const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const fs = std.fs; const log = std.log.scoped(.link); const macho = std.macho; const mem = std.mem; const testing = std.testing; +const Sha256 = std.crypto.hash.sha2.Sha256; +const Allocator = std.mem.Allocator; + const trace = @import("../../tracy.zig").trace; -const Allocator = mem.Allocator; const Hasher = @import("hasher.zig").ParallelHasher; const MachO = @import("../MachO.zig"); -const Sha256 = std.crypto.hash.sha2.Sha256; const hash_size = Sha256.digest_length; @@ -250,7 +252,7 @@ pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const } pub const WriteOpts = struct { - file: fs.File, + file: Io.File, exec_seg_base: u64, exec_seg_limit: u64, file_size: u32, diff --git a/src/link/MachO/fat.zig b/src/link/MachO/fat.zig index 7772f7a4de..fd9a302531 100644 --- a/src/link/MachO/fat.zig +++ b/src/link/MachO/fat.zig @@ -1,18 +1,20 @@ +const builtin = @import("builtin"); +const native_endian = builtin.target.cpu.arch.endian(); + const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; -const builtin = @import("builtin"); const log = std.log.scoped(.macho); const macho = std.macho; const mem = std.mem; -const native_endian = builtin.target.cpu.arch.endian(); const MachO = @import("../MachO.zig"); -pub fn readFatHeader(file: std.fs.File) !macho.fat_header { +pub fn readFatHeader(file: Io.File) !macho.fat_header { return readFatHeaderGeneric(macho.fat_header, file, 0); } -fn readFatHeaderGeneric(comptime Hdr: type, file: std.fs.File, offset: usize) !Hdr { +fn readFatHeaderGeneric(comptime Hdr: type, file: Io.File, offset: usize) !Hdr { var buffer: [@sizeOf(Hdr)]u8 = undefined; const nread = try file.preadAll(&buffer, offset); if (nread != buffer.len) return error.InputOutput; @@ -27,7 +29,7 @@ pub const Arch = struct { size: u32, }; -pub fn parseArchs(file: std.fs.File, fat_header: macho.fat_header, out: *[2]Arch) ![]const Arch { +pub fn parseArchs(file: Io.File, fat_header: macho.fat_header, out: *[2]Arch) ![]const Arch { var count: usize = 0; var fat_arch_index: u32 = 0; while (fat_arch_index < fat_header.nfat_arch and count < out.len) : (fat_arch_index += 1) { diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index 05b43de181..cd687a4941 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -355,11 +355,12 @@ pub const File = union(enum) { dylib: Dylib, }; - pub const Handle = std.fs.File; + pub const Handle = Io.File; pub const HandleIndex = Index; }; const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const log = std.log.scoped(.link); const macho = std.macho; diff --git a/src/link/MachO/hasher.zig b/src/link/MachO/hasher.zig index 78cd847c40..8cf53071c8 100644 --- a/src/link/MachO/hasher.zig +++ b/src/link/MachO/hasher.zig @@ -1,3 +1,9 @@ +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; + +const trace = @import("../../tracy.zig").trace; + pub fn ParallelHasher(comptime Hasher: type) type { const hash_size = Hasher.digest_length; @@ -5,7 +11,7 @@ pub fn ParallelHasher(comptime Hasher: type) type { allocator: Allocator, io: std.Io, - pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct { + pub fn hash(self: Self, file: Io.File, out: [][hash_size]u8, opts: struct { chunk_size: u64 = 0x4000, max_file_size: ?u64 = null, }) !void { @@ -23,7 +29,7 @@ pub fn ParallelHasher(comptime Hasher: type) type { const buffer = try self.allocator.alloc(u8, chunk_size * out.len); defer self.allocator.free(buffer); - const results = try self.allocator.alloc(fs.File.PReadError!usize, out.len); + const results = try self.allocator.alloc(Io.File.PReadError!usize, out.len); defer self.allocator.free(results); { @@ -51,11 +57,11 @@ pub fn ParallelHasher(comptime Hasher: type) type { } fn worker( - file: fs.File, + file: Io.File, fstart: usize, buffer: []u8, out: *[hash_size]u8, - err: *fs.File.PReadError!usize, + err: *Io.File.PReadError!usize, ) void { const tracy = trace(@src()); defer tracy.end(); @@ -66,11 +72,3 @@ pub fn ParallelHasher(comptime Hasher: type) type { const Self = @This(); }; } - -const assert = std.debug.assert; -const fs = std.fs; -const mem = std.mem; -const std = @import("std"); -const trace = @import("../../tracy.zig").trace; - -const Allocator = mem.Allocator; diff --git a/src/link/MachO/uuid.zig b/src/link/MachO/uuid.zig index d08ac0c5b8..4d8eac7523 100644 --- a/src/link/MachO/uuid.zig +++ b/src/link/MachO/uuid.zig @@ -1,10 +1,18 @@ +const std = @import("std"); +const Io = std.Io; +const Md5 = std.crypto.hash.Md5; + +const trace = @import("../../tracy.zig").trace; +const Compilation = @import("../../Compilation.zig"); +const Hasher = @import("hasher.zig").ParallelHasher; + /// Calculates Md5 hash of each chunk in parallel and then hashes all Md5 hashes to produce /// the final digest. /// While this is NOT a correct MD5 hash of the contents, this methodology is used by LLVM/LLD /// and we will use it too as it seems accepted by Apple OSes. /// TODO LLD also hashes the output filename to disambiguate between same builds with different /// output files. Should we also do that? -pub fn calcUuid(comp: *const Compilation, file: fs.File, file_size: u64, out: *[Md5.digest_length]u8) !void { +pub fn calcUuid(comp: *const Compilation, file: Io.File, file_size: u64, out: *[Md5.digest_length]u8) !void { const tracy = trace(@src()); defer tracy.end(); @@ -37,12 +45,3 @@ inline fn conform(out: *[Md5.digest_length]u8) void { out[6] = (out[6] & 0x0F) | (3 << 4); out[8] = (out[8] & 0x3F) | 0x80; } - -const fs = std.fs; -const mem = std.mem; -const std = @import("std"); -const trace = @import("../../tracy.zig").trace; - -const Compilation = @import("../../Compilation.zig"); -const Md5 = std.crypto.hash.Md5; -const Hasher = @import("hasher.zig").ParallelHasher; diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig index 975b94578b..7d4134ccaf 100644 --- a/src/link/MappedFile.zig +++ b/src/link/MappedFile.zig @@ -1,3 +1,15 @@ +const MappedFile = @This(); + +const builtin = @import("builtin"); +const is_linux = builtin.os.tag == .linux; +const is_windows = builtin.os.tag == .windows; + +const std = @import("std"); +const Io = std.Io; +const assert = std.debug.assert; +const linux = std.os.linux; +const windows = std.os.windows; + file: std.Io.File, flags: packed struct { block_size: std.mem.Alignment, @@ -16,7 +28,7 @@ writers: std.SinglyLinkedList, pub const growth_factor = 4; -pub const Error = std.posix.MMapError || std.posix.MRemapError || std.fs.File.SetEndPosError || error{ +pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.SetEndPosError || error{ NotFile, SystemResources, IsDir, @@ -618,7 +630,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested // Resize the entire file if (ni == Node.Index.root) { try mf.ensureCapacityForSetLocation(gpa); - try std.fs.File.adaptFromNewApi(mf.file).setEndPos(new_size); + try Io.File.adaptFromNewApi(mf.file).setEndPos(new_size); try mf.ensureTotalCapacity(@intCast(new_size)); ni.setLocationAssumeCapacity(mf, old_offset, new_size); return; @@ -1059,12 +1071,3 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void { ni = node.next; } } - -const assert = std.debug.assert; -const builtin = @import("builtin"); -const is_linux = builtin.os.tag == .linux; -const is_windows = builtin.os.tag == .windows; -const linux = std.os.linux; -const MappedFile = @This(); -const std = @import("std"); -const windows = std.os.windows; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 160e6cdcc6..7ab1e0eb4b 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -20,6 +20,7 @@ const native_endian = builtin.cpu.arch.endian(); const build_options = @import("build_options"); const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; const Path = Cache.Path; @@ -3001,9 +3002,9 @@ pub fn createEmpty( .read = true, .mode = if (fs.has_executable_bit) if (target.os.tag == .wasi and output_mode == .Exe) - fs.File.default_mode | 0b001_000_000 + Io.File.default_mode | 0b001_000_000 else - fs.File.default_mode + Io.File.default_mode else 0, }); diff --git a/src/link/tapi.zig b/src/link/tapi.zig index 4c1471a6b4..fff25b7544 100644 --- a/src/link/tapi.zig +++ b/src/link/tapi.zig @@ -1,10 +1,10 @@ const std = @import("std"); -const fs = std.fs; +const Io = std.Io; const mem = std.mem; const log = std.log.scoped(.tapi); -const yaml = @import("tapi/yaml.zig"); +const Allocator = std.mem.Allocator; -const Allocator = mem.Allocator; +const yaml = @import("tapi/yaml.zig"); const Yaml = yaml.Yaml; const VersionField = union(enum) { @@ -130,7 +130,7 @@ pub const Tbd = union(enum) { pub const TapiError = error{ NotLibStub, InputOutput, -} || yaml.YamlError || std.fs.File.PReadError; +} || yaml.YamlError || Io.File.PReadError; pub const LibStub = struct { /// Underlying memory for stub's contents. @@ -139,7 +139,7 @@ pub const LibStub = struct { /// Typed contents of the tbd file. inner: []Tbd, - pub fn loadFromFile(allocator: Allocator, file: fs.File) TapiError!LibStub { + pub fn loadFromFile(allocator: Allocator, file: Io.File) TapiError!LibStub { const filesize = blk: { const stat = file.stat() catch break :blk std.math.maxInt(u32); break :blk @min(stat.size, std.math.maxInt(u32)); -- cgit v1.2.3 From dd1d15b72aa3bae4b38e2337609758ffb7a7b55a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 6 Dec 2025 17:32:19 -0800 Subject: update all occurrences of std.fs.Dir to std.Io.Dir --- lib/compiler/aro/aro/Compilation.zig | 6 ++-- lib/compiler/resinator/cli.zig | 2 +- lib/compiler/resinator/errors.zig | 6 ++-- lib/compiler/resinator/main.zig | 2 +- lib/compiler/resinator/utils.zig | 4 +-- lib/compiler/std-docs.zig | 2 +- lib/std/Build.zig | 2 +- lib/std/Build/Step.zig | 6 ++-- lib/std/Build/Watch.zig | 2 +- lib/std/Io/Dir.zig | 2 +- lib/std/crypto/Certificate/Bundle.zig | 4 +-- lib/std/dynamic_library.zig | 2 +- lib/std/fs/path.zig | 4 +-- lib/std/fs/test.zig | 13 ++++---- lib/std/process/Child.zig | 4 +-- lib/std/testing.zig | 60 ++++++++++++++++++----------------- lib/std/zig/WindowsSdk.zig | 8 ++--- lib/std/zig/llvm/Builder.zig | 2 +- lib/std/zip.zig | 5 +-- src/Compilation.zig | 4 +-- src/Package/Fetch/git.zig | 4 +-- src/fmt.zig | 6 ++-- src/link/Lld.zig | 7 ++-- src/link/MachO.zig | 2 +- 24 files changed, 81 insertions(+), 78 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 06b27c33bb..c31caefb0f 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -154,7 +154,7 @@ gpa: Allocator, /// Allocations in this arena live all the way until `Compilation.deinit`. arena: Allocator, io: Io, -cwd: std.fs.Dir, +cwd: Io.Dir, diagnostics: *Diagnostics, sources: std.StringArrayHashMapUnmanaged(Source) = .empty, @@ -181,7 +181,7 @@ pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .empty, /// Used by MS extensions which allow searching for includes relative to the directory of the main source file. ms_cwd_source_id: ?Source.Id = null, -pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) Compilation { +pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: Io.Dir) Compilation { return .{ .gpa = gpa, .arena = arena, @@ -193,7 +193,7 @@ pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, /// Initialize Compilation with default environment, /// pragma handlers and emulation mode set to target. -pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation { +pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: Io.Dir) !Compilation { var comp: Compilation = .{ .gpa = gpa, .arena = arena, diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 17da5c7b75..bb54289e3e 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -250,7 +250,7 @@ pub const Options = struct { /// worlds' situation where we'll be compatible with most use-cases /// of the .rc extension being omitted from the CLI args, but still /// work fine if the file itself does not have an extension. - pub fn maybeAppendRC(options: *Options, cwd: std.fs.Dir) !void { + pub fn maybeAppendRC(options: *Options, cwd: Io.Dir) !void { switch (options.input_source) { .stdio => return, .filename => {}, diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 61fd00e683..14ff28a697 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -67,7 +67,7 @@ pub const Diagnostics = struct { return @intCast(index); } - pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void { + pub fn renderToStdErr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void { const io = self.io; const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); @@ -903,7 +903,7 @@ pub fn renderErrorMessage( io: Io, writer: *std.Io.Writer, tty_config: std.Io.tty.Config, - cwd: std.fs.Dir, + cwd: Io.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, @@ -1100,7 +1100,7 @@ const CorrespondingLines = struct { pub fn init( io: Io, - cwd: std.fs.Dir, + cwd: Io.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index e171d8199c..c726a06cf4 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -707,7 +707,7 @@ const ErrorHandler = union(enum) { pub fn emitDiagnostics( self: *ErrorHandler, allocator: Allocator, - cwd: std.fs.Dir, + cwd: Io.Dir, source: []const u8, diagnostics: *Diagnostics, mappings: SourceMappings, diff --git a/lib/compiler/resinator/utils.zig b/lib/compiler/resinator/utils.zig index e8565f3af9..3f03b73c54 100644 --- a/lib/compiler/resinator/utils.zig +++ b/lib/compiler/resinator/utils.zig @@ -25,11 +25,11 @@ pub const UncheckedSliceWriter = struct { } }; -/// Cross-platform 'std.fs.Dir.openFile' wrapper that will always return IsDir if +/// Cross-platform 'Io.Dir.openFile' wrapper that will always return IsDir if /// a directory is attempted to be opened. /// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed. pub fn openFileNotDir( - cwd: std.fs.Dir, + cwd: Io.Dir, io: Io, path: []const u8, flags: Io.File.OpenFlags, diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index 15c17ee59b..f1ca7fb5bb 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -133,7 +133,7 @@ fn accept(context: *Context, connection: std.net.Server.Connection) void { const Context = struct { gpa: Allocator, io: Io, - lib_dir: std.fs.Dir, + lib_dir: Io.Dir, zig_lib_directory: []const u8, zig_exe_path: []const u8, global_cache_path: []const u8, diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 2755b895c2..7bfdbb6449 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1699,7 +1699,7 @@ pub fn addCheckFile( return Step.CheckFile.create(b, file_source, options); } -pub fn truncateFile(b: *Build, dest_path: []const u8) (fs.Dir.MakeError || fs.Dir.StatFileError)!void { +pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Dir.StatFileError)!void { const io = b.graph.io; if (b.verbose) log.info("truncate {s}", .{dest_path}); const cwd = fs.cwd(); diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 2b1e6d8ace..56ef32e8d8 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -505,7 +505,7 @@ pub fn evalZigProcess( return result; } -/// Wrapper around `std.fs.Dir.updateFile` that handles verbose and error output. +/// Wrapper around `Io.Dir.updateFile` that handles verbose and error output. pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !Io.Dir.PrevStatus { const b = s.owner; const io = b.graph.io; @@ -515,8 +515,8 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); } -/// Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output. -pub fn installDir(s: *Step, dest_path: []const u8) !std.fs.Dir.MakePathStatus { +/// Wrapper around `Io.Dir.makePathStatus` that handles verbose and error output. +pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.MakePathStatus { const b = s.owner; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); return std.fs.cwd().makePathStatus(dest_path) catch |err| diff --git a/lib/std/Build/Watch.zig b/lib/std/Build/Watch.zig index ca01376e02..ff06ad3ff3 100644 --- a/lib/std/Build/Watch.zig +++ b/lib/std/Build/Watch.zig @@ -350,7 +350,7 @@ const Os = switch (builtin.os.tag) { } fn init(gpa: Allocator, path: Cache.Path) !*@This() { - // The following code is a drawn out NtCreateFile call. (mostly adapted from std.fs.Dir.makeOpenDirAccessMaskW) + // The following code is a drawn out NtCreateFile call. (mostly adapted from Io.Dir.makeOpenDirAccessMaskW) // It's necessary in order to get the specific flags that are required when calling ReadDirectoryChangesW. var dir_handle: windows.HANDLE = undefined; const root_fd = path.root_dir.handle.fd; diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 5a74c8ca72..1c28c2f9b3 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -481,7 +481,7 @@ pub fn updateFile( } var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. - var atomic_file = try std.fs.Dir.atomicFile(.adaptFromNewApi(dest_dir), dest_path, .{ + var atomic_file = try Dir.atomicFile(.adaptFromNewApi(dest_dir), dest_path, .{ .permissions = actual_permissions, .write_buffer = &buffer, }); diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig index 1d21918b5c..df671e6f63 100644 --- a/lib/std/crypto/Certificate/Bundle.zig +++ b/lib/std/crypto/Certificate/Bundle.zig @@ -177,7 +177,7 @@ pub fn addCertsFromDirPath( cb: *Bundle, gpa: Allocator, io: Io, - dir: fs.Dir, + dir: Io.Dir, sub_dir_path: []const u8, ) AddCertsFromDirPathError!void { var iterable_dir = try dir.openDir(sub_dir_path, .{ .iterate = true }); @@ -200,7 +200,7 @@ pub fn addCertsFromDirPathAbsolute( pub const AddCertsFromDirError = AddCertsFromFilePathError; -pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, iterable_dir: fs.Dir) AddCertsFromDirError!void { +pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, iterable_dir: Io.Dir) AddCertsFromDirError!void { var it = iterable_dir.iterate(); while (try it.next()) |entry| { switch (entry.kind) { diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index ca36d5cbb9..7db177ad70 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -157,7 +157,7 @@ pub const ElfDynLib = struct { dt_gnu_hash: *elf.gnu_hash.Header, }; - fn openPath(path: []const u8, io: Io) !std.fs.Dir { + fn openPath(path: []const u8, io: Io) !Io.Dir { if (path.len == 0) return error.NotDir; var parts = std.mem.tokenizeScalar(u8, path, '/'); var parent = if (path[0] == '/') try std.fs.cwd().openDir("/", .{}) else std.fs.cwd(); diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig index f00007756f..a8465f52d4 100644 --- a/lib/std/fs/path.zig +++ b/lib/std/fs/path.zig @@ -872,7 +872,7 @@ pub fn resolve(allocator: Allocator, paths: []const []const u8) Allocator.Error! /// This function is like a series of `cd` statements executed one after another. /// It resolves "." and ".." to the best of its ability, but will not convert relative paths to -/// an absolute path, use std.fs.Dir.realpath instead. +/// an absolute path, use Io.Dir.realpath instead. /// ".." components may persist in the resolved path if the resolved path is relative or drive-relative. /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters. /// @@ -1095,7 +1095,7 @@ pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) Allocator /// This function is like a series of `cd` statements executed one after another. /// It resolves "." and ".." to the best of its ability, but will not convert relative paths to -/// an absolute path, use std.fs.Dir.realpath instead. +/// an absolute path, use Io.Dir.realpath instead. /// ".." components may persist in the resolved path if the resolved path is relative. /// The result does not have a trailing path separator. /// This function does not perform any syscalls. Executing this series of path diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index f770ddd30e..36ccd3a6be 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -9,12 +9,11 @@ const mem = std.mem; const wasi = std.os.wasi; const windows = std.os.windows; const posix = std.posix; - const ArenaAllocator = std.heap.ArenaAllocator; -const Dir = std.fs.Dir; +const Dir = std.Io.Dir; const File = std.Io.File; -const tmpDir = testing.tmpDir; -const SymLinkFlags = std.fs.Dir.SymLinkFlags; +const tmpDir = std.testing.tmpDir; +const SymLinkFlags = std.Io.Dir.SymLinkFlags; const PathType = enum { relative, @@ -80,7 +79,7 @@ const TestContext = struct { path_sep: u8, arena: ArenaAllocator, tmp: testing.TmpDir, - dir: std.fs.Dir, + dir: Io.Dir, transform_fn: *const PathType.TransformFn, pub fn init(path_type: PathType, path_sep: u8, allocator: mem.Allocator, transform_fn: *const PathType.TransformFn) TestContext { @@ -1772,7 +1771,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { errdefer file.close(io); const S = struct { - fn checkFn(dir: *fs.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { + fn checkFn(dir: *Io.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { started.set(); const file1 = try dir.createFile(path, .{ .lock = .exclusive }); @@ -2016,7 +2015,7 @@ test "walker without fully iterating" { try testing.expectEqual(@as(usize, 1), num_walked); } -test "'.' and '..' in fs.Dir functions" { +test "'.' and '..' in Io.Dir functions" { if (native_os == .windows and builtin.cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/17134 return error.SkipZigTest; diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index 87d2fe3ba9..b774303901 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -77,7 +77,7 @@ cwd: ?[]const u8, /// Set to change the current working directory when spawning the child process. /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 /// Once that is done, `cwd` will be deprecated in favor of this field. -cwd_dir: ?fs.Dir = null, +cwd_dir: ?Io.Dir = null, err_pipe: if (native_os == .windows) void else ?posix.fd_t, @@ -439,7 +439,7 @@ pub fn run(args: struct { allocator: mem.Allocator, argv: []const []const u8, cwd: ?[]const u8 = null, - cwd_dir: ?fs.Dir = null, + cwd_dir: ?Io.Dir = null, /// Required if unable to access the current env map (e.g. building a /// library on some platforms). env_map: ?*const EnvMap = null, diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 63131d771c..19038543a6 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -1,5 +1,7 @@ -const std = @import("std.zig"); const builtin = @import("builtin"); + +const std = @import("std.zig"); +const Io = std.Io; const assert = std.debug.assert; const math = std.math; @@ -28,7 +30,7 @@ pub var allocator_instance: std.heap.GeneralPurposeAllocator(.{ break :b .init; }; -pub var io_instance: std.Io.Threaded = undefined; +pub var io_instance: Io.Threaded = undefined; pub const io = io_instance.io(); /// TODO https://github.com/ziglang/zig/issues/5738 @@ -355,7 +357,7 @@ test expectApproxEqRel { /// This function is intended to be used only in tests. When the two slices are not /// equal, prints diagnostics to stderr to show exactly how they are not equal (with /// the differences highlighted in red), then returns a test failure error. -/// The colorized output is optional and controlled by the return of `std.Io.tty.Config.detect`. +/// The colorized output is optional and controlled by the return of `Io.tty.Config.detect`. /// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead. pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void { const diff_index: usize = diff_index: { @@ -378,8 +380,8 @@ fn failEqualSlices( expected: []const T, actual: []const T, diff_index: usize, - w: *std.Io.Writer, - ttyconf: std.Io.tty.Config, + w: *Io.Writer, + ttyconf: Io.tty.Config, ) !void { try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); @@ -464,11 +466,11 @@ fn SliceDiffer(comptime T: type) type { start_index: usize, expected: []const T, actual: []const T, - ttyconf: std.Io.tty.Config, + ttyconf: Io.tty.Config, const Self = @This(); - pub fn write(self: Self, writer: *std.Io.Writer) !void { + pub fn write(self: Self, writer: *Io.Writer) !void { for (self.expected, 0..) |value, i| { const full_index = self.start_index + i; const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; @@ -487,9 +489,9 @@ fn SliceDiffer(comptime T: type) type { const BytesDiffer = struct { expected: []const u8, actual: []const u8, - ttyconf: std.Io.tty.Config, + ttyconf: Io.tty.Config, - pub fn write(self: BytesDiffer, writer: *std.Io.Writer) !void { + pub fn write(self: BytesDiffer, writer: *Io.Writer) !void { var expected_iterator = std.mem.window(u8, self.expected, 16, 16); var row: usize = 0; while (expected_iterator.next()) |chunk| { @@ -535,7 +537,7 @@ const BytesDiffer = struct { } } - fn writeDiff(self: BytesDiffer, writer: *std.Io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void { + fn writeDiff(self: BytesDiffer, writer: *Io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void { if (diff) try self.ttyconf.setColor(writer, .red); try writer.print(fmt, args); if (diff) try self.ttyconf.setColor(writer, .reset); @@ -605,8 +607,8 @@ pub fn expect(ok: bool) !void { } pub const TmpDir = struct { - dir: std.fs.Dir, - parent_dir: std.fs.Dir, + dir: Io.Dir, + parent_dir: Io.Dir, sub_path: [sub_path_len]u8, const random_bytes_count = 12; @@ -620,7 +622,7 @@ pub const TmpDir = struct { } }; -pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir { +pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; std.crypto.random.bytes(&random_bytes); var sub_path: [TmpDir.sub_path_len]u8 = undefined; @@ -929,7 +931,7 @@ test "expectEqualDeep primitive type" { a, b, - pub fn format(self: @This(), writer: *std.Io.Writer) !void { + pub fn format(self: @This(), writer: *Io.Writer) !void { try writer.writeAll(@tagName(self)); } }; @@ -1160,7 +1162,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime } else |err| switch (err) { error.OutOfMemory => { if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) { - const tty_config: std.Io.tty.Config = .detect(.stderr()); + const tty_config: Io.tty.Config = .detect(.stderr()); print( "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}", .{ @@ -1220,14 +1222,14 @@ pub inline fn fuzz( return @import("root").fuzz(context, testOne, options); } -/// A `std.Io.Reader` that writes a predetermined list of buffers during `stream`. +/// A `Io.Reader` that writes a predetermined list of buffers during `stream`. pub const Reader = struct { calls: []const Call, - interface: std.Io.Reader, + interface: Io.Reader, next_call_index: usize, next_offset: usize, /// Further reduces how many bytes are written in each `stream` call. - artificial_limit: std.Io.Limit = .unlimited, + artificial_limit: Io.Limit = .unlimited, pub const Call = struct { buffer: []const u8, @@ -1247,7 +1249,7 @@ pub const Reader = struct { }; } - fn stream(io_r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + fn stream(io_r: *Io.Reader, w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize { const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r)); if (r.calls.len - r.next_call_index == 0) return error.EndOfStream; const call = r.calls[r.next_call_index]; @@ -1262,13 +1264,13 @@ pub const Reader = struct { } }; -/// A `std.Io.Reader` that gets its data from another `std.Io.Reader`, and always +/// A `Io.Reader` that gets its data from another `Io.Reader`, and always /// writes to its own buffer (and returns 0) during `stream` and `readVec`. pub const ReaderIndirect = struct { - in: *std.Io.Reader, - interface: std.Io.Reader, + in: *Io.Reader, + interface: Io.Reader, - pub fn init(in: *std.Io.Reader, buffer: []u8) ReaderIndirect { + pub fn init(in: *Io.Reader, buffer: []u8) ReaderIndirect { return .{ .in = in, .interface = .{ @@ -1283,17 +1285,17 @@ pub const ReaderIndirect = struct { }; } - fn readVec(r: *std.Io.Reader, _: [][]u8) std.Io.Reader.Error!usize { + fn readVec(r: *Io.Reader, _: [][]u8) Io.Reader.Error!usize { try streamInner(r); return 0; } - fn stream(r: *std.Io.Reader, _: *std.Io.Writer, _: std.Io.Limit) std.Io.Reader.StreamError!usize { + fn stream(r: *Io.Reader, _: *Io.Writer, _: Io.Limit) Io.Reader.StreamError!usize { try streamInner(r); return 0; } - fn streamInner(r: *std.Io.Reader) std.Io.Reader.Error!void { + fn streamInner(r: *Io.Reader) Io.Reader.Error!void { const r_indirect: *ReaderIndirect = @alignCast(@fieldParentPtr("interface", r)); // If there's no room remaining in the buffer at all, make room. @@ -1301,12 +1303,12 @@ pub const ReaderIndirect = struct { try r.rebase(r.buffer.len); } - var writer: std.Io.Writer = .{ + var writer: Io.Writer = .{ .buffer = r.buffer, .end = r.end, .vtable = &.{ - .drain = std.Io.Writer.unreachableDrain, - .rebase = std.Io.Writer.unreachableRebase, + .drain = Io.Writer.unreachableDrain, + .rebase = Io.Writer.unreachableRebase, }, }; defer r.end = writer.end; diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index a7b16e1bed..6b6e4fa9f7 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -77,7 +77,7 @@ pub fn free(sdk: WindowsSdk, allocator: Allocator) void { /// and a version. Returns slice of version strings sorted in descending order. /// Caller owns result. fn iterateAndFilterByVersion( - iterator: *std.fs.Dir.Iterator, + iterator: *Io.Dir.Iterator, allocator: Allocator, prefix: []const u8, ) error{OutOfMemory}![][]const u8 { @@ -608,7 +608,7 @@ pub const Installation = struct { }; const MsvcLibDir = struct { - fn findInstancesDirViaSetup(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaSetup(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir { const vs_setup_key_path = "SOFTWARE\\Microsoft\\VisualStudio\\Setup"; const vs_setup_key = RegistryWtf8.openKey(windows.HKEY_LOCAL_MACHINE, vs_setup_key_path, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, @@ -633,7 +633,7 @@ const MsvcLibDir = struct { return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDirViaCLSID(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDirViaCLSID(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir { const setup_configuration_clsid = "{177f0c4a-1cd3-4de7-a32c-71dbbb9fa36d}"; const setup_config_key = RegistryWtf8.openKey(windows.HKEY_CLASSES_ROOT, "CLSID\\" ++ setup_configuration_clsid, .{}) catch |err| switch (err) { error.KeyNotFound => return error.PathNotFound, @@ -669,7 +669,7 @@ const MsvcLibDir = struct { return std.fs.openDirAbsolute(instances_path, .{ .iterate = true }) catch return error.PathNotFound; } - fn findInstancesDir(allocator: Allocator) error{ OutOfMemory, PathNotFound }!std.fs.Dir { + fn findInstancesDir(allocator: Allocator) error{ OutOfMemory, PathNotFound }!Io.Dir { // First, try getting the packages cache path from the registry. // This only seems to exist when the path is different from the default. method1: { diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 9ca0124f4f..443bdcc391 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -9582,7 +9582,7 @@ pub fn dump(b: *Builder) void { b.printToFile(stderr, &buffer) catch {}; } -pub fn printToFilePath(b: *Builder, io: Io, dir: std.fs.Dir, path: []const u8) !void { +pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void { var buffer: [4000]u8 = undefined; const file = try dir.createFile(io, path, .{}); defer file.close(io); diff --git a/lib/std/zip.zig b/lib/std/zip.zig index 9588651e7f..0ca77c98a1 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -7,6 +7,7 @@ const builtin = @import("builtin"); const is_le = builtin.target.cpu.arch.endian() == .little; const std = @import("std"); +const Io = std.Io; const File = std.Io.File; const Writer = std.Io.Writer; const Reader = std.Io.Reader; @@ -461,7 +462,7 @@ pub const Iterator = struct { stream: *File.Reader, options: ExtractOptions, filename_buf: []u8, - dest: std.fs.Dir, + dest: Io.Dir, ) !void { if (filename_buf.len < self.filename_len) return error.ZipInsufficientBuffer; @@ -650,7 +651,7 @@ pub const ExtractOptions = struct { }; /// Extract the zipped files to the given `dest` directory. -pub fn extract(dest: std.fs.Dir, fr: *File.Reader, options: ExtractOptions) !void { +pub fn extract(dest: Io.Dir, fr: *File.Reader, options: ExtractOptions) !void { if (options.verify_checksums) @panic("TODO unimplemented"); var iter = try Iterator.init(fr); diff --git a/src/Compilation.zig b/src/Compilation.zig index 582c9dff3c..d75cba5a11 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -446,7 +446,7 @@ pub const Path = struct { } /// Given a `Path`, returns the directory handle and sub path to be used to open the path. - pub fn openInfo(p: Path, dirs: Directories) struct { fs.Dir, []const u8 } { + pub fn openInfo(p: Path, dirs: Directories) struct { Io.Dir, []const u8 } { const dir = switch (p.root) { .none => { const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd); @@ -1872,7 +1872,7 @@ pub const CreateDiagnostic = union(enum) { pub const CreateCachePath = struct { which: enum { local, global }, sub: []const u8, - err: (fs.Dir.MakeError || fs.Dir.OpenError || fs.Dir.StatFileError), + err: (Io.Dir.MakeError || Io.Dir.OpenError || Io.Dir.StatFileError), }; pub fn format(diag: CreateDiagnostic, w: *Writer) Writer.Error!void { switch (diag) { diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index 0fca3a0ee3..abaa8fef73 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -214,7 +214,7 @@ pub const Repository = struct { pub fn checkout( repository: *Repository, io: Io, - worktree: std.fs.Dir, + worktree: Io.Dir, commit_oid: Oid, diagnostics: *Diagnostics, ) !void { @@ -231,7 +231,7 @@ pub const Repository = struct { fn checkoutTree( repository: *Repository, io: Io, - dir: std.fs.Dir, + dir: Io.Dir, tree_oid: Oid, current_path: []const u8, diagnostics: *Diagnostics, diff --git a/src/fmt.zig b/src/fmt.zig index 7bdc24054e..663d09e9cb 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -204,7 +204,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } } -fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) !void { +fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: Io.Dir, sub_path: []const u8) !void { fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), else => { @@ -219,7 +219,7 @@ fn fmtPathDir( fmt: *Fmt, file_path: []const u8, check_mode: bool, - parent_dir: fs.Dir, + parent_dir: Io.Dir, parent_sub_path: []const u8, ) !void { const io = fmt.io; @@ -257,7 +257,7 @@ fn fmtPathFile( fmt: *Fmt, file_path: []const u8, check_mode: bool, - dir: fs.Dir, + dir: Io.Dir, sub_path: []const u8, ) !void { const io = fmt.io; diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 66b032e0a9..49f6d3f7c7 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -400,7 +400,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try std.fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, @@ -816,7 +816,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try std.fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, @@ -1371,7 +1371,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { // regarding eliding redundant object -> object transformations. return error.NoObjectsToLink; }; - try fs.Dir.copyFile( + try Io.Dir.copyFile( the_object_path.root_dir.handle, the_object_path.sub_path, directory.handle, @@ -1692,6 +1692,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi } const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; const allocPrint = std.fmt.allocPrint; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 72a49c0c9e..93adc633ce 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3573,7 +3573,7 @@ pub fn getTarget(self: *const MachO) *const std.Target { /// into a new inode, remove the original file, and rename the copy to match /// the original file. This is super messy, but there doesn't seem any other /// way to please the XNU. -pub fn invalidateKernelCache(dir: fs.Dir, sub_path: []const u8) !void { +pub fn invalidateKernelCache(dir: Io.Dir, sub_path: []const u8) !void { const tracy = trace(@src()); defer tracy.end(); if (builtin.target.os.tag.isDarwin() and builtin.target.cpu.arch == .aarch64) { -- cgit v1.2.3 From f53248a40936ebc9aaf75ddbd16e67ebec05ab84 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Dec 2025 13:39:09 -0800 Subject: update all std.fs.cwd() to std.Io.Dir.cwd() --- lib/compiler/aro/aro/Compilation.zig | 8 +- lib/compiler/aro/aro/Driver.zig | 10 +-- lib/compiler/aro/aro/Parser.zig | 27 +++---- lib/compiler/aro/aro/Preprocessor.zig | 6 +- lib/compiler/aro/aro/Tokenizer.zig | 5 +- lib/compiler/aro/aro/Value.zig | 11 +-- lib/compiler/aro/main.zig | 2 +- lib/compiler/objcopy.zig | 4 +- lib/compiler/reduce.zig | 6 +- lib/compiler/resinator/cli.zig | 2 +- lib/compiler/resinator/compile.zig | 4 +- lib/compiler/resinator/main.zig | 22 +++--- lib/compiler/std-docs.zig | 2 +- lib/compiler/translate-c/main.zig | 8 +- lib/std/Build.zig | 10 +-- lib/std/Build/Cache.zig | 8 +- lib/std/Build/Step.zig | 17 ++-- lib/std/Build/Step/CheckFile.zig | 4 +- lib/std/Build/Step/ConfigHeader.zig | 8 +- lib/std/Build/Step/Options.zig | 15 ++-- lib/std/Build/Step/Run.zig | 2 +- lib/std/Build/Watch.zig | 16 ++-- lib/std/Io/File.zig | 8 ++ lib/std/Io/Threaded.zig | 9 +-- lib/std/Io/Writer.zig | 6 +- lib/std/Io/net/test.zig | 2 +- lib/std/Io/test.zig | 10 +-- lib/std/Thread.zig | 4 +- lib/std/crypto/Certificate/Bundle/macos.zig | 2 +- lib/std/crypto/codecs/asn1/test.zig | 4 +- lib/std/debug.zig | 20 ++--- lib/std/debug/ElfFile.zig | 2 +- lib/std/debug/MachOFile.zig | 2 +- lib/std/debug/SelfInfo/Elf.zig | 19 +++-- lib/std/debug/SelfInfo/MachO.zig | 2 +- lib/std/debug/SelfInfo/Windows.zig | 4 +- lib/std/dynamic_library.zig | 8 +- lib/std/fs/test.zig | 116 +++++++++++++--------------- lib/std/os/linux/IoUring.zig | 24 +++--- lib/std/os/linux/test.zig | 6 +- lib/std/os/windows.zig | 4 +- lib/std/posix.zig | 14 ++-- lib/std/posix/test.zig | 52 ++++++------- lib/std/process/Child.zig | 2 +- lib/std/std.zig | 2 +- lib/std/tar.zig | 14 ++-- lib/std/testing.zig | 2 +- lib/std/zig/LibCInstallation.zig | 12 +-- lib/std/zig/WindowsSdk.zig | 2 +- lib/std/zig/system.zig | 6 +- lib/std/zig/system/darwin/macos.zig | 7 +- lib/std/zip.zig | 4 +- src/Compilation.zig | 20 ++--- src/Package/Fetch.zig | 12 +-- src/Package/Fetch/git.zig | 12 +-- src/Zcu/PerThread.zig | 4 +- src/codegen/llvm.zig | 17 ++-- src/fmt.zig | 6 +- src/introspect.zig | 4 +- src/libs/freebsd.zig | 12 +-- src/libs/glibc.zig | 16 ++-- src/libs/mingw.zig | 17 ++-- src/libs/netbsd.zig | 12 +-- src/link/C.zig | 4 +- src/link/Coff.zig | 6 +- src/link/Elf.zig | 4 +- src/link/Lld.zig | 4 +- src/link/MachO.zig | 14 ++-- src/link/MachO/CodeSignature.zig | 2 +- src/link/SpirV.zig | 3 +- src/link/Wasm.zig | 4 +- src/main.zig | 36 ++++----- 72 files changed, 398 insertions(+), 377 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 09e4861d13..b3e4d5544d 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -2253,7 +2253,7 @@ test "addSourceFromBuffer" { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("path", str); @@ -2267,7 +2267,7 @@ test "addSourceFromBuffer" { var arena: std.heap.ArenaAllocator = .init(allocator); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); _ = try comp.addSourceFromBuffer("path", "spliced\\\nbuffer\n"); @@ -2313,7 +2313,7 @@ test "addSourceFromBuffer - exhaustive check for carriage return elimination" { var buf: [alphabet.len]u8 = @splat(alphabet[0]); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var source_count: u32 = 0; @@ -2341,7 +2341,7 @@ test "ignore BOM at beginning of file" { const Test = struct { fn run(arena: Allocator, buf: []const u8) !void { var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("file.c", buf); diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index f933e3ce52..fec3cea0f8 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1327,7 +1327,7 @@ fn processSource( const dep_file_name = try d.getDepFileName(source, writer_buf[0..std.fs.max_name_bytes]); const file = if (dep_file_name) |path| - d.comp.cwd.createFile(path, .{}) catch |er| + d.comp.cwd.createFile(io, path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, errorDescription(er) }) else Io.File.stdout(); @@ -1352,7 +1352,7 @@ fn processSource( } const file = if (d.output_name) |some| - d.comp.cwd.createFile(some, .{}) catch |er| + d.comp.cwd.createFile(io, some, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) }) else Io.File.stdout(); @@ -1405,7 +1405,7 @@ fn processSource( defer assembly.deinit(gpa); if (d.only_preprocess_and_compile) { - const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); defer out_file.close(io); @@ -1419,7 +1419,7 @@ fn processSource( // then assemble to out_file_name var assembly_name_buf: [std.fs.max_name_bytes]u8 = undefined; const assembly_out_file_name = try d.getRandomFilename(&assembly_name_buf, ".s"); - const out_file = d.comp.cwd.createFile(assembly_out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, assembly_out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ assembly_out_file_name, errorDescription(er) }); defer out_file.close(io); assembly.writeToFile(out_file) catch |er| @@ -1455,7 +1455,7 @@ fn processSource( }; defer obj.deinit(); - const out_file = d.comp.cwd.createFile(out_file_name, .{}) catch |er| + const out_file = d.comp.cwd.createFile(io, out_file_name, .{}) catch |er| return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); defer out_file.close(io); diff --git a/lib/compiler/aro/aro/Parser.zig b/lib/compiler/aro/aro/Parser.zig index 4a89e0d460..fc21ee4d0b 100644 --- a/lib/compiler/aro/aro/Parser.zig +++ b/lib/compiler/aro/aro/Parser.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; const Allocator = mem.Allocator; const assert = std.debug.assert; @@ -211,7 +212,7 @@ fn checkIdentifierCodepointWarnings(p: *Parser, codepoint: u21, loc: Source.Loca const prev_total = p.diagnostics.total; var sf = std.heap.stackFallback(1024, p.comp.gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); if (!char_info.isC99IdChar(codepoint)) { @@ -425,7 +426,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) if (p.diagnostics.effectiveKind(diagnostic) == .off) return; var sf = std.heap.stackFallback(1024, p.comp.gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); p.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory; @@ -447,7 +448,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) }, p.pp.expansionSlice(tok_i), true); } -fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !void { +fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void { var i: usize = 0; inline for (std.meta.fields(@TypeOf(args))) |arg_info| { const arg = @field(args, arg_info.name); @@ -476,13 +477,13 @@ fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !vo try w.writeAll(fmt[i..]); } -fn formatTokenId(w: *std.Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize { +fn formatTokenId(w: *Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize { const i = Diagnostics.templateIndex(w, fmt, "{tok_id}"); try w.writeAll(tok_id.symbol()); return i; } -fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) !usize { +fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usize { const i = Diagnostics.templateIndex(w, fmt, "{qt}"); try w.writeByte('\''); try qt.print(p.comp, w); @@ -501,7 +502,7 @@ fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) return i; } -fn formatResult(p: *Parser, w: *std.Io.Writer, fmt: []const u8, res: Result) !usize { +fn formatResult(p: *Parser, w: *Io.Writer, fmt: []const u8, res: Result) !usize { const i = Diagnostics.templateIndex(w, fmt, "{value}"); switch (res.val.opt_ref) { .none => try w.writeAll("(none)"), @@ -524,7 +525,7 @@ const Normalized = struct { return .{ .str = str }; } - pub fn format(ctx: Normalized, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Normalized, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{normalized}"); var it: std.unicode.Utf8Iterator = .{ .bytes = ctx.str, @@ -558,7 +559,7 @@ const Codepoint = struct { return .{ .codepoint = codepoint }; } - pub fn format(ctx: Codepoint, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Codepoint, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{codepoint}"); try w.print("{X:0>4}", .{ctx.codepoint}); return i; @@ -572,7 +573,7 @@ const Escaped = struct { return .{ .str = str }; } - pub fn format(ctx: Escaped, w: *std.Io.Writer, fmt: []const u8) !usize { + pub fn format(ctx: Escaped, w: *Io.Writer, fmt: []const u8) !usize { const i = Diagnostics.templateIndex(w, fmt, "{s}"); try std.zig.stringEscape(ctx.str, w); return i; @@ -1453,7 +1454,7 @@ fn decl(p: *Parser) Error!bool { return true; } -fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *std.Io.Writer.Allocating) !?[]const u8 { +fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *Io.Writer.Allocating) !?[]const u8 { const w = &allocating.writer; const cond = cond_node.get(&p.tree); @@ -1526,7 +1527,7 @@ fn staticAssert(p: *Parser) Error!bool { } else { if (!res.val.toBool(p.comp)) { var sf = std.heap.stackFallback(1024, gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); if (p.staticAssertMessage(res_node, str, &allocating) catch return error.OutOfMemory) |message| { @@ -9719,7 +9720,7 @@ fn primaryExpr(p: *Parser) Error!?Result { qt = some.qt; } else if (p.func.qt) |func_qt| { var sf = std.heap.stackFallback(1024, gpa); - var allocating: std.Io.Writer.Allocating = .init(sf.get()); + var allocating: Io.Writer.Allocating = .init(sf.get()); defer allocating.deinit(); func_qt.printNamed(p.tokSlice(p.func.name), p.comp, &allocating.writer) catch return error.OutOfMemory; @@ -10608,7 +10609,7 @@ test "Node locations" { const arena = arena_state.allocator(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); const file = try comp.addSourceFromBuffer("file.c", diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig index d47727cbf0..e8343dc83a 100644 --- a/lib/compiler/aro/aro/Preprocessor.zig +++ b/lib/compiler/aro/aro/Preprocessor.zig @@ -3900,7 +3900,7 @@ test "Preserve pragma tokens sometimes" { defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); try comp.addDefaultPragmaHandlers(); @@ -3967,7 +3967,7 @@ test "destringify" { var arena: std.heap.ArenaAllocator = .init(gpa); defer arena.deinit(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena.allocator(), std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var pp = Preprocessor.init(&comp, .default); defer pp.deinit(); @@ -4030,7 +4030,7 @@ test "Include guards" { const arena = arena_state.allocator(); var diagnostics: Diagnostics = .{ .output = .ignore }; - var comp = Compilation.init(gpa, arena, std.testing.io, &diagnostics, std.fs.cwd()); + var comp = Compilation.init(gpa, arena, std.testing.io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var pp = Preprocessor.init(&comp, .default); defer pp.deinit(); diff --git a/lib/compiler/aro/aro/Tokenizer.zig b/lib/compiler/aro/aro/Tokenizer.zig index c497c5ce82..198d49364a 100644 --- a/lib/compiler/aro/aro/Tokenizer.zig +++ b/lib/compiler/aro/aro/Tokenizer.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Compilation = @import("Compilation.zig"); @@ -2326,7 +2327,7 @@ test "Tokenizer fuzz test" { fn testOne(_: @This(), input_bytes: []const u8) anyerror!void { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const source = try comp.addSourceFromBuffer("fuzz.c", input_bytes); @@ -2351,7 +2352,7 @@ test "Tokenizer fuzz test" { fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, langopts: ?LangOpts) !void { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena.allocator(), std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); if (langopts) |provided| { comp.langopts = provided; diff --git a/lib/compiler/aro/aro/Value.zig b/lib/compiler/aro/aro/Value.zig index 25a2d1824f..14949ce03b 100644 --- a/lib/compiler/aro/aro/Value.zig +++ b/lib/compiler/aro/aro/Value.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; @@ -80,7 +81,7 @@ test "minUnsignedBits" { defer arena_state.deinit(); const arena = arena_state.allocator(); - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" }); comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query)); @@ -119,7 +120,7 @@ test "minSignedBits" { defer arena_state.deinit(); const arena = arena_state.allocator(); - var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, std.fs.cwd()); + var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, undefined, Io.Dir.cwd()); defer comp.deinit(); const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" }); comp.target = .fromZigTarget(try std.zig.system.resolveTargetQuery(std.testing.io, target_query)); @@ -1080,7 +1081,7 @@ const NestedPrint = union(enum) { }, }; -pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!void { +pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!void { try w.writeByte('&'); try w.writeAll(base); if (!offset.isZero(comp)) { @@ -1089,7 +1090,7 @@ pub fn printPointer(offset: Value, base: []const u8, comp: *const Compilation, w } } -pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!?NestedPrint { +pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!?NestedPrint { if (qt.is(comp, .bool)) { try w.writeAll(if (v.isZero(comp)) "false" else "true"); return null; @@ -1116,7 +1117,7 @@ pub fn print(v: Value, qt: QualType, comp: *const Compilation, w: *std.Io.Writer return null; } -pub fn printString(bytes: []const u8, qt: QualType, comp: *const Compilation, w: *std.Io.Writer) std.Io.Writer.Error!void { +pub fn printString(bytes: []const u8, qt: QualType, comp: *const Compilation, w: *Io.Writer) Io.Writer.Error!void { const size: Compilation.CharUnitSize = @enumFromInt(qt.childType(comp).sizeof(comp)); const without_null = bytes[0 .. bytes.len - @intFromEnum(size)]; try w.writeByte('"'); diff --git a/lib/compiler/aro/main.zig b/lib/compiler/aro/main.zig index 66c8add4a3..d1be1dbb21 100644 --- a/lib/compiler/aro/main.zig +++ b/lib/compiler/aro/main.zig @@ -59,7 +59,7 @@ pub fn main() u8 { } }, }; - var comp = Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |er| switch (er) { + var comp = Compilation.initDefault(gpa, arena, io, &diagnostics, Io.Dir.cwd()) catch |er| switch (er) { error.OutOfMemory => { std.debug.print("out of memory\n", .{}); if (fast_exit) process.exit(1); diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 485e644daa..e48f76a6a6 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -152,7 +152,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void defer threaded.deinit(); const io = threaded.io(); - const input_file = fs.cwd().openFile(input, .{}) catch |err| fatal("failed to open {s}: {t}", .{ input, err }); + const input_file = Io.Dir.cwd().openFile(input, .{}) catch |err| fatal("failed to open {s}: {t}", .{ input, err }); defer input_file.close(io); const stat = input_file.stat() catch |err| fatal("failed to stat {s}: {t}", .{ input, err }); @@ -180,7 +180,7 @@ fn cmdObjCopy(gpa: Allocator, arena: Allocator, args: []const []const u8) !void const mode = if (out_fmt != .elf or only_keep_debug) Io.File.default_mode else stat.mode; - var output_file = try fs.cwd().createFile(output, .{ .mode = mode }); + var output_file = try Io.Dir.cwd().createFile(io, output, .{ .mode = mode }); defer output_file.close(io); var out = output_file.writer(&output_buffer); diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index bbd3d172b4..d3f33ad81a 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -233,7 +233,7 @@ pub fn main() !void { } } - try std.fs.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); + try Io.Dir.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); // std.debug.print("trying this code:\n{s}\n", .{rendered.items}); const interestingness = try runCheck(arena, interestingness_argv.items); @@ -274,7 +274,7 @@ pub fn main() !void { fixups.clearRetainingCapacity(); rendered.clearRetainingCapacity(); try tree.render(gpa, &rendered.writer, fixups); - try std.fs.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); + try Io.Dir.cwd().writeFile(.{ .sub_path = root_source_file_path, .data = rendered.written() }); return std.process.cleanExit(); } @@ -398,7 +398,7 @@ fn transformationsToFixups( } fn parse(gpa: Allocator, file_path: []const u8) !Ast { - const source_code = std.fs.cwd().readFileAllocOptions( + const source_code = Io.Dir.cwd().readFileAllocOptions( file_path, gpa, .limited(std.math.maxInt(u32)), diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index bb54289e3e..ae4ece2968 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -2003,7 +2003,7 @@ test "maybeAppendRC" { // Create the file so that it's found. In this scenario, .rc should not get // appended. - var file = try tmp.dir.createFile("foo", .{}); + var file = try tmp.dir.createFile(io, "foo", .{}); file.close(io); try options.maybeAppendRC(tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig index 7dc77e5ee1..3e046a10c1 100644 --- a/lib/compiler/resinator/compile.zig +++ b/lib/compiler/resinator/compile.zig @@ -111,7 +111,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); } } - // Re-open the passed in cwd since we want to be able to close it (std.fs.cwd() shouldn't be closed) + // Re-open the passed in cwd since we want to be able to close it (Io.Dir.cwd() shouldn't be closed) const cwd_dir = options.cwd.openDir(".", .{}) catch |err| { try options.diagnostics.append(.{ .err = .failed_to_open_cwd, @@ -406,7 +406,7 @@ pub const Compiler = struct { // `/test.bin` relative to include paths and instead only treats it as // an absolute path. if (std.fs.path.isAbsolute(path)) { - const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); + const file = try utils.openFileNotDir(Io.Dir.cwd(), path, .{}); errdefer file.close(io); if (self.dependencies) |dependencies| { diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index c726a06cf4..416abc2ab7 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -67,7 +67,7 @@ pub fn main() !void { }, else => |e| return e, }; - try options.maybeAppendRC(std.fs.cwd()); + try options.maybeAppendRC(Io.Dir.cwd()); if (!zig_integration) { // print any warnings/notes @@ -141,7 +141,7 @@ pub fn main() !void { if (!zig_integration) std.debug.unlockStderrWriter(); } - var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd()); + var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd()); defer comp.deinit(); var argv: std.ArrayList([]const u8) = .empty; @@ -196,7 +196,7 @@ pub fn main() !void { }; }, .filename => |input_filename| { - break :full_input std.fs.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| { + break :full_input Io.Dir.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| { try error_handler.emitMessage(gpa, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) }); std.process.exit(1); }; @@ -212,7 +212,7 @@ pub fn main() !void { try output_file.writeAll(full_input); }, .filename => |output_filename| { - try std.fs.cwd().writeFile(.{ .sub_path = output_filename, .data = full_input }); + try Io.Dir.cwd().writeFile(.{ .sub_path = output_filename, .data = full_input }); }, } return; @@ -277,7 +277,7 @@ pub fn main() !void { const output_buffered_stream = res_stream_writer.interface(); compile(gpa, io, final_input, output_buffered_stream, .{ - .cwd = std.fs.cwd(), + .cwd = Io.Dir.cwd(), .diagnostics = &diagnostics, .source_mappings = &mapping_results.mappings, .dependencies = maybe_dependencies, @@ -294,7 +294,7 @@ pub fn main() !void { .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page, }) catch |err| switch (err) { error.ParseError, error.CompileError => { - try error_handler.emitDiagnostics(gpa, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings); + try error_handler.emitDiagnostics(gpa, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings); // Delete the output file on error res_stream.cleanupAfterError(io); std.process.exit(1); @@ -306,12 +306,12 @@ pub fn main() !void { // print any warnings/notes if (!zig_integration) { - diagnostics.renderToStdErr(std.fs.cwd(), final_input, mapping_results.mappings); + diagnostics.renderToStdErr(Io.Dir.cwd(), final_input, mapping_results.mappings); } // write the depfile if (options.depfile_path) |depfile_path| { - var depfile = std.fs.cwd().createFile(depfile_path, .{}) catch |err| { + var depfile = Io.Dir.cwd().createFile(io, depfile_path, .{}) catch |err| { try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) }); std.process.exit(1); }; @@ -440,7 +440,7 @@ const IoStream = struct { // Delete the output file on error file.close(io); // Failing to delete is not really a big deal, so swallow any errors - std.fs.cwd().deleteFile(self.name) catch {}; + Io.Dir.cwd().deleteFile(self.name) catch {}; }, .stdio, .memory, .closed => return, } @@ -457,8 +457,8 @@ const IoStream = struct { switch (source) { .filename => |filename| return .{ .file = switch (io) { - .input => try openFileNotDir(std.fs.cwd(), filename, .{}), - .output => try std.fs.cwd().createFile(filename, .{}), + .input => try openFileNotDir(Io.Dir.cwd(), filename, .{}), + .output => try Io.Dir.cwd().createFile(io, filename, .{}), }, }, .stdio => |file| return .{ .stdio = file }, diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index e4efac28cd..87c4da9faa 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -40,7 +40,7 @@ pub fn main() !void { const zig_exe_path = argv.next().?; const global_cache_path = argv.next().?; - var lib_dir = try std.fs.cwd().openDir(zig_lib_directory, .{}); + var lib_dir = try Io.Dir.cwd().openDir(zig_lib_directory, .{}); defer lib_dir.close(io); var listen_port: u16 = 0; diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index 830c70e424..d0a873fd78 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -47,7 +47,7 @@ pub fn main() u8 { }; defer diagnostics.deinit(); - var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |err| switch (err) { + var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, Io.Dir.cwd()) catch |err| switch (err) { error.OutOfMemory => { std.debug.print("ran out of memory initializing C compilation\n", .{}); if (fast_exit) process.exit(1); @@ -226,7 +226,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration const dep_file_name = try d.getDepFileName(source, out_buf[0..std.fs.max_name_bytes]); const file = if (dep_file_name) |path| - d.comp.cwd.createFile(path, .{}) catch |er| + d.comp.cwd.createFile(io, path, .{}) catch |er| return d.fatal("unable to create dependency file '{s}': {s}", .{ path, aro.Driver.errorDescription(er) }) else Io.File.stdout(); @@ -253,10 +253,10 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration if (d.output_name) |path| blk: { if (std.mem.eql(u8, path, "-")) break :blk; if (std.fs.path.dirname(path)) |dirname| { - std.fs.cwd().makePath(dirname) catch |err| + Io.Dir.cwd().makePath(dirname) catch |err| return d.fatal("failed to create path to '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); } - out_file = std.fs.cwd().createFile(path, .{}) catch |err| { + out_file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| { return d.fatal("failed to create output file '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); }; close_out_file = true; diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 7bfdbb6449..cc2f70fd2f 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1702,13 +1702,13 @@ pub fn addCheckFile( pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Dir.StatFileError)!void { const io = b.graph.io; if (b.verbose) log.info("truncate {s}", .{dest_path}); - const cwd = fs.cwd(); - var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) { + const cwd = Io.Dir.cwd(); + var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { error.FileNotFound => blk: { if (fs.path.dirname(dest_path)) |dirname| { try cwd.makePath(dirname); } - break :blk try cwd.createFile(dest_path, .{}); + break :blk try cwd.createFile(io, dest_path, .{}); }, else => |e| return e, }; @@ -1846,7 +1846,7 @@ pub fn runAllowFail( }; errdefer b.allocator.free(stdout); - const term = try child.wait(); + const term = try child.wait(io); switch (term) { .Exited => |code| { if (code != 0) { @@ -2193,7 +2193,7 @@ fn dependencyInner( const build_root: std.Build.Cache.Directory = .{ .path = build_root_string, - .handle = fs.cwd().openDir(build_root_string, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(build_root_string, .{}) catch |err| { std.debug.print("unable to open '{s}': {s}\n", .{ build_root_string, @errorName(err), }); diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index 42459c033d..fdcb2ab714 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -508,7 +508,7 @@ pub const Manifest = struct { // and `want_shared_lock` is set, a shared lock might be sufficient, so we'll // open with a shared lock instead. while (true) { - if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ + if (self.cache.manifest_dir.createFile(io, &manifest_file_path, .{ .read = true, .truncate = false, .lock = .exclusive, @@ -543,7 +543,7 @@ pub const Manifest = struct { return error.CacheCheckFailed; } - if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ + if (self.cache.manifest_dir.createFile(io, &manifest_file_path, .{ .read = true, .truncate = false, .lock = .exclusive, @@ -873,7 +873,7 @@ pub const Manifest = struct { if (man.want_refresh_timestamp) { man.want_refresh_timestamp = false; - var file = man.cache.manifest_dir.createFile("timestamp", .{ + var file = man.cache.manifest_dir.createFile(io, "timestamp", .{ .read = true, .truncate = true, }) catch |err| switch (err) { @@ -1324,7 +1324,7 @@ fn hashFile(file: Io.File, bin_digest: *[Hasher.mac_length]u8) Io.File.PReadErro fn testGetCurrentFileTimestamp(io: Io, dir: Io.Dir) !Io.Timestamp { const test_out_file = "test-filetimestamp.tmp"; - var file = try dir.createFile(test_out_file, .{ + var file = try dir.createFile(io, test_out_file, .{ .read = true, .truncate = true, }); diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 56ef32e8d8..2ec1c0ef31 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -401,6 +401,9 @@ pub fn evalZigProcess( web_server: ?*Build.WebServer, gpa: Allocator, ) !?Path { + const b = s.owner; + const io = b.graph.io; + // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); s.result_failed_command = try allocPrintCmd(gpa, null, argv); @@ -411,7 +414,7 @@ pub fn evalZigProcess( const result = zigProcessUpdate(s, zp, watch, web_server, gpa) catch |err| switch (err) { error.BrokenPipe => { // Process restart required. - const term = zp.child.wait() catch |e| { + const term = zp.child.wait(io) catch |e| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], e }); }; _ = term; @@ -427,7 +430,7 @@ pub fn evalZigProcess( if (s.result_error_msgs.items.len > 0 and result == null) { // Crash detected. - const term = zp.child.wait() catch |e| { + const term = zp.child.wait(io) catch |e| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], e }); }; s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0; @@ -439,9 +442,7 @@ pub fn evalZigProcess( return result; } assert(argv.len != 0); - const b = s.owner; const arena = b.allocator; - const io = b.graph.io; try handleChildProcUnsupported(s); try handleVerbose(s.owner, null, argv); @@ -478,7 +479,7 @@ pub fn evalZigProcess( zp.child.stdin.?.close(io); zp.child.stdin = null; - const term = zp.child.wait() catch |err| { + const term = zp.child.wait(io) catch |err| { return s.fail("unable to wait for {s}: {t}", .{ argv[0], err }); }; s.result_peak_rss = zp.child.resource_usage_statistics.getMaxRss() orelse 0; @@ -519,7 +520,7 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.MakePathStatus { const b = s.owner; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); - return std.fs.cwd().makePathStatus(dest_path) catch |err| + return Io.Dir.cwd().makePathStatus(dest_path) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); } @@ -895,7 +896,7 @@ pub fn addWatchInput(step: *Step, lazy_file: Build.LazyPath) Allocator.Error!voi try addWatchInputFromPath(step, .{ .root_dir = .{ .path = null, - .handle = std.fs.cwd(), + .handle = Io.Dir.cwd(), }, .sub_path = std.fs.path.dirname(path_string) orelse "", }, std.fs.path.basename(path_string)); @@ -920,7 +921,7 @@ pub fn addDirectoryWatchInput(step: *Step, lazy_directory: Build.LazyPath) Alloc try addDirectoryWatchInputFromPath(step, .{ .root_dir = .{ .path = null, - .handle = std.fs.cwd(), + .handle = Io.Dir.cwd(), }, .sub_path = path_string, }); diff --git a/lib/std/Build/Step/CheckFile.zig b/lib/std/Build/Step/CheckFile.zig index efeedc8b80..560b6ad050 100644 --- a/lib/std/Build/Step/CheckFile.zig +++ b/lib/std/Build/Step/CheckFile.zig @@ -3,7 +3,9 @@ //! TODO: generalize the code in std.testing.expectEqualStrings and make this //! CheckFile step produce those helpful diagnostics when there is not a match. const CheckFile = @This(); + const std = @import("std"); +const Io = std.Io; const Step = std.Build.Step; const fs = std.fs; const mem = std.mem; @@ -53,7 +55,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try step.singleUnchangingWatchInput(check_file.source); const src_path = check_file.source.getPath2(b, step); - const contents = fs.cwd().readFileAlloc(src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| { return step.fail("unable to read '{s}': {s}", .{ src_path, @errorName(err), }); diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index df2419764d..ea7d9d99ff 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -1,5 +1,7 @@ -const std = @import("std"); const ConfigHeader = @This(); + +const std = @import("std"); +const Io = std.Io; const Step = std.Build.Step; const Allocator = std.mem.Allocator; const Writer = std.Io.Writer; @@ -205,7 +207,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .autoconf_undef, .autoconf_at => |file_source| { try bw.writeAll(c_generated_line); const src_path = file_source.getPath2(b, step); - const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { return step.fail("unable to read autoconf input file '{s}': {s}", .{ src_path, @errorName(err), }); @@ -219,7 +221,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .cmake => |file_source| { try bw.writeAll(c_generated_line); const src_path = file_source.getPath2(b, step); - const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { + const contents = Io.Dir.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| { return step.fail("unable to read cmake input file '{s}': {s}", .{ src_path, @errorName(err), }); diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 9f5665e93a..1416e0e916 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -1,12 +1,13 @@ -const std = @import("std"); +const Options = @This(); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const fs = std.fs; const Step = std.Build.Step; const GeneratedFile = std.Build.GeneratedFile; const LazyPath = std.Build.LazyPath; -const Options = @This(); - pub const base_id: Step.Id = .options; step: Step, @@ -542,11 +543,11 @@ test Options { .cache = .{ .io = io, .gpa = arena.allocator(), - .manifest_dir = std.fs.cwd(), + .manifest_dir = Io.Dir.cwd(), }, .zig_exe = "test", .env_map = std.process.EnvMap.init(arena.allocator()), - .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() }, + .global_cache_root = .{ .path = "test", .handle = Io.Dir.cwd() }, .host = .{ .query = .{}, .result = try std.zig.system.resolveTargetQuery(io, .{}), @@ -557,8 +558,8 @@ test Options { var builder = try std.Build.create( &graph, - .{ .path = "test", .handle = std.fs.cwd() }, - .{ .path = "test", .handle = std.fs.cwd() }, + .{ .path = "test", .handle = Io.Dir.cwd() }, + .{ .path = "test", .handle = Io.Dir.cwd() }, &.{}, ); diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 7c54c8048e..af6bc20438 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1023,7 +1023,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, options, null); - const dep_file_dir = std.fs.cwd(); + const dep_file_dir = Io.Dir.cwd(); const dep_file_basename = dep_output_file.generated_file.getPath2(b, step); if (has_side_effects) try man.addDepFile(dep_file_dir, dep_file_basename) diff --git a/lib/std/Build/Watch.zig b/lib/std/Build/Watch.zig index ff06ad3ff3..f7ac47961e 100644 --- a/lib/std/Build/Watch.zig +++ b/lib/std/Build/Watch.zig @@ -122,7 +122,7 @@ const Os = switch (builtin.os.tag) { }) catch return error.NameTooLong; const stack_ptr: *std.os.linux.file_handle = @ptrCast(&file_handle_buffer); stack_ptr.handle_bytes = file_handle_buffer.len - @sizeOf(std.os.linux.file_handle); - try posix.name_to_handle_at(path.root_dir.handle.fd, adjusted_path, stack_ptr, mount_id, std.os.linux.AT.HANDLE_FID); + try posix.name_to_handle_at(path.root_dir.handle.handle, adjusted_path, stack_ptr, mount_id, std.os.linux.AT.HANDLE_FID); const stack_lfh: FileHandle = .{ .handle = stack_ptr }; return stack_lfh.clone(gpa); } @@ -222,7 +222,7 @@ const Os = switch (builtin.os.tag) { posix.fanotify_mark(fan_fd, .{ .ADD = true, .ONLYDIR = true, - }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| { + }, fan_mask, path.root_dir.handle.handle, path.subPathOrDot()) catch |err| { fatal("unable to watch {f}: {s}", .{ path, @errorName(err) }); }; } @@ -275,7 +275,7 @@ const Os = switch (builtin.os.tag) { posix.fanotify_mark(fan_fd, .{ .REMOVE = true, .ONLYDIR = true, - }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) { + }, fan_mask, path.root_dir.handle.handle, path.subPathOrDot()) catch |err| switch (err) { error.FileNotFound => {}, // Expected, harmless. else => |e| std.log.warn("unable to unwatch '{f}': {s}", .{ path, @errorName(e) }), }; @@ -353,7 +353,7 @@ const Os = switch (builtin.os.tag) { // The following code is a drawn out NtCreateFile call. (mostly adapted from Io.Dir.makeOpenDirAccessMaskW) // It's necessary in order to get the specific flags that are required when calling ReadDirectoryChangesW. var dir_handle: windows.HANDLE = undefined; - const root_fd = path.root_dir.handle.fd; + const root_fd = path.root_dir.handle.handle; const sub_path = path.subPathOrDot(); const sub_path_w = try windows.sliceToPrefixedFileW(root_fd, sub_path); const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; @@ -681,9 +681,9 @@ const Os = switch (builtin.os.tag) { if (!gop.found_existing) { const skip_open_dir = path.sub_path.len == 0; const dir_fd = if (skip_open_dir) - path.root_dir.handle.fd + path.root_dir.handle.handle else - posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| { + posix.openat(path.root_dir.handle.handle, path.sub_path, dir_open_flags, 0) catch |err| { fatal("failed to open directory {f}: {s}", .{ path, @errorName(err) }); }; // Empirically the dir has to stay open or else no events are triggered. @@ -750,7 +750,7 @@ const Os = switch (builtin.os.tag) { // to access that data via the dir_fd field. const path = w.dir_table.keys()[i]; const dir_fd = if (path.sub_path.len == 0) - path.root_dir.handle.fd + path.root_dir.handle.handle else handles.items(.dir_fd)[i]; assert(dir_fd != -1); @@ -761,7 +761,7 @@ const Os = switch (builtin.os.tag) { const last_dir_fd = fd: { const last_path = w.dir_table.keys()[handles.len - 1]; const last_dir_fd = if (last_path.sub_path.len == 0) - last_path.root_dir.handle.fd + last_path.root_dir.handle.handle else handles.items(.dir_fd)[handles.len - 1]; assert(last_dir_fd != -1); diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index 8e71f648e2..a9b4775772 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -527,6 +527,14 @@ pub fn writerStreaming(file: File, io: Io, buffer: []u8) Writer { return .initStreaming(file, io, buffer); } +/// Equivalent to creating a streaming writer, writing `bytes`, and then flushing. +pub fn writeStreamingAll(file: File, io: Io, bytes: []const u8) Writer.Error!void { + var index: usize = 0; + while (index < bytes.len) { + index += try io.vtable.fileWriteStreaming(io.userdata, file, &.{}, &.{bytes[index..]}, 1); + } +} + pub const LockError = error{ SystemResources, FileLocksUnsupported, diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index fb76002201..124f886515 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -2361,7 +2361,7 @@ fn dirCreateFilePosix( .NFILE => return error.SystemFdQuotaExceeded, .NODEV => return error.NoDevice, .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, + .SRCH => return error.FileNotFound, // Linux when accessing procfs. .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, @@ -2670,7 +2670,7 @@ fn dirOpenFilePosix( .NFILE => return error.SystemFdQuotaExceeded, .NODEV => return error.NoDevice, .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, + .SRCH => return error.FileNotFound, // Linux when opening procfs files. .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, @@ -3287,7 +3287,7 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b .NFILE => return error.SystemFdQuotaExceeded, .NODEV => return error.NoDevice, .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, + .SRCH => return error.FileNotFound, // Linux when accessing procfs. .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, @@ -5548,7 +5548,6 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: [][]u8) File. switch (e) { .INVAL => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err), - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => |err| { if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. @@ -5672,7 +5671,6 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: [][]u8, offs switch (e) { .INVAL => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err), - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => |err| { if (native_os == .wasi) return error.NotOpenForReading; // File operation on directory. @@ -6312,7 +6310,6 @@ fn fileWriteStreaming( switch (e) { .INVAL => return error.InvalidArgument, .FAULT => |err| return errnoBug(err), - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // Can be a race condition. .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 3f25bc6a26..63ae6d93a0 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2835,7 +2835,7 @@ test "discarding sendFile" { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [256]u8 = undefined; var file_writer: File.Writer = .init(file, &r_buffer); @@ -2857,7 +2857,7 @@ test "allocating sendFile" { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [2]u8 = undefined; var file_writer: File.Writer = .init(file, &r_buffer); @@ -2881,7 +2881,7 @@ test sendFileReading { var tmp_dir = testing.tmpDir(.{}); defer tmp_dir.cleanup(); - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); defer file.close(io); var r_buffer: [2]u8 = undefined; var file_writer: File.Writer = .init(file, &r_buffer); diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig index 5818f6c3f7..c9ed0d3284 100644 --- a/lib/std/Io/net/test.zig +++ b/lib/std/Io/net/test.zig @@ -278,7 +278,7 @@ test "listen on a unix socket, send bytes, receive bytes" { defer testing.allocator.free(socket_path); const socket_addr = try net.UnixAddress.init(socket_path); - defer std.fs.cwd().deleteFile(socket_path) catch {}; + defer Io.Dir.cwd().deleteFile(socket_path) catch {}; var server = try socket_addr.listen(io, .{}); defer server.socket.close(io); diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index 9f21fe50e7..e731dc18d7 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -27,7 +27,7 @@ test "write a file, read it, then delete it" { random.bytes(data[0..]); const tmp_file_name = "temp_test_file.txt"; { - var file = try tmp.dir.createFile(tmp_file_name, .{}); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); var file_writer = file.writer(&.{}); @@ -40,7 +40,7 @@ test "write a file, read it, then delete it" { { // Make sure the exclusive flag is honored. - try expectError(File.OpenError.PathAlreadyExists, tmp.dir.createFile(tmp_file_name, .{ .exclusive = true })); + try expectError(File.OpenError.PathAlreadyExists, tmp.dir.createFile(io, tmp_file_name, .{ .exclusive = true })); } { @@ -70,7 +70,7 @@ test "File seek ops" { const io = testing.io; const tmp_file_name = "temp_test_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); try file.writeAll(&([_]u8{0x55} ** 8192)); @@ -96,7 +96,7 @@ test "setEndPos" { defer tmp.cleanup(); const tmp_file_name = "temp_test_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); // Verify that the file size changes and the file offset is not moved @@ -121,7 +121,7 @@ test "updateTimes" { defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{ .read = true }); + var file = try tmp.dir.createFile(io, tmp_file_name, .{ .read = true }); defer file.close(io); const stat_old = try file.stat(); diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 102bb59415..8453bc4c81 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -208,7 +208,7 @@ pub fn setName(self: Thread, io: Io, name: []const u8) SetNameError!void { var buf: [32]u8 = undefined; const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); - const file = try std.fs.cwd().openFile(io, path, .{ .mode = .write_only }); + const file = try Io.Dir.cwd().openFile(io, path, .{ .mode = .write_only }); defer file.close(io); try file.writeAll(name); @@ -325,7 +325,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co var threaded: std.Io.Threaded = .init_single_threaded; const io = threaded.ioBasic(); - const file = try std.fs.cwd().openFile(io, path, .{}); + const file = try Io.Dir.cwd().openFile(io, path, .{}); defer file.close(io); var file_reader = file.readerStreaming(io, &.{}); diff --git a/lib/std/crypto/Certificate/Bundle/macos.zig b/lib/std/crypto/Certificate/Bundle/macos.zig index 473505ac51..444d8da675 100644 --- a/lib/std/crypto/Certificate/Bundle/macos.zig +++ b/lib/std/crypto/Certificate/Bundle/macos.zig @@ -19,7 +19,7 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanM _ = io; // TODO migrate file system to use std.Io for (keychain_paths) |keychain_path| { - const bytes = std.fs.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { + const bytes = Io.Dir.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { error.StreamTooLong => return error.FileTooBig, else => |e| return e, }; diff --git a/lib/std/crypto/codecs/asn1/test.zig b/lib/std/crypto/codecs/asn1/test.zig index ff854fcbde..3dbedb9f80 100644 --- a/lib/std/crypto/codecs/asn1/test.zig +++ b/lib/std/crypto/codecs/asn1/test.zig @@ -73,8 +73,8 @@ test AllTypes { try std.testing.expectEqualSlices(u8, encoded, buf); // Use this to update test file. - // const dir = try std.fs.cwd().openDir("lib/std/crypto/asn1", .{}); - // var file = try dir.createFile(path, .{}); + // const dir = try Io.Dir.cwd().openDir("lib/std/crypto/asn1", .{}); + // var file = try dir.createFile(io, path, .{}); // defer file.close(io); // try file.writeAll(buf); } diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 97741ecb40..5df0eef2d5 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -60,7 +60,7 @@ pub const cpu_context = @import("debug/cpu_context.zig"); /// }; /// /// Only required if `can_unwind == true`. Unwinds a single stack frame, returning the frame's /// /// return address, or 0 if the end of the stack has been reached. -/// pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) SelfInfoError!usize; +/// pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) SelfInfoError!usize; /// ``` pub const SelfInfo = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "SelfInfo")) root.debug.SelfInfo @@ -558,9 +558,9 @@ pub fn defaultPanic( stderr.print("{s}\n", .{msg}) catch break :trace; if (@errorReturnTrace()) |t| if (t.index > 0) { - stderr.writeAll("error return context:\n") catch break :trace; + stderr.writeStreamingAll("error return context:\n") catch break :trace; writeStackTrace(t, stderr, tty_config) catch break :trace; - stderr.writeAll("\nstack trace:\n") catch break :trace; + stderr.writeStreamingAll("\nstack trace:\n") catch break :trace; }; writeCurrentStackTrace(.{ .first_address = first_trace_addr orelse @returnAddress(), @@ -575,7 +575,7 @@ pub fn defaultPanic( // A panic happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - File.stderr().writeAll("aborting due to recursive panic\n") catch {}; + File.stderr().writeStreamingAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. } @@ -960,7 +960,7 @@ const StackIterator = union(enum) { }, }; - fn next(it: *StackIterator) Result { + fn next(it: *StackIterator, io: Io) Result { switch (it.*) { .ctx_first => |context_ptr| { // After the first frame, start actually unwinding. @@ -976,7 +976,7 @@ const StackIterator = union(enum) { .di => |*unwind_context| { const di = getSelfDebugInfo() catch unreachable; const di_gpa = getDebugInfoAllocator(); - const ret_addr = di.unwindFrame(di_gpa, unwind_context) catch |err| { + const ret_addr = di.unwindFrame(di_gpa, io, unwind_context) catch |err| { const pc = unwind_context.pc; const fp = unwind_context.getFp(); it.* = .{ .fp = fp }; @@ -1297,7 +1297,7 @@ test printLineFromFile { aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{}); + const file = try test_dir.dir.createFile(io, "line_overlaps_page_boundary.zig", .{}); defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "line_overlaps_page_boundary.zig" }); defer gpa.free(path); @@ -1316,7 +1316,7 @@ test printLineFromFile { aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{}); + const file = try test_dir.dir.createFile(io, "file_ends_on_page_boundary.zig", .{}); defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); defer gpa.free(path); @@ -1330,7 +1330,7 @@ test printLineFromFile { aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{}); + const file = try test_dir.dir.createFile(io, "very_long_first_line_spanning_multiple_pages.zig", .{}); defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); defer gpa.free(path); @@ -1356,7 +1356,7 @@ test printLineFromFile { aw.clearRetainingCapacity(); } { - const file = try test_dir.dir.createFile("file_of_newlines.zig", .{}); + const file = try test_dir.dir.createFile(io, "file_of_newlines.zig", .{}); defer file.close(io); const path = try fs.path.join(gpa, &.{ test_dir_path, "file_of_newlines.zig" }); defer gpa.free(path); diff --git a/lib/std/debug/ElfFile.zig b/lib/std/debug/ElfFile.zig index a0f1188ade..203ee8effb 100644 --- a/lib/std/debug/ElfFile.zig +++ b/lib/std/debug/ElfFile.zig @@ -375,7 +375,7 @@ fn loadSeparateDebugFile( args: anytype, ) Allocator.Error!?[]align(std.heap.page_size_min) const u8 { const path = try std.fmt.allocPrint(arena, fmt, args); - const elf_file = std.fs.cwd().openFile(io, path, .{}) catch return null; + const elf_file = Io.Dir.cwd().openFile(io, path, .{}) catch return null; defer elf_file.close(io); const result = loadInner(arena, elf_file, opt_crc) catch |err| switch (err) { diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig index ae904c0aec..18126a1c29 100644 --- a/lib/std/debug/MachOFile.zig +++ b/lib/std/debug/MachOFile.zig @@ -512,7 +512,7 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { /// Uses `mmap` to map the file at `path` into memory. fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { - const file = std.fs.cwd().openFile(io, path, .{}) catch |err| switch (err) { + const file = Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 213389bf04..6ed18bcb80 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -29,13 +29,12 @@ pub fn deinit(si: *SelfInfo, gpa: Allocator) void { } pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!std.debug.Symbol { - _ = io; const module = try si.findModule(gpa, address, .exclusive); defer si.rwlock.unlock(); const vaddr = address - module.load_offset; - const loaded_elf = try module.getLoadedElf(gpa); + const loaded_elf = try module.getLoadedElf(gpa, io); if (loaded_elf.file.dwarf) |*dwarf| { if (!loaded_elf.scanned_dwarf) { dwarf.open(gpa, native_endian) catch |err| switch (err) { @@ -180,7 +179,7 @@ comptime { } } pub const UnwindContext = Dwarf.SelfUnwinder; -pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error!usize { +pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, io: Io, context: *UnwindContext) Error!usize { comptime assert(can_unwind); { @@ -201,7 +200,7 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error @memset(si.unwind_cache.?, .empty); } - const unwind_sections = try module.getUnwindSections(gpa); + const unwind_sections = try module.getUnwindSections(gpa, io); for (unwind_sections) |*unwind| { if (context.computeRules(gpa, unwind, module.load_offset, null)) |entry| { entry.populate(si.unwind_cache.?); @@ -261,12 +260,12 @@ const Module = struct { }; /// Assumes we already hold an exclusive lock. - fn getUnwindSections(mod: *Module, gpa: Allocator) Error![]Dwarf.Unwind { - if (mod.unwind == null) mod.unwind = loadUnwindSections(mod, gpa); + fn getUnwindSections(mod: *Module, gpa: Allocator, io: Io) Error![]Dwarf.Unwind { + if (mod.unwind == null) mod.unwind = loadUnwindSections(mod, gpa, io); const us = &(mod.unwind.? catch |err| return err); return us.buf[0..us.len]; } - fn loadUnwindSections(mod: *Module, gpa: Allocator) Error!UnwindSections { + fn loadUnwindSections(mod: *Module, gpa: Allocator, io: Io) Error!UnwindSections { var us: UnwindSections = .{ .buf = undefined, .len = 0, @@ -284,7 +283,7 @@ const Module = struct { } else { // There is no `.eh_frame_hdr` section. There may still be an `.eh_frame` or `.debug_frame` // section, but we'll have to load the binary to get at it. - const loaded = try mod.getLoadedElf(gpa); + const loaded = try mod.getLoadedElf(gpa, io); // If both are present, we can't just pick one -- the info could be split between them. // `.debug_frame` is likely to be the more complete section, so we'll prioritize that one. if (loaded.file.debug_frame) |*debug_frame| { @@ -325,7 +324,7 @@ const Module = struct { } fn loadElf(mod: *Module, gpa: Allocator, io: Io) Error!LoadedElf { const load_result = if (mod.name.len > 0) res: { - var file = std.fs.cwd().openFile(io, mod.name, .{}) catch return error.MissingDebugInfo; + var file = Io.Dir.cwd().openFile(io, mod.name, .{}) catch return error.MissingDebugInfo; defer file.close(io); break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(mod.name)); } else res: { @@ -334,7 +333,7 @@ const Module = struct { else => return error.ReadFailed, }; defer gpa.free(path); - var file = std.fs.cwd().openFile(io, path, .{}) catch return error.MissingDebugInfo; + var file = Io.Dir.cwd().openFile(io, path, .{}) catch return error.MissingDebugInfo; defer file.close(io); break :res std.debug.ElfFile.load(gpa, file, mod.build_id, &.native(path)); }; diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index 15da616f3b..db8e5334e6 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -616,7 +616,7 @@ test { /// Uses `mmap` to map the file at `path` into memory. fn mapDebugInfoFile(io: Io, path: []const u8) ![]align(std.heap.page_size_min) const u8 { - const file = std.fs.cwd().openFile(io, path, .{}) catch |err| switch (err) { + const file = Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) { error.FileNotFound => return error.MissingDebugInfo, else => return error.ReadFailed, }; diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index f0ac30cca2..9874efd497 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -432,7 +432,7 @@ const Module = struct { break :pdb null; }; const pdb_file_open_result = if (fs.path.isAbsolute(path)) res: { - break :res std.fs.cwd().openFile(io, path, .{}); + break :res Io.Dir.cwd().openFile(io, path, .{}); } else res: { const self_dir = std.process.executableDirPathAlloc(io, gpa) catch |err| switch (err) { error.OutOfMemory, error.Unexpected => |e| return e, @@ -441,7 +441,7 @@ const Module = struct { defer gpa.free(self_dir); const abs_path = try fs.path.join(gpa, &.{ self_dir, path }); defer gpa.free(abs_path); - break :res std.fs.cwd().openFile(io, abs_path, .{}); + break :res Io.Dir.cwd().openFile(io, abs_path, .{}); }; const pdb_file = pdb_file_open_result catch |err| switch (err) { error.FileNotFound, error.IsDir => break :pdb null, diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 7db177ad70..a1801d00d0 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -160,7 +160,7 @@ pub const ElfDynLib = struct { fn openPath(path: []const u8, io: Io) !Io.Dir { if (path.len == 0) return error.NotDir; var parts = std.mem.tokenizeScalar(u8, path, '/'); - var parent = if (path[0] == '/') try std.fs.cwd().openDir("/", .{}) else std.fs.cwd(); + var parent = if (path[0] == '/') try Io.Dir.cwd().openDir("/", .{}) else Io.Dir.cwd(); while (parts.next()) |part| { const child = try parent.openDir(part, .{}); parent.close(io); @@ -174,7 +174,7 @@ pub const ElfDynLib = struct { while (paths.next()) |p| { var dir = openPath(p) catch continue; defer dir.close(io); - const fd = posix.openat(dir.fd, file_name, .{ + const fd = posix.openat(dir.handle, file_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true, }, 0) catch continue; @@ -184,9 +184,9 @@ pub const ElfDynLib = struct { } fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?posix.fd_t { - var dir = std.fs.cwd().openDir(dir_path, .{}) catch return null; + var dir = Io.Dir.cwd().openDir(dir_path, .{}) catch return null; defer dir.close(io); - return posix.openat(dir.fd, file_name, .{ + return posix.openat(dir.handle, file_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true, }, 0) catch null; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index f4bdecf89d..aab86d40a6 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -46,7 +46,7 @@ const PathType = enum { // The final path may not actually exist which would cause realpath to fail. // So instead, we get the path of the dir and join it with the relative path. var fd_path_buf: [fs.max_path_bytes]u8 = undefined; - const dir_path = try std.os.getFdPath(dir.fd, &fd_path_buf); + const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); return fs.path.joinZ(allocator, &.{ dir_path, relative_path }); } }.transform, @@ -55,7 +55,7 @@ const PathType = enum { // Any drive absolute path (C:\foo) can be converted into a UNC path by // using '127.0.0.1' as the server name and '$' as the share name. var fd_path_buf: [fs.max_path_bytes]u8 = undefined; - const dir_path = try std.os.getFdPath(dir.fd, &fd_path_buf); + const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); const windows_path_type = windows.getWin32PathType(u8, dir_path); switch (windows_path_type) { .unc_absolute => return fs.path.joinZ(allocator, &.{ dir_path, relative_path }), @@ -256,7 +256,7 @@ fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, sy const target_path_w = try std.unicode.wtf8ToWtf16LeAlloc(allocator, target_path); defer allocator.free(target_path_w); // Calling the W functions directly requires the path to be NT-prefixed - const symlink_path_w = try std.os.windows.sliceToPrefixedFileW(dir.fd, symlink_path); + const symlink_path_w = try std.os.windows.sliceToPrefixedFileW(dir.handle, symlink_path); const wtf16_buffer = try allocator.alloc(u16, target_path_w.len); defer allocator.free(wtf16_buffer); const actual = try dir.readLinkW(symlink_path_w.span(), wtf16_buffer); @@ -288,9 +288,11 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { var symlink: Dir = switch (builtin.target.os.tag) { .windows => windows_symlink: { - const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.fd, "symlink"); + const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.handle, "symlink"); - var handle: windows.HANDLE = undefined; + var result: Dir = .{ + .handle = undefined, + }; const path_len_bytes = @as(u16, @intCast(sub_path_w.span().len * 2)); var nt_name = windows.UNICODE_STRING{ @@ -300,26 +302,16 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { }; var attr: windows.OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), - .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.fd, - .Attributes = .{}, + .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.handle, + .Attributes = 0, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; var io_status_block: windows.IO_STATUS_BLOCK = undefined; const rc = windows.ntdll.NtCreateFile( - &handle, - .{ - .SPECIFIC = .{ .FILE_DIRECTORY = .{ - .READ_EA = true, - .TRAVERSE = true, - .READ_ATTRIBUTES = true, - } }, - .STANDARD = .{ - .RIGHTS = .READ, - .SYNCHRONIZE = true, - }, - }, + &result.handle, + windows.STANDARD_RIGHTS_READ | windows.FILE_READ_ATTRIBUTES | windows.FILE_READ_EA | windows.SYNCHRONIZE | windows.FILE_TRAVERSE, &attr, &io_status_block, null, @@ -337,7 +329,7 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { ); switch (rc) { - .SUCCESS => break :windows_symlink .{ .fd = handle }, + .SUCCESS => break :windows_symlink .{ .fd = result.handle }, else => return windows.unexpectedStatus(rc), } }, @@ -351,8 +343,8 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { .ACCMODE = .RDONLY, .CLOEXEC = true, }; - const fd = try posix.openatZ(ctx.dir.fd, &sub_path_c, flags, 0); - break :linux_symlink Dir{ .fd = fd }; + const fd = try posix.openatZ(ctx.dir.handle, &sub_path_c, flags, 0); + break :linux_symlink .{ .handle = fd }; }, else => unreachable, }; @@ -456,7 +448,7 @@ test "openDirAbsolute" { test "openDir cwd parent '..'" { const io = testing.io; - var dir = fs.cwd().openDir("..", .{}) catch |err| { + var dir = Io.Dir.cwd().openDir("..", .{}) catch |err| { if (native_os == .wasi and err == error.PermissionDenied) { return; // This is okay. WASI disallows escaping from the fs sandbox } @@ -534,7 +526,7 @@ test "Dir.Iterator" { defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -570,7 +562,7 @@ test "Dir.Iterator many entries" { var buf: [4]u8 = undefined; // Enough to store "1024". while (i < num) : (i += 1) { const name = try std.fmt.bufPrint(&buf, "{}", .{i}); - const file = try tmp_dir.dir.createFile(name, .{}); + const file = try tmp_dir.dir.createFile(io, name, .{}); file.close(io); } @@ -603,7 +595,7 @@ test "Dir.Iterator twice" { defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -638,7 +630,7 @@ test "Dir.Iterator reset" { defer tmp_dir.cleanup(); // First, create a couple of entries to iterate over. - const file = try tmp_dir.dir.createFile("some_file", .{}); + const file = try tmp_dir.dir.createFile(io, "some_file", .{}); file.close(io); try tmp_dir.dir.makeDir("some_dir"); @@ -769,7 +761,7 @@ test "readFileAlloc" { var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); - var file = try tmp_dir.dir.createFile("test_file", .{ .read = true }); + var file = try tmp_dir.dir.createFile(io, "test_file", .{ .read = true }); defer file.close(io); const buf1 = try tmp_dir.dir.readFileAlloc("test_file", testing.allocator, .limited(1024)); @@ -843,7 +835,7 @@ test "directory operations on files" { const test_file_name = try ctx.transformPath("test_file"); - var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); + var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); file.close(io); try testing.expectError(error.PathAlreadyExists, ctx.dir.makeDir(test_file_name)); @@ -876,7 +868,7 @@ test "file operations on directories" { try ctx.dir.makeDir(test_dir_name); - try testing.expectError(error.IsDir, ctx.dir.createFile(test_dir_name, .{})); + try testing.expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); try testing.expectError(error.IsDir, ctx.dir.deleteFile(test_dir_name)); switch (native_os) { .dragonfly, .netbsd => { @@ -969,7 +961,7 @@ test "Dir.rename files" { // Renaming files const test_file_name = try ctx.transformPath("test_file"); const renamed_test_file_name = try ctx.transformPath("test_file_renamed"); - var file = try ctx.dir.createFile(test_file_name, .{ .read = true }); + var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); file.close(io); try ctx.dir.rename(test_file_name, renamed_test_file_name); @@ -983,7 +975,7 @@ test "Dir.rename files" { // Rename to existing file succeeds const existing_file_path = try ctx.transformPath("existing_file"); - var existing_file = try ctx.dir.createFile(existing_file_path, .{ .read = true }); + var existing_file = try ctx.dir.createFile(io, existing_file_path, .{ .read = true }); existing_file.close(io); try ctx.dir.rename(renamed_test_file_name, existing_file_path); @@ -1017,7 +1009,7 @@ test "Dir.rename directories" { var dir = try ctx.dir.openDir(test_dir_renamed_path, .{}); // Put a file in the directory - var file = try dir.createFile("test_file", .{ .read = true }); + var file = try dir.createFile(io, "test_file", .{ .read = true }); file.close(io); dir.close(io); @@ -1070,7 +1062,7 @@ test "Dir.rename directory onto non-empty dir" { try ctx.dir.makeDir(test_dir_path); var target_dir = try ctx.dir.makeOpenPath(target_dir_path, .{}); - var file = try target_dir.createFile("test_file", .{ .read = true }); + var file = try target_dir.createFile(io, "test_file", .{ .read = true }); file.close(io); target_dir.close(io); @@ -1094,7 +1086,7 @@ test "Dir.rename file <-> dir" { const test_file_path = try ctx.transformPath("test_file"); const test_dir_path = try ctx.transformPath("test_dir"); - var file = try ctx.dir.createFile(test_file_path, .{ .read = true }); + var file = try ctx.dir.createFile(io, test_file_path, .{ .read = true }); file.close(io); try ctx.dir.makeDir(test_dir_path); try testing.expectError(error.IsDir, ctx.dir.rename(test_file_path, test_dir_path)); @@ -1115,7 +1107,7 @@ test "rename" { // Renaming files const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; - var file = try tmp_dir1.dir.createFile(test_file_name, .{ .read = true }); + var file = try tmp_dir1.dir.createFile(io, test_file_name, .{ .read = true }); file.close(io); try fs.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name); @@ -1149,7 +1141,7 @@ test "renameAbsolute" { // Renaming files const test_file_name = "test_file"; const renamed_test_file_name = "test_file_renamed"; - var file = try tmp_dir.dir.createFile(test_file_name, .{ .read = true }); + var file = try tmp_dir.dir.createFile(io, test_file_name, .{ .read = true }); file.close(io); try fs.renameAbsolute( try fs.path.join(allocator, &.{ base_path, test_file_name }), @@ -1454,7 +1446,7 @@ test "writev, readv" { var write_vecs: [2][]const u8 = .{ line1, line2 }; var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; - var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); + var src_file = try tmp.dir.createFile(io, "test.txt", .{ .read = true }); defer src_file.close(io); var writer = src_file.writerStreaming(&.{}); @@ -1484,7 +1476,7 @@ test "pwritev, preadv" { var buf2: [line2.len]u8 = undefined; var read_vecs: [2][]u8 = .{ &buf2, &buf1 }; - var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); + var src_file = try tmp.dir.createFile(io, "test.txt", .{ .read = true }); defer src_file.close(io); var writer = src_file.writer(&.{}); @@ -1584,14 +1576,14 @@ test "sendfile" { const line2 = "second line\n"; var vecs = [_][]const u8{ line1, line2 }; - var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); + var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); defer src_file.close(io); { var fw = src_file.writer(&.{}); try fw.interface.writeVecAll(&vecs); } - var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); + var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); defer dest_file.close(io); const header1 = "header1\n"; @@ -1627,12 +1619,12 @@ test "sendfile with buffered data" { var dir = try tmp.dir.openDir("os_test_tmp", .{}); defer dir.close(io); - var src_file = try dir.createFile("sendfile1.txt", .{ .read = true }); + var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); defer src_file.close(io); try src_file.writeAll("AAAABBBB"); - var dest_file = try dir.createFile("sendfile2.txt", .{ .read = true }); + var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); defer dest_file.close(io); var src_buffer: [32]u8 = undefined; @@ -1718,10 +1710,10 @@ test "open file with exclusive nonblocking lock twice" { const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); } }.impl); @@ -1735,10 +1727,10 @@ test "open file with shared and exclusive nonblocking lock" { const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); } }.impl); @@ -1752,10 +1744,10 @@ test "open file with exclusive and shared nonblocking lock" { const io = ctx.io; const filename = try ctx.transformPath("file_nonblocking_lock_test.txt"); - const file1 = try ctx.dir.createFile(filename, .{ .lock = .exclusive, .lock_nonblocking = true }); + const file1 = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); defer file1.close(io); - const file2 = ctx.dir.createFile(filename, .{ .lock = .shared, .lock_nonblocking = true }); + const file2 = ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); try testing.expectError(error.WouldBlock, file2); } }.impl); @@ -1769,13 +1761,13 @@ test "open file with exclusive lock twice, make sure second lock waits" { const io = ctx.io; const filename = try ctx.transformPath("file_lock_test.txt"); - const file = try ctx.dir.createFile(filename, .{ .lock = .exclusive }); + const file = try ctx.dir.createFile(io, filename, .{ .lock = .exclusive }); errdefer file.close(io); const S = struct { fn checkFn(dir: *Io.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { started.set(); - const file1 = try dir.createFile(path, .{ .lock = .exclusive }); + const file1 = try dir.createFile(io, path, .{ .lock = .exclusive }); locked.set(); file1.close(io); @@ -1847,13 +1839,13 @@ test "read from locked file" { const filename = try ctx.transformPath("read_lock_file_test.txt"); { - const f = try ctx.dir.createFile(filename, .{ .read = true }); + const f = try ctx.dir.createFile(io, filename, .{ .read = true }); defer f.close(io); var buffer: [1]u8 = undefined; _ = try f.read(&buffer); } { - const f = try ctx.dir.createFile(filename, .{ + const f = try ctx.dir.createFile(io, filename, .{ .read = true, .lock = .exclusive, }); @@ -2037,7 +2029,7 @@ test "'.' and '..' in Io.Dir functions" { var created_subdir = try ctx.dir.openDir(subdir_path, .{}); created_subdir.close(io); - const created_file = try ctx.dir.createFile(file_path, .{}); + const created_file = try ctx.dir.createFile(io, file_path, .{}); created_file.close(io); try ctx.dir.access(file_path, .{}); @@ -2103,7 +2095,7 @@ test "chmod" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - const file = try tmp.dir.createFile("test_file", .{ .mode = 0o600 }); + const file = try tmp.dir.createFile(io, "test_file", .{ .mode = 0o600 }); defer file.close(io); try testing.expectEqual(@as(File.Mode, 0o600), (try file.stat()).mode & 0o7777); @@ -2127,7 +2119,7 @@ test "chown" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - const file = try tmp.dir.createFile("test_file", .{}); + const file = try tmp.dir.createFile(io, "test_file", .{}); defer file.close(io); try file.chown(null, null); @@ -2228,7 +2220,7 @@ test "read file non vectored" { const contents = "hello, world!\n"; - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); defer file.close(io); { var file_writer: File.Writer = .init(file, &.{}); @@ -2260,7 +2252,7 @@ test "seek keeping partial buffer" { const contents = "0123456789"; - const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true }); + const file = try tmp_dir.dir.createFile(io, "input.txt", .{ .read = true }); defer file.close(io); { var file_writer: File.Writer = .init(file, &.{}); @@ -2321,7 +2313,7 @@ test "seekTo flushes buffered data" { const contents = "data"; - const file = try tmp.dir.createFile("seek.bin", .{ .read = true }); + const file = try tmp.dir.createFile(io, "seek.bin", .{ .read = true }); defer file.close(io); { var buf: [16]u8 = undefined; @@ -2350,7 +2342,7 @@ test "File.Writer sendfile with buffered contents" { try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" }); const in = try tmp_dir.dir.openFile(io, "a", .{}); defer in.close(io); - const out = try tmp_dir.dir.createFile("b", .{}); + const out = try tmp_dir.dir.createFile(io, "b", .{}); defer out.close(io); var in_buf: [2]u8 = undefined; @@ -2397,7 +2389,7 @@ test "readlinkat" { // create a symbolic link if (native_os == .windows) { std.os.windows.CreateSymbolicLink( - tmp.dir.fd, + tmp.dir.handle, &[_]u16{ 'l', 'i', 'n', 'k' }, &[_:0]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, false, @@ -2407,7 +2399,7 @@ test "readlinkat" { else => return err, }; } else { - try posix.symlinkat("file.txt", tmp.dir.fd, "link"); + try posix.symlinkat("file.txt", tmp.dir.handle, "link"); } // read the link diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index c7d3f35d40..0972a302da 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -1991,7 +1991,7 @@ test "writev/fsync/readv" { defer tmp.cleanup(); const path = "test_io_uring_writev_fsync_readv"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); + const file = try tmp.dir.createFile(io, path, .{ .read = true, .truncate = true }); defer file.close(io); const fd = file.handle; @@ -2062,7 +2062,7 @@ test "write/read" { var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const path = "test_io_uring_write_read"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); + const file = try tmp.dir.createFile(io, path, .{ .read = true, .truncate = true }); defer file.close(io); const fd = file.handle; @@ -2110,12 +2110,12 @@ test "splice/read" { var tmp = std.testing.tmpDir(.{}); const path_src = "test_io_uring_splice_src"; - const file_src = try tmp.dir.createFile(path_src, .{ .read = true, .truncate = true }); + const file_src = try tmp.dir.createFile(io, path_src, .{ .read = true, .truncate = true }); defer file_src.close(io); const fd_src = file_src.handle; const path_dst = "test_io_uring_splice_dst"; - const file_dst = try tmp.dir.createFile(path_dst, .{ .read = true, .truncate = true }); + const file_dst = try tmp.dir.createFile(io, path_dst, .{ .read = true, .truncate = true }); defer file_dst.close(io); const fd_dst = file_dst.handle; @@ -2185,7 +2185,7 @@ test "write_fixed/read_fixed" { defer tmp.cleanup(); const path = "test_io_uring_write_read_fixed"; - const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true }); + const file = try tmp.dir.createFile(io, path, .{ .read = true, .truncate = true }); defer file.close(io); const fd = file.handle; @@ -2306,7 +2306,7 @@ test "close" { defer tmp.cleanup(); const path = "test_io_uring_close"; - const file = try tmp.dir.createFile(path, .{}); + const file = try tmp.dir.createFile(io, path, .{}); errdefer file.close(io); const sqe_close = try ring.close(0x44444444, file.handle); @@ -2652,7 +2652,7 @@ test "fallocate" { defer tmp.cleanup(); const path = "test_io_uring_fallocate"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .mode = 0o666 }); defer file.close(io); try testing.expectEqual(@as(u64, 0), (try file.stat()).size); @@ -2699,7 +2699,7 @@ test "statx" { var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); const path = "test_io_uring_statx"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .mode = 0o666 }); defer file.close(io); try testing.expectEqual(@as(u64, 0), (try file.stat()).size); @@ -2969,7 +2969,7 @@ test "renameat" { // Write old file with data - const old_file = try tmp.dir.createFile(old_path, .{ .truncate = true, .mode = 0o666 }); + const old_file = try tmp.dir.createFile(io, old_path, .{ .truncate = true, .mode = 0o666 }); defer old_file.close(io); try old_file.writeAll("hello"); @@ -3028,7 +3028,7 @@ test "unlinkat" { // Write old file with data - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .mode = 0o666 }); defer file.close(io); // Submit unlinkat @@ -3125,7 +3125,7 @@ test "symlinkat" { const path = "test_io_uring_symlinkat"; const link_path = "test_io_uring_symlinkat_link"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .mode = 0o666 }); defer file.close(io); // Submit symlinkat @@ -3177,7 +3177,7 @@ test "linkat" { // Write file with data - const first_file = try tmp.dir.createFile(first_path, .{ .truncate = true, .mode = 0o666 }); + const first_file = try tmp.dir.createFile(io, first_path, .{ .truncate = true, .mode = 0o666 }); defer first_file.close(io); try first_file.writeAll("hello"); diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 39606ddfac..d7cfb4e138 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -18,7 +18,7 @@ test "fallocate" { defer tmp.cleanup(); const path = "test_fallocate"; - const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 }); + const file = try tmp.dir.createFile(io, path, .{ .truncate = true, .mode = 0o666 }); defer file.close(io); try expect((try file.stat()).size == 0); @@ -85,7 +85,7 @@ test "statx" { defer tmp.cleanup(); const tmp_file_name = "just_a_temporary_file.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); var buf: linux.Statx = undefined; @@ -121,7 +121,7 @@ test "fadvise" { defer tmp.cleanup(); const tmp_file_name = "temp_posix_fadvise.txt"; - var file = try tmp.dir.createFile(tmp_file_name, .{}); + var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); var buf: [2048]u8 = undefined; diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 6b5b678b20..ba5282256f 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -4639,8 +4639,8 @@ pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) Wtf16ToPrefixedFileWE break :path_to_get path; } // We can also skip GetFinalPathNameByHandle if the handle matches - // the handle returned by fs.cwd() - if (dir.? == std.fs.cwd().fd) { + // the handle returned by Io.Dir.cwd() + if (dir.? == Io.Dir.cwd().fd) { break :path_to_get path; } // At this point, we know we have a relative path that had too many diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 392987ec50..f4aa970413 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -15,15 +15,16 @@ //! deal with the exception. const builtin = @import("builtin"); -const root = @import("root"); +const native_os = builtin.os.tag; + const std = @import("std.zig"); +const Io = std.Io; const mem = std.mem; const fs = std.fs; -const max_path_bytes = fs.max_path_bytes; +const max_path_bytes = std.fs.max_path_bytes; const maxInt = std.math.maxInt; const cast = std.math.cast; const assert = std.debug.assert; -const native_os = builtin.os.tag; const page_size_min = std.heap.page_size_min; test { @@ -797,7 +798,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .CANCELED => return error.Canceled, .BADF => return error.NotOpenForReading, // Can be a race condition. @@ -917,7 +917,6 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { .INTR => continue, .INVAL => return error.InvalidArgument, .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // can be a race condition. .DESTADDRREQ => unreachable, // `connect` was never called. @@ -985,7 +984,8 @@ pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t { .NFILE => return error.SystemFdQuotaExceeded, .NODEV => return error.NoDevice, .NOENT => return error.FileNotFound, - .SRCH => return error.ProcessNotFound, + // Can happen on Linux when opening procfs files. + .SRCH => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, @@ -1560,7 +1560,7 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void { pub fn mkdirW(dir_path_w: []const u16, mode: mode_t) MakeDirError!void { _ = mode; const sub_dir_handle = windows.OpenFile(dir_path_w, .{ - .dir = fs.cwd().fd, + .dir = Io.Dir.cwd().handle, .access_mask = .{ .STANDARD = .{ .SYNCHRONIZE = true }, .GENERIC = .{ .READ = true }, diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 0071a72a26..dc63be6e14 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -148,7 +148,7 @@ test "linkat with different directories" { try tmp.dir.writeFile(.{ .sub_path = target_name, .data = "example" }); // Test 1: link from file in subdir back up to target in parent directory - try posix.linkat(tmp.dir.fd, target_name, subdir.fd, link_name, 0); + try posix.linkat(tmp.dir.handle, target_name, subdir.handle, link_name, 0); const efd = try tmp.dir.openFile(io, target_name, .{}); defer efd.close(io); @@ -164,7 +164,7 @@ test "linkat with different directories" { } // Test 2: remove link - try posix.unlinkat(subdir.fd, link_name, 0); + try posix.unlinkat(subdir.handle, link_name, 0); _, const elink = try getLinkInfo(efd.handle); try testing.expectEqual(@as(posix.nlink_t, 1), elink); } @@ -373,7 +373,7 @@ test "mmap" { // Create a file used for testing mmap() calls with a file descriptor { - const file = try tmp.dir.createFile(test_out_file, .{}); + const file = try tmp.dir.createFile(io, test_out_file, .{}); defer file.close(io); var stream = file.writer(&.{}); @@ -444,7 +444,7 @@ test "fcntl" { const test_out_file = "os_tmp_test"; - const file = try tmp.dir.createFile(test_out_file, .{}); + const file = try tmp.dir.createFile(io, test_out_file, .{}); defer file.close(io); // Note: The test assumes createFile opens the file with CLOEXEC @@ -495,7 +495,7 @@ test "fsync" { defer tmp.cleanup(); const test_out_file = "os_tmp_test"; - const file = try tmp.dir.createFile(test_out_file, .{}); + const file = try tmp.dir.createFile(io, test_out_file, .{}); defer file.close(io); try posix.fsync(file.handle); @@ -617,7 +617,7 @@ test "dup & dup2" { defer tmp.cleanup(); { - var file = try tmp.dir.createFile("os_dup_test", .{}); + var file = try tmp.dir.createFile(io, "os_dup_test", .{}); defer file.close(io); var duped = Io.File{ .handle = try posix.dup(file.handle) }; @@ -659,7 +659,7 @@ test "writev longer than IOV_MAX" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var file = try tmp.dir.createFile("pwritev", .{}); + var file = try tmp.dir.createFile(io, "pwritev", .{}); defer file.close(io); const iovecs = [_]posix.iovec_const{.{ .base = "a", .len = 1 }} ** (posix.IOV_MAX + 1); @@ -684,7 +684,7 @@ test "POSIX file locking with fcntl" { defer tmp.cleanup(); // Create a temporary lock file - var file = try tmp.dir.createFile("lock", .{ .read = true }); + var file = try tmp.dir.createFile(io, "lock", .{ .read = true }); defer file.close(io); try file.setEndPos(2); const fd = file.handle; @@ -881,7 +881,7 @@ test "isatty" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var file = try tmp.dir.createFile("foo", .{}); + var file = try tmp.dir.createFile(io, "foo", .{}); defer file.close(io); try expectEqual(posix.isatty(file.handle), false); @@ -893,7 +893,7 @@ test "pread with empty buffer" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var file = try tmp.dir.createFile("pread_empty", .{ .read = true }); + var file = try tmp.dir.createFile(io, "pread_empty", .{ .read = true }); defer file.close(io); const bytes = try a.alloc(u8, 0); @@ -909,7 +909,7 @@ test "write with empty buffer" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var file = try tmp.dir.createFile("write_empty", .{}); + var file = try tmp.dir.createFile(io, "write_empty", .{}); defer file.close(io); const bytes = try a.alloc(u8, 0); @@ -925,7 +925,7 @@ test "pwrite with empty buffer" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var file = try tmp.dir.createFile("pwrite_empty", .{}); + var file = try tmp.dir.createFile(io, "pwrite_empty", .{}); defer file.close(io); const bytes = try a.alloc(u8, 0); @@ -965,35 +965,35 @@ test "fchmodat smoke test" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try expectError(error.FileNotFound, posix.fchmodat(tmp.dir.fd, "regfile", 0o666, 0)); + try expectError(error.FileNotFound, posix.fchmodat(tmp.dir.handle, "regfile", 0o666, 0)); const fd = try posix.openat( - tmp.dir.fd, + tmp.dir.handle, "regfile", .{ .ACCMODE = .WRONLY, .CREAT = true, .EXCL = true, .TRUNC = true }, 0o644, ); posix.close(fd); - try posix.symlinkat("regfile", tmp.dir.fd, "symlink"); - const sym_mode = try getFileMode(tmp.dir.fd, "symlink"); + try posix.symlinkat("regfile", tmp.dir.handle, "symlink"); + const sym_mode = try getFileMode(tmp.dir.handle, "symlink"); - try posix.fchmodat(tmp.dir.fd, "regfile", 0o640, 0); - try expectMode(tmp.dir.fd, "regfile", 0o640); - try posix.fchmodat(tmp.dir.fd, "regfile", 0o600, posix.AT.SYMLINK_NOFOLLOW); - try expectMode(tmp.dir.fd, "regfile", 0o600); + try posix.fchmodat(tmp.dir.handle, "regfile", 0o640, 0); + try expectMode(tmp.dir.handle, "regfile", 0o640); + try posix.fchmodat(tmp.dir.handle, "regfile", 0o600, posix.AT.SYMLINK_NOFOLLOW); + try expectMode(tmp.dir.handle, "regfile", 0o600); - try posix.fchmodat(tmp.dir.fd, "symlink", 0o640, 0); - try expectMode(tmp.dir.fd, "regfile", 0o640); - try expectMode(tmp.dir.fd, "symlink", sym_mode); + try posix.fchmodat(tmp.dir.handle, "symlink", 0o640, 0); + try expectMode(tmp.dir.handle, "regfile", 0o640); + try expectMode(tmp.dir.handle, "symlink", sym_mode); var test_link = true; - posix.fchmodat(tmp.dir.fd, "symlink", 0o600, posix.AT.SYMLINK_NOFOLLOW) catch |err| switch (err) { + posix.fchmodat(tmp.dir.handle, "symlink", 0o600, posix.AT.SYMLINK_NOFOLLOW) catch |err| switch (err) { error.OperationNotSupported => test_link = false, else => |e| return e, }; if (test_link) - try expectMode(tmp.dir.fd, "symlink", 0o600); - try expectMode(tmp.dir.fd, "regfile", 0o640); + try expectMode(tmp.dir.handle, "symlink", 0o600); + try expectMode(tmp.dir.handle, "regfile", 0o640); } const CommonOpenFlags = packed struct { diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index b774303901..33faeef061 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -677,7 +677,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); if (self.cwd_dir) |cwd| { - posix.fchdir(cwd.fd) catch |err| forkChildErrReport(err_pipe[1], err); + posix.fchdir(cwd.handle) catch |err| forkChildErrReport(err_pipe[1], err); } else if (self.cwd) |cwd| { posix.chdir(cwd) catch |err| forkChildErrReport(err_pipe[1], err); } diff --git a/lib/std/std.zig b/lib/std/std.zig index 106811859b..1690c0575c 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -114,7 +114,7 @@ pub const options: Options = if (@hasDecl(root, "std_options")) root.std_options pub const Options = struct { enable_segfault_handler: bool = debug.default_enable_segfault_handler, - /// Function used to implement `std.fs.cwd` for WASI. + /// Function used to implement `std.Io.Dir.cwd` for WASI. wasiCwd: fn () os.wasi.fd_t = os.defaultWasiCwd, /// The current log level. diff --git a/lib/std/tar.zig b/lib/std/tar.zig index d861314fec..8a0bbb342f 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -610,7 +610,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp } }, .file => { - if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| { + if (createDirAndFile(io, dir, file_name, fileMode(file.mode, options))) |fs_file| { defer fs_file.close(io); var file_writer = fs_file.writer(&file_contents_buffer); try it.streamRemaining(file, &file_writer.interface); @@ -638,12 +638,12 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp } } -fn createDirAndFile(dir: Io.Dir, file_name: []const u8, mode: Io.File.Mode) !Io.File { - const fs_file = dir.createFile(file_name, .{ .exclusive = true, .mode = mode }) catch |err| { +fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mode) !Io.File { + const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { try dir.makePath(dir_name); - return try dir.createFile(file_name, .{ .exclusive = true, .mode = mode }); + return try dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }); } } return err; @@ -880,9 +880,9 @@ test "create file and symlink" { var root = testing.tmpDir(.{}); defer root.cleanup(); - var file = try createDirAndFile(root.dir, "file1", default_mode); + var file = try createDirAndFile(io, root.dir, "file1", default_mode); file.close(io); - file = try createDirAndFile(root.dir, "a/b/c/file2", default_mode); + file = try createDirAndFile(io, root.dir, "a/b/c/file2", default_mode); file.close(io); createDirAndSymlink(root.dir, "a/b/c/file2", "symlink1") catch |err| { @@ -894,7 +894,7 @@ test "create file and symlink" { // Danglink symlnik, file created later try createDirAndSymlink(root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); - file = try createDirAndFile(root.dir, "g/h/i/file4", default_mode); + file = try createDirAndFile(io, root.dir, "g/h/i/file4", default_mode); file.close(io); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 19038543a6..99d67ec132 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -628,7 +628,7 @@ pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { var sub_path: [TmpDir.sub_path_len]u8 = undefined; _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - const cwd = std.fs.cwd(); + const cwd = Io.Dir.cwd(); var cache_dir = cwd.makeOpenPath(".zig-cache", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); defer cache_dir.close(io); diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index c8bde2ab02..80317850df 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -57,7 +57,7 @@ pub fn parse( } } - const contents = try std.fs.cwd().readFileAlloc(libc_file, allocator, .limited(std.math.maxInt(usize))); + const contents = try Io.Dir.cwd().readFileAlloc(libc_file, allocator, .limited(std.math.maxInt(usize))); defer allocator.free(contents); var it = std.mem.tokenizeScalar(u8, contents, '\n'); @@ -337,7 +337,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F // search in reverse order const search_path_untrimmed = search_paths.items[search_paths.items.len - path_i - 1]; const search_path = std.mem.trimStart(u8, search_path_untrimmed, " "); - var search_dir = fs.cwd().openDir(search_path, .{}) catch |err| switch (err) { + var search_dir = Io.Dir.cwd().openDir(search_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -392,7 +392,7 @@ fn findNativeIncludeDirWindows( result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -440,7 +440,7 @@ fn findNativeCrtDirWindows( result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -508,7 +508,7 @@ fn findNativeKernel32LibDir( result_buf.shrinkAndFree(0); try result_buf.print("{s}\\Lib\\{s}\\um\\{s}", .{ install.path, install.version, arch_sub_dir }); - var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -544,7 +544,7 @@ fn findNativeMsvcIncludeDir( const dir_path = try fs.path.join(allocator, &[_][]const u8{ up2, "include" }); errdefer allocator.free(dir_path); - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { + var dir = Io.Dir.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index 6b6e4fa9f7..dca474020a 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -828,7 +828,7 @@ const MsvcLibDir = struct { try lib_dir_buf.appendSlice("VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"); var default_tools_version_buf: [512]u8 = undefined; - const default_tools_version_contents = std.fs.cwd().readFile(lib_dir_buf.items, &default_tools_version_buf) catch { + const default_tools_version_contents = Io.Dir.cwd().readFile(lib_dir_buf.items, &default_tools_version_buf) catch { return error.PathNotFound; }; var tokenizer = std.mem.tokenizeAny(u8, default_tools_version_contents, " \r\n"); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index d3bafc16f2..9fa0546c3b 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -1,11 +1,12 @@ const builtin = @import("builtin"); +const native_endian = builtin.cpu.arch.endian(); + const std = @import("../std.zig"); const mem = std.mem; const elf = std.elf; const fs = std.fs; const assert = std.debug.assert; const Target = std.Target; -const native_endian = builtin.cpu.arch.endian(); const posix = std.posix; const Io = std.Io; @@ -69,7 +70,7 @@ pub fn getExternalExecutor( if (os_match and cpu_ok) native: { if (options.link_libc) { if (candidate.dynamic_linker.get()) |candidate_dl| { - fs.cwd().access(candidate_dl, .{}) catch { + Io.Dir.cwd().access(candidate_dl, .{}) catch { bad_result = .{ .bad_dl = candidate_dl }; break :native; }; @@ -710,6 +711,7 @@ fn abiAndDynamicLinkerFromFile( error.SystemResources, error.FileSystem, error.SymLinkLoop, + error.Canceled, error.Unexpected, => |e| return e, }; diff --git a/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig index 9bb4e34e3b..4ff6846a09 100644 --- a/lib/std/zig/system/darwin/macos.zig +++ b/lib/std/zig/system/darwin/macos.zig @@ -1,9 +1,10 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const mem = std.mem; const testing = std.testing; - const Target = std.Target; /// Detect macOS version. @@ -54,7 +55,7 @@ pub fn detect(target_os: *Target.Os) !void { // approx. 4 times historical file size var buf: [2048]u8 = undefined; - if (std.fs.cwd().readFile(path, &buf)) |bytes| { + if (Io.Dir.cwd().readFile(path, &buf)) |bytes| { if (parseSystemVersion(bytes)) |ver| { // never return non-canonical `10.(16+)` if (!(ver.major == 10 and ver.minor >= 16)) { diff --git a/lib/std/zip.zig b/lib/std/zip.zig index 0ca77c98a1..9d08847092 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -564,9 +564,9 @@ pub const Iterator = struct { defer parent_dir.close(io); const basename = std.fs.path.basename(filename); - break :blk try parent_dir.createFile(basename, .{ .exclusive = true }); + break :blk try parent_dir.createFile(io, basename, .{ .exclusive = true }); } - break :blk try dest.createFile(filename, .{ .exclusive = true }); + break :blk try dest.createFile(io, filename, .{ .exclusive = true }); }; defer out_file.close(io); var out_file_buffer: [1024]u8 = undefined; diff --git a/src/Compilation.zig b/src/Compilation.zig index 24b994f608..5f15ef5f74 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -450,7 +450,7 @@ pub const Path = struct { const dir = switch (p.root) { .none => { const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd); - return .{ fs.cwd(), cwd_sub_path }; + return .{ Io.Dir.cwd(), cwd_sub_path }; }, .zig_lib => dirs.zig_lib.handle, .global_cache => dirs.global_cache.handle, @@ -723,7 +723,7 @@ pub const Directories = struct { pub fn deinit(dirs: *Directories, io: Io) void { // The local and global caches could be the same. - const close_local = dirs.local_cache.handle.fd != dirs.global_cache.handle.fd; + const close_local = dirs.local_cache.handle.handle != dirs.global_cache.handle.handle; dirs.global_cache.handle.close(io); if (close_local) dirs.local_cache.handle.close(io); @@ -814,7 +814,7 @@ pub const Directories = struct { return .{ .path = if (std.mem.eql(u8, name, ".")) null else name, .handle = .{ - .fd = preopens.find(name) orelse fatal("WASI preopen not found: '{s}'", .{name}), + .handle = preopens.find(name) orelse fatal("WASI preopen not found: '{s}'", .{name}), }, }; } @@ -824,8 +824,8 @@ pub const Directories = struct { }; const nonempty_path = if (path.len == 0) "." else path; const handle_or_err = switch (thing) { - .@"zig lib" => fs.cwd().openDir(nonempty_path, .{}), - .@"global cache", .@"local cache" => fs.cwd().makeOpenPath(nonempty_path, .{}), + .@"zig lib" => Io.Dir.cwd().openDir(nonempty_path, .{}), + .@"global cache", .@"local cache" => Io.Dir.cwd().makeOpenPath(nonempty_path, .{}), }; return .{ .path = if (path.len == 0) null else path, @@ -1104,7 +1104,7 @@ pub const CObject = struct { const source_line = source_line: { if (diag.src_loc.offset == 0 or diag.src_loc.column == 0) break :source_line 0; - const file = fs.cwd().openFile(io, file_name, .{}) catch break :source_line 0; + const file = Io.Dir.cwd().openFile(io, file_name, .{}) catch break :source_line 0; defer file.close(io); var buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &buffer); @@ -1179,7 +1179,7 @@ pub const CObject = struct { }; var buffer: [1024]u8 = undefined; - const file = try fs.cwd().openFile(io, path, .{}); + const file = try Io.Dir.cwd().openFile(io, path, .{}); defer file.close(io); var file_reader = file.reader(io, &buffer); var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface }); @@ -2109,7 +2109,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, }, }; // These correspond to std.zig.Server.Message.PathPrefix. - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(options.dirs.zig_lib); cache.addPrefix(options.dirs.local_cache); cache.addPrefix(options.dirs.global_cache); @@ -5220,7 +5220,7 @@ fn createDepFile( binfile: Cache.Path, ) anyerror!void { var buf: [4096]u8 = undefined; - var af = try std.fs.cwd().atomicFile(depfile, .{ .write_buffer = &buf }); + var af = try Io.Dir.cwd().atomicFile(depfile, .{ .write_buffer = &buf }); defer af.deinit(); comp.writeDepFile(binfile, &af.file_writer.interface) catch return af.file_writer.err.?; @@ -5284,7 +5284,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { }; } - var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| { + var tar_file = out_dir.createFile(io, "sources.tar", .{}) catch |err| { return comp.lockAndSetMiscFailure( .docs_copy, "unable to create '{f}/sources.tar': {s}", diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 3bd05120ff..8a30529bc5 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -383,14 +383,14 @@ pub fn run(f: *Fetch) RunError!void { }, .remote => |remote| remote, .path_or_url => |path_or_url| { - if (fs.cwd().openDir(path_or_url, .{ .iterate = true })) |dir| { + if (Io.Dir.cwd().openDir(path_or_url, .{ .iterate = true })) |dir| { var resource: Resource = .{ .dir = dir }; return f.runResource(path_or_url, &resource, null); } else |dir_err| { var server_header_buffer: [init_resource_buffer_size]u8 = undefined; const file_err = if (dir_err == error.NotDir) e: { - if (fs.cwd().openFile(io, path_or_url, .{})) |file| { + if (Io.Dir.cwd().openFile(io, path_or_url, .{})) |file| { var resource: Resource = .{ .file = file.reader(io, &server_header_buffer) }; return f.runResource(path_or_url, &resource, null); } else |err| break :e err; @@ -1303,7 +1303,7 @@ fn unzip( const random_integer = std.crypto.random.int(u64); zip_path[prefix.len..][0..random_len].* = std.fmt.hex(random_integer); - break cache_root.handle.createFile(&zip_path, .{ + break cache_root.handle.createFile(io, &zip_path, .{ .exclusive = true, .read = true, }) catch |err| switch (err) { @@ -1365,7 +1365,7 @@ fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!U { var pack_dir = try out_dir.makeOpenPath(".git", .{}); defer pack_dir.close(io); - var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); + var pack_file = try pack_dir.createFile(io, "pkg.pack", .{ .read = true }); defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = b: { @@ -1376,7 +1376,7 @@ fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!U break :b pack_file_writer.moveToReader(io); }; - var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); + var index_file = try pack_dir.createFile(io, "pkg.idx", .{ .read = true }); defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); @@ -2235,7 +2235,7 @@ test "set executable bit based on file content" { fn saveEmbedFile(io: Io, comptime tarball_name: []const u8, dir: Io.Dir) !void { //const tarball_name = "duplicate_paths_excluded.tar.gz"; const tarball_content = @embedFile("Fetch/testdata/" ++ tarball_name); - var tmp_file = try dir.createFile(tarball_name, .{}); + var tmp_file = try dir.createFile(io, tarball_name, .{}); defer tmp_file.close(io); try tmp_file.writeAll(tarball_content); } diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index ccae9440e2..7b08a89cae 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -264,7 +264,7 @@ pub const Repository = struct { try repository.odb.seekOid(entry.oid); const file_object = try repository.odb.readObject(); if (file_object.type != .blob) return error.InvalidFile; - var file = dir.createFile(entry.name, .{ .exclusive = true }) catch |e| { + var file = dir.createFile(io, entry.name, .{ .exclusive = true }) catch |e| { const file_name = try std.fs.path.join(diagnostics.allocator, &.{ current_path, entry.name }); errdefer diagnostics.allocator.free(file_name); try diagnostics.errors.append(diagnostics.allocator, .{ .unable_to_create_file = .{ @@ -1584,14 +1584,14 @@ fn runRepositoryTest(io: Io, comptime format: Oid.Format, head_commit: []const u var git_dir = testing.tmpDir(.{}); defer git_dir.cleanup(); - var pack_file = try git_dir.dir.createFile("testrepo.pack", .{ .read = true }); + var pack_file = try git_dir.dir.createFile(io, "testrepo.pack", .{ .read = true }); defer pack_file.close(io); try pack_file.writeAll(testrepo_pack); var pack_file_buffer: [2000]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); - var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true }); + var index_file = try git_dir.dir.createFile(io, "testrepo.idx", .{ .read = true }); defer index_file.close(io); var index_file_buffer: [2000]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); @@ -1714,20 +1714,20 @@ pub fn main() !void { const format = std.meta.stringToEnum(Oid.Format, args[1]) orelse return error.InvalidFormat; - var pack_file = try std.fs.cwd().openFile(io, args[2], .{}); + var pack_file = try Io.Dir.cwd().openFile(io, args[2], .{}); defer pack_file.close(io); var pack_file_buffer: [4096]u8 = undefined; var pack_file_reader = pack_file.reader(io, &pack_file_buffer); const commit = try Oid.parse(format, args[3]); - var worktree = try std.fs.cwd().makeOpenPath(args[4], .{}); + var worktree = try Io.Dir.cwd().makeOpenPath(args[4], .{}); defer worktree.close(io); var git_dir = try worktree.makeOpenPath(".git", .{}); defer git_dir.close(io); std.debug.print("Starting index...\n", .{}); - var index_file = try git_dir.createFile("idx", .{ .read = true }); + var index_file = try git_dir.createFile(io, "idx", .{ .read = true }); defer index_file.close(io); var index_file_buffer: [4096]u8 = undefined; var index_file_writer = index_file.writer(&index_file_buffer); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 45b1302138..9a75b2096e 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -170,7 +170,7 @@ pub fn updateFile( // version. Likewise if we're working on AstGen and another process asks for // the cached file, they'll get it. const cache_file = while (true) { - break zir_dir.createFile(&hex_digest, .{ + break zir_dir.createFile(io, &hex_digest, .{ .read = true, .truncate = false, .lock = lock, @@ -196,7 +196,7 @@ pub fn updateFile( cache_directory, }); } - break zir_dir.createFile(&hex_digest, .{ + break zir_dir.createFile(io, &hex_digest, .{ .read = true, .truncate = false, .lock = lock, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index cb4fe0459f..4fc58c2c4b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1,19 +1,22 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const log = std.log.scoped(.codegen); const math = std.math; const DW = std.dwarf; - const Builder = std.zig.llvm.Builder; + +const build_options = @import("build_options"); const llvm = if (build_options.have_llvm) @import("llvm/bindings.zig") else @compileError("LLVM unavailable"); + const link = @import("../link.zig"); const Compilation = @import("../Compilation.zig"); -const build_options = @import("build_options"); const Zcu = @import("../Zcu.zig"); const InternPool = @import("../InternPool.zig"); const Package = @import("../Package.zig"); @@ -964,7 +967,7 @@ pub const Object = struct { if (std.mem.eql(u8, path, "-")) { o.builder.dump(); } else { - o.builder.printToFilePath(std.fs.cwd(), path) catch |err| { + o.builder.printToFilePath(Io.Dir.cwd(), path) catch |err| { log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); }; } @@ -978,7 +981,7 @@ pub const Object = struct { o.builder.clearAndFree(); if (options.pre_bc_path) |path| { - var file = std.fs.cwd().createFile(path, .{}) catch |err| + var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); defer file.close(io); @@ -991,7 +994,7 @@ pub const Object = struct { options.post_ir_path == null and options.post_bc_path == null) return; if (options.post_bc_path) |path| { - var file = std.fs.cwd().createFile(path, .{}) catch |err| + var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| return diags.fail("failed to create '{s}': {s}", .{ path, @errorName(err) }); defer file.close(io); @@ -2711,7 +2714,7 @@ pub const Object = struct { } fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 { - var aw: std.Io.Writer.Allocating = .init(o.gpa); + var aw: Io.Writer.Allocating = .init(o.gpa); defer aw.deinit(); ty.print(&aw.writer, pt, null) catch |err| switch (err) { error.WriteFailed => return error.OutOfMemory, diff --git a/src/fmt.zig b/src/fmt.zig index ce8a31fa4c..36a3833986 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -182,11 +182,11 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! // Mark any excluded files/directories as already seen, // so that they are skipped later during actual processing for (excluded_files.items) |file_path| { - const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { + const stat = Io.Dir.cwd().statFile(file_path) catch |err| switch (err) { error.FileNotFound => continue, // On Windows, statFile does not work for directories error.IsDir => dir: { - var dir = try fs.cwd().openDir(file_path, .{}); + var dir = try Io.Dir.cwd().openDir(file_path, .{}); defer dir.close(io); break :dir try dir.stat(); }, @@ -196,7 +196,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! } for (input_files.items) |file_path| { - try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); + try fmtPath(&fmt, file_path, check_flag, Io.Dir.cwd(), file_path); } try fmt.stdout_writer.interface.flush(); if (fmt.any_error) { diff --git a/src/introspect.zig b/src/introspect.zig index d2faa9a55c..04ddf47e8a 100644 --- a/src/introspect.zig +++ b/src/introspect.zig @@ -82,7 +82,7 @@ pub fn findZigLibDirFromSelfExe( cwd_path: []const u8, self_exe_path: []const u8, ) error{ OutOfMemory, FileNotFound }!Cache.Directory { - const cwd = fs.cwd(); + const cwd = Io.Dir.cwd(); var cur_path: []const u8 = self_exe_path; while (fs.path.dirname(cur_path)) |dirname| : (cur_path = dirname) { var base_dir = cwd.openDir(dirname, .{}) catch continue; @@ -206,7 +206,7 @@ pub fn resolveSuitableLocalCacheDir(arena: Allocator, cwd: []const u8) Allocator var cur_dir = cwd; while (true) { const joined = try fs.path.join(arena, &.{ cur_dir, Package.build_zig_basename }); - if (fs.cwd().access(joined, .{})) |_| { + if (Io.Dir.cwd().access(joined, .{})) |_| { return try fs.path.join(arena, &.{ cur_dir, default_local_zig_cache_basename }); } else |err| switch (err) { error.FileNotFound => { diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index 8c5e0afe4b..cfd8d5554c 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -446,7 +446,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .io = io, .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); defer cache.manifest_dir.close(io); @@ -468,7 +468,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -986,7 +986,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -1014,7 +1014,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.C const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.getSoVersion(&target.os), + so_files.dir_path.sub_path, path.sep, lib.name, lib.getSoVersion(&target.os), }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index bec20ff3d4..e3d8ce1f7f 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -681,7 +681,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .io = io, .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); defer cache.manifest_dir.close(io); @@ -703,7 +703,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -775,7 +775,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye try stubs_asm.appendSlice(".text\n"); var sym_i: usize = 0; - var sym_name_buf: std.Io.Writer.Allocating = .init(arena); + var sym_name_buf: Io.Writer.Allocating = .init(arena); var opt_symbol_name: ?[]const u8 = null; var versions_buffer: [32]u8 = undefined; var versions_len: usize = undefined; @@ -796,7 +796,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye // twice, which causes a "duplicate symbol" assembler error. var versions_written = std.AutoArrayHashMap(Version, void).init(arena); - var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); + var inc_reader: Io.Reader = .fixed(metadata.inclusions); const fn_inclusions_len = try inc_reader.takeInt(u16, .little); @@ -1130,7 +1130,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -1156,7 +1156,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.C const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, + so_files.dir_path.sub_path, path.sep, lib.name, lib.sover, }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index 005696e1fc..b3ca51e833 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -1,7 +1,8 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; -const path = std.fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const log = std.log.scoped(.mingw); @@ -259,7 +260,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { .io = io, .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), }; - cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); defer cache.manifest_dir.close(io); @@ -304,7 +305,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { .output = .{ .to_list = .{ .arena = .init(gpa) } }, }; defer diagnostics.deinit(); - var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, std.fs.cwd()); + var aro_comp = aro.Compilation.init(gpa, arena, io, &diagnostics, Io.Dir.cwd()); defer aro_comp.deinit(); aro_comp.target = .fromZigTarget(target.*); @@ -343,7 +344,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { } const members = members: { - var aw: std.Io.Writer.Allocating = .init(gpa); + var aw: Io.Writer.Allocating = .init(gpa); errdefer aw.deinit(); try pp.prettyPrintTokens(&aw.writer, .result_only); @@ -376,7 +377,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { errdefer gpa.free(lib_final_path); { - const lib_final_file = try o_dir.createFile(final_lib_basename, .{ .truncate = true }); + const lib_final_file = try o_dir.createFile(io, final_lib_basename, .{ .truncate = true }); defer lib_final_file.close(io); var buffer: [1024]u8 = undefined; var file_writer = lib_final_file.writer(&buffer); @@ -442,7 +443,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{ lib_path, lib_name }); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -459,7 +460,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -476,7 +477,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (std.fs.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index 67e6a2f903..cb6a80d69d 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -1,9 +1,9 @@ const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; const mem = std.mem; const log = std.log; -const fs = std.fs; -const path = fs.path; +const path = std.Io.Dir.path; const assert = std.debug.assert; const Version = std.SemanticVersion; const Path = std.Build.Cache.Path; @@ -387,7 +387,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .io = io, .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}), }; - cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); + cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); cache.addPrefix(comp.dirs.global_cache); defer cache.manifest_dir.close(io); @@ -409,7 +409,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -640,7 +640,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye .lock = man.toOwnedLock(), .dir_path = .{ .root_dir = comp.dirs.global_cache, - .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), + .sub_path = try gpa.dupe(u8, "o" ++ path.sep_str ++ digest), }, }); } @@ -661,7 +661,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.C const so_path: Path = .{ .root_dir = so_files.dir_path.root_dir, .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ - so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, + so_files.dir_path.sub_path, path.sep, lib.name, lib.sover, }) catch return comp.setAllocFailure(), }; task_buffer[task_buffer_i] = .{ .load_dso = so_path }; diff --git a/src/link/C.zig b/src/link/C.zig index 04c92443e5..a001f8fdd9 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -136,7 +136,7 @@ pub fn createEmpty( assert(!use_lld); assert(!use_llvm); - const file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, }); @@ -792,7 +792,7 @@ pub fn flushEmitH(zcu: *Zcu) !void { } const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; - const file = try directory.handle.createFile(emit_h.loc.basename, .{ + const file = try directory.handle.createFile(io, emit_h.loc.basename, .{ // We set the end position explicitly below; by not truncating the file, we possibly // make it easier on the file system by doing 1 reallocation instead of two. .truncate = false, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index e1d52fb7c4..009e59ed0d 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -631,12 +631,14 @@ fn create( else => return error.UnsupportedCOFFArchitecture, }; + const io = comp.io; + const coff = try arena.create(Coff); - const file = try path.root_dir.handle.createFile(comp.io, path.sub_path, .{ + const file = try path.root_dir.handle.createFile(io, path.sub_path, .{ .read = true, .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode), }); - errdefer file.close(comp.io); + errdefer file.close(io); coff.* = .{ .base = .{ .tag = .coff2, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 584a50c7f2..53812a37ec 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -313,9 +313,11 @@ pub fn createEmpty( const is_obj = output_mode == .Obj; const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static); + const io = comp.io; + // What path should this ELF linker code output to? const sub_path = emit.sub_path; - self.base.file = try emit.root_dir.handle.createFile(sub_path, .{ + self.base.file = try emit.root_dir.handle.createFile(io, sub_path, .{ .truncate = true, .read = true, .mode = link.File.determineMode(output_mode, link_mode), diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 49f6d3f7c7..b25b9da9d9 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -1572,7 +1572,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { // report a nice error here with the file path if it fails instead of // just returning the error code. // chmod does not interact with umask, so we use a conservative -rwxr--r-- here. - std.posix.fchmodat(fs.cwd().fd, full_out_path, 0o744, 0) catch |err| switch (err) { + std.posix.fchmodat(Io.Dir.cwd().handle, full_out_path, 0o744, 0) catch |err| switch (err) { error.OperationNotSupported => unreachable, // Not a symlink. else => |e| return e, }; @@ -1624,7 +1624,7 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi const rand_int = std.crypto.random.int(u64); const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp"; - const rsp_file = try comp.dirs.local_cache.handle.createFile(rsp_path, .{}); + const rsp_file = try comp.dirs.local_cache.handle.createFile(io, rsp_path, .{}); defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err| log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) }); { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index e837cc853a..0f6127e10e 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -219,7 +219,9 @@ pub fn createEmpty( }; errdefer self.base.destroy(); - self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const io = comp.io; + + self.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, .mode = link.File.determineMode(output_mode, link_mode), @@ -1082,7 +1084,7 @@ fn accessLibPath( test_path.clearRetainingCapacity(); try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1110,7 +1112,7 @@ fn accessFrameworkPath( ext, }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1191,7 +1193,7 @@ fn parseDependentDylibs(self: *MachO) !void { try test_path.print("{s}{s}", .{ path, ext }); } try checked_paths.append(try arena.dupe(u8, test_path.items)); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -3289,7 +3291,7 @@ pub fn reopenDebugInfo(self: *MachO) !void { var d_sym_bundle = try self.base.emit.root_dir.handle.makeOpenPath(d_sym_path, .{}); defer d_sym_bundle.close(io); - self.d_sym.?.file = try d_sym_bundle.createFile(fs.path.basename(self.base.emit.sub_path), .{ + self.d_sym.?.file = try d_sym_bundle.createFile(io, fs.path.basename(self.base.emit.sub_path), .{ .truncate = false, .read = true, }); @@ -4370,7 +4372,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi // The file/property is also available with vendored libc. fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 { const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" }); - const contents = try fs.cwd().readFileAlloc(sdk_path, arena, .limited(std.math.maxInt(u16))); + const contents = try Io.Dir.cwd().readFileAlloc(sdk_path, arena, .limited(std.math.maxInt(u16))); const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{}); if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string; return error.SdkVersionFailure; diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig index 5f9a9ecac9..814faf234a 100644 --- a/src/link/MachO/CodeSignature.zig +++ b/src/link/MachO/CodeSignature.zig @@ -247,7 +247,7 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void { } pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void { - const inner = try fs.cwd().readFileAlloc(path, allocator, .limited(std.math.maxInt(u32))); + const inner = try Io.Dir.cwd().readFileAlloc(path, allocator, .limited(std.math.maxInt(u32))); self.entitlements = .{ .inner = inner }; } diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 7e28dc0a8b..d13caaa315 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -33,6 +33,7 @@ pub fn createEmpty( options: link.File.OpenOptions, ) !*Linker { const gpa = comp.gpa; + const io = comp.io; const target = &comp.root_mod.resolved_target.result; assert(!comp.config.use_lld); // Caught by Compilation.Config.resolve @@ -78,7 +79,7 @@ pub fn createEmpty( }; errdefer linker.deinit(); - linker.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + linker.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, }); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 7ab1e0eb4b..5f89625d56 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2997,7 +2997,9 @@ pub fn createEmpty( .named => |name| (try wasm.internString(name)).toOptional(), }; - wasm.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + const io = comp.io; + + wasm.base.file = try emit.root_dir.handle.createFile(io, emit.sub_path, .{ .truncate = true, .read = true, .mode = if (fs.has_executable_bit) diff --git a/src/main.zig b/src/main.zig index b040b6c8ef..67b7384b57 100644 --- a/src/main.zig +++ b/src/main.zig @@ -713,7 +713,7 @@ const Emit = union(enum) { } else e: { // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. if (fs.path.dirname(path)) |dir_path| { - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { + var dir = Io.Dir.cwd().openDir(dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; dir.close(io); @@ -3304,7 +3304,7 @@ fn buildOutputType( } else emit: { // If there's a dirname, check that dir exists. This will give a more descriptive error than `Compilation` otherwise would. if (fs.path.dirname(path)) |dir_path| { - var dir = fs.cwd().openDir(dir_path, .{}) catch |err| { + var dir = Io.Dir.cwd().openDir(dir_path, .{}) catch |err| { fatal("unable to open output directory '{s}': {s}", .{ dir_path, @errorName(err) }); }; dir.close(io); @@ -3389,7 +3389,7 @@ fn buildOutputType( // file will not run and this temp file will be leaked. The filename // will be a hash of its contents — so multiple invocations of // `zig cc -` will result in the same temp file name. - var f = try dirs.local_cache.handle.createFile(dump_path, .{}); + var f = try dirs.local_cache.handle.createFile(io, dump_path, .{}); defer f.close(io); // Re-using the hasher from Cache, since the functional requirements @@ -4773,7 +4773,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! var ok_count: usize = 0; for (template_paths) |template_path| { - if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { + if (templates.write(arena, Io.Dir.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { std.log.info("created {s}", .{template_path}); ok_count += 1; } else |err| switch (err) { @@ -5227,7 +5227,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) if (system_pkg_dir_path) |p| { job_queue.global_cache = .{ .path = p, - .handle = fs.cwd().openDir(p, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(p, .{}) catch |err| { fatal("unable to open system package directory '{s}': {s}", .{ p, @errorName(err), }); @@ -5823,7 +5823,7 @@ const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, /// Initialize the arguments from a Response File. "*.rsp" fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit - const cmd_line = try fs.cwd().readFileAlloc(resp_file_path, allocator, .limited(max_bytes)); + const cmd_line = try Io.Dir.cwd().readFileAlloc(resp_file_path, allocator, .limited(max_bytes)); errdefer allocator.free(cmd_line); return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); @@ -6187,7 +6187,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { const display_path = zig_source_path orelse ""; const source: [:0]const u8 = s: { var f = if (zig_source_path) |p| file: { - break :file fs.cwd().openFile(io, p, .{}) catch |err| { + break :file Io.Dir.cwd().openFile(io, p, .{}) catch |err| { fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; } else Io.File.stdin(); @@ -6494,7 +6494,7 @@ fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void { const cache_file = args[0]; - var f = fs.cwd().openFile(io, cache_file, .{}) catch |err| { + var f = Io.Dir.cwd().openFile(io, cache_file, .{}) catch |err| { fatal("unable to open zir cache file for dumping '{s}': {s}", .{ cache_file, @errorName(err) }); }; defer f.close(io); @@ -6541,7 +6541,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { const new_source_path = args[1]; const old_source = source: { - var f = fs.cwd().openFile(io, old_source_path, .{}) catch |err| + var f = Io.Dir.cwd().openFile(io, old_source_path, .{}) catch |err| fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); defer f.close(io); var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); @@ -6549,7 +6549,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); }; const new_source = source: { - var f = fs.cwd().openFile(io, new_source_path, .{}) catch |err| + var f = Io.Dir.cwd().openFile(io, new_source_path, .{}) catch |err| fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); defer f.close(io); var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer); @@ -6845,7 +6845,7 @@ fn accessFrameworkPath( framework_dir_path, framework_name, framework_name, ext, }); try checked_paths.print("\n {s}", .{test_path.items}); - fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{ ext, test_path.items, @errorName(e), @@ -6957,7 +6957,7 @@ fn cmdFetch( var global_cache_directory: Directory = l: { const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); break :l .{ - .handle = try fs.cwd().makeOpenPath(p, .{}), + .handle = try Io.Dir.cwd().makeOpenPath(p, .{}), .path = p, }; }; @@ -7260,7 +7260,7 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { if (options.build_file) |bf| { if (fs.path.dirname(bf)) |dirname| { - const dir = fs.cwd().openDir(dirname, .{}) catch |err| { + const dir = Io.Dir.cwd().openDir(dirname, .{}) catch |err| { fatal("unable to open directory to build file from argument 'build-file', '{s}': {s}", .{ dirname, @errorName(err) }); }; return .{ @@ -7272,7 +7272,7 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { return .{ .build_zig_basename = build_zig_basename, - .directory = .{ .path = null, .handle = fs.cwd() }, + .directory = .{ .path = null, .handle = Io.Dir.cwd() }, .cleanup_build_dir = null, }; } @@ -7280,8 +7280,8 @@ fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot { var dirname: []const u8 = cwd_path; while (true) { const joined_path = try fs.path.join(arena, &[_][]const u8{ dirname, build_zig_basename }); - if (fs.cwd().access(joined_path, .{})) |_| { - const dir = fs.cwd().openDir(dirname, .{}) catch |err| { + if (Io.Dir.cwd().access(joined_path, .{})) |_| { + const dir = Io.Dir.cwd().openDir(dirname, .{}) catch |err| { fatal("unable to open directory while searching for build.zig file, '{s}': {s}", .{ dirname, @errorName(err) }); }; return .{ @@ -7443,7 +7443,7 @@ const Templates = struct { } }; fn writeSimpleTemplateFile(io: Io, file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { - const f = try fs.cwd().createFile(file_name, .{ .exclusive = true }); + const f = try Io.Dir.cwd().createFile(io, file_name, .{ .exclusive = true }); defer f.close(io); var buf: [4096]u8 = undefined; var fw = f.writer(&buf); @@ -7591,7 +7591,7 @@ fn addLibDirectoryWarn2( ignore_not_found: bool, ) void { lib_directories.appendAssumeCapacity(.{ - .handle = fs.cwd().openDir(path, .{}) catch |err| { + .handle = Io.Dir.cwd().openDir(path, .{}) catch |err| { if (err == error.FileNotFound and ignore_not_found) return; warn("unable to open library directory '{s}': {s}", .{ path, @errorName(err) }); return; -- cgit v1.2.3 From 950d18ef695bb7a28397e080dc3c201559ec4ee2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Dec 2025 17:14:31 -0800 Subject: update all access() to access(io) --- lib/compiler/aro/aro/Driver.zig | 6 +-- lib/compiler/aro/aro/Driver/Filesystem.zig | 8 ++-- lib/compiler/aro/aro/Toolchain.zig | 13 ++++--- lib/compiler/aro/backend/Assembly.zig | 4 +- lib/compiler/resinator/cli.zig | 10 ++--- lib/compiler/resinator/main.zig | 6 +-- lib/compiler/std-docs.zig | 8 ++-- lib/compiler/translate-c/main.zig | 4 +- lib/std/Build.zig | 2 +- lib/std/Build/Cache/Path.zig | 4 +- lib/std/Build/Step.zig | 12 +++--- lib/std/Build/Step/InstallDir.zig | 2 +- lib/std/Build/Step/Run.zig | 47 ++++++++++++----------- lib/std/Build/Step/WriteFile.zig | 9 ++--- lib/std/Io.zig | 4 +- lib/std/Io/Dir.zig | 16 ++++---- lib/std/Io/Threaded.zig | 13 +++++-- lib/std/Io/test.zig | 2 +- lib/std/debug.zig | 8 ++-- lib/std/fs/test.zig | 24 ++++++------ lib/std/posix.zig | 61 ------------------------------ lib/std/posix/test.zig | 12 +++--- lib/std/zig/LibCInstallation.zig | 10 ++--- lib/std/zig/llvm/Builder.zig | 4 +- lib/std/zig/system.zig | 3 +- src/Compilation.zig | 2 +- src/Package/Fetch.zig | 5 ++- src/introspect.zig | 4 +- src/libs/mingw.zig | 12 +++--- src/link/C.zig | 3 +- src/link/Lld.zig | 9 +++-- src/link/MachO.zig | 21 +++++----- src/main.zig | 8 ++-- 33 files changed, 159 insertions(+), 197 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index fec3cea0f8..b344cc8a9d 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1333,7 +1333,7 @@ fn processSource( Io.File.stdout(); defer if (dep_file_name != null) file.close(io); - var file_writer = file.writer(&writer_buf); + var file_writer = file.writer(io, &writer_buf); dep_file.write(&file_writer.interface) catch return d.fatal("unable to write dependency file: {s}", .{errorDescription(file_writer.err.?)}); } @@ -1358,7 +1358,7 @@ fn processSource( Io.File.stdout(); defer if (d.output_name != null) file.close(io); - var file_writer = file.writer(&writer_buf); + var file_writer = file.writer(io, &writer_buf); pp.prettyPrintTokens(&file_writer.interface, dump_mode) catch return d.fatal("unable to write result: {s}", .{errorDescription(file_writer.err.?)}); @@ -1459,7 +1459,7 @@ fn processSource( return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, errorDescription(er) }); defer out_file.close(io); - var file_writer = out_file.writer(&writer_buf); + var file_writer = out_file.writer(io, &writer_buf); obj.finish(&file_writer.interface) catch return d.fatal("could not output to object file '{s}': {s}", .{ out_file_name, errorDescription(file_writer.err.?) }); } diff --git a/lib/compiler/aro/aro/Driver/Filesystem.zig b/lib/compiler/aro/aro/Driver/Filesystem.zig index 001f10f27c..c229dfd831 100644 --- a/lib/compiler/aro/aro/Driver/Filesystem.zig +++ b/lib/compiler/aro/aro/Driver/Filesystem.zig @@ -57,8 +57,8 @@ fn existsFake(entries: []const Filesystem.Entry, path: []const u8) bool { return false; } -fn canExecutePosix(path: []const u8) bool { - std.posix.access(path, std.posix.X_OK) catch return false; +fn canExecutePosix(io: Io, path: []const u8) bool { + Io.Dir.accessAbsolute(io, path, .{ .execute = true }) catch return false; // Todo: ensure path is not a directory return true; } @@ -172,10 +172,10 @@ pub const Filesystem = union(enum) { } }; - pub fn exists(fs: Filesystem, path: []const u8) bool { + pub fn exists(fs: Filesystem, io: Io, path: []const u8) bool { switch (fs) { .real => |cwd| { - cwd.access(path, .{}) catch return false; + cwd.access(io, path, .{}) catch return false; return true; }, .fake => |paths| return existsFake(paths, path), diff --git a/lib/compiler/aro/aro/Toolchain.zig b/lib/compiler/aro/aro/Toolchain.zig index 0328c264d0..0aa9d76fc8 100644 --- a/lib/compiler/aro/aro/Toolchain.zig +++ b/lib/compiler/aro/aro/Toolchain.zig @@ -501,7 +501,7 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { try d.includes.ensureUnusedCapacity(gpa, 1); if (d.resource_dir) |resource_dir| { const path = try std.fs.path.join(arena, &.{ resource_dir, "include" }); - comp.cwd.access(path, .{}) catch { + comp.cwd.access(io, path, .{}) catch { return d.fatal("Aro builtin headers not found in provided -resource-dir", .{}); }; d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path }); @@ -512,7 +512,7 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { var base_dir = d.comp.cwd.openDir(io, dirname, .{}) catch continue; defer base_dir.close(io); - base_dir.access("include/stddef.h", .{}) catch continue; + base_dir.access(io, "include/stddef.h", .{}) catch continue; const path = try std.fs.path.join(arena, &.{ dirname, "include" }); d.includes.appendAssumeCapacity(.{ .kind = .system, .path = path }); break; @@ -524,12 +524,14 @@ pub fn addBuiltinIncludeDir(tc: *const Toolchain) !void { /// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned pub fn readFile(tc: *const Toolchain, path: []const u8, buf: []u8) ?[]const u8 { const comp = tc.driver.comp; - return comp.cwd.readFile(comp.io, path, buf) catch null; + const io = comp.io; + return comp.cwd.readFile(io, path, buf) catch null; } pub fn exists(tc: *const Toolchain, path: []const u8) bool { const comp = tc.driver.comp; - comp.cwd.access(comp.io, path, .{}) catch return false; + const io = comp.io; + comp.cwd.access(io, path, .{}) catch return false; return true; } @@ -547,7 +549,8 @@ pub fn canExecute(tc: *const Toolchain, path: []const u8) bool { } const comp = tc.driver.comp; - comp.cwd.access(comp.io, path, .{ .execute = true }) catch return false; + const io = comp.io; + comp.cwd.access(io, path, .{ .execute = true }) catch return false; // Todo: ensure path is not a directory return true; } diff --git a/lib/compiler/aro/backend/Assembly.zig b/lib/compiler/aro/backend/Assembly.zig index 80143bf97f..4ec4860b51 100644 --- a/lib/compiler/aro/backend/Assembly.zig +++ b/lib/compiler/aro/backend/Assembly.zig @@ -12,8 +12,8 @@ pub fn deinit(self: *const Assembly, gpa: Allocator) void { gpa.free(self.text); } -pub fn writeToFile(self: Assembly, file: Io.File) !void { - var file_writer = file.writer(&.{}); +pub fn writeToFile(self: Assembly, io: Io, file: Io.File) !void { + var file_writer = file.writer(io, &.{}); var buffers = [_][]const u8{ self.data, self.text }; try file_writer.interface.writeSplatAll(&buffers, 1); diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index ae4ece2968..5588390197 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -250,13 +250,13 @@ pub const Options = struct { /// worlds' situation where we'll be compatible with most use-cases /// of the .rc extension being omitted from the CLI args, but still /// work fine if the file itself does not have an extension. - pub fn maybeAppendRC(options: *Options, cwd: Io.Dir) !void { + pub fn maybeAppendRC(options: *Options, io: Io, cwd: Io.Dir) !void { switch (options.input_source) { .stdio => return, .filename => {}, } if (options.input_format == .rc and std.fs.path.extension(options.input_source.filename).len == 0) { - cwd.access(options.input_source.filename, .{}) catch |err| switch (err) { + cwd.access(io, options.input_source.filename, .{}) catch |err| switch (err) { error.FileNotFound => { var filename_bytes = try options.allocator.alloc(u8, options.input_source.filename.len + 3); @memcpy(filename_bytes[0..options.input_source.filename.len], options.input_source.filename); @@ -2005,19 +2005,19 @@ test "maybeAppendRC" { // appended. var file = try tmp.dir.createFile(io, "foo", .{}); file.close(io); - try options.maybeAppendRC(tmp.dir); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); // Now delete the file and try again. But this time change the input format // to non-rc. try tmp.dir.deleteFile("foo"); options.input_format = .res; - try options.maybeAppendRC(tmp.dir); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); // Finally, reset the input format to rc. Since the verbatim name is no longer found // and the input filename does not have an extension, .rc should get appended. options.input_format = .rc; - try options.maybeAppendRC(tmp.dir); + try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo.rc", options.input_source.filename); } diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index 416abc2ab7..1a6ef5eea3 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -318,7 +318,7 @@ pub fn main() !void { defer depfile.close(io); var depfile_buffer: [1024]u8 = undefined; - var depfile_writer = depfile.writer(&depfile_buffer); + var depfile_writer = depfile.writer(io, &depfile_buffer); switch (options.depfile_fmt) { .json => { var write_stream: std.json.Stringify = .{ @@ -521,9 +521,9 @@ const IoStream = struct { } }; - pub fn writer(source: *Source, allocator: Allocator, buffer: []u8) Writer { + pub fn writer(source: *Source, allocator: Allocator, io: Io, buffer: []u8) Writer { return switch (source.*) { - .file, .stdio => |file| .{ .file = file.writer(buffer) }, + .file, .stdio => |file| .{ .file = file.writer(io, buffer) }, .memory => |*list| .{ .allocating = .fromArrayList(allocator, list) }, .closed => unreachable, }; diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index d5beab5f17..f1382e6eae 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -334,8 +334,8 @@ fn buildWasmBinary( }); defer poller.deinit(); - try sendMessage(child.stdin.?, .update); - try sendMessage(child.stdin.?, .exit); + try sendMessage(io, child.stdin.?, .update); + try sendMessage(io, child.stdin.?, .exit); var result: ?Cache.Path = null; var result_error_bundle = std.zig.ErrorBundle.empty; @@ -421,12 +421,12 @@ fn buildWasmBinary( }; } -fn sendMessage(file: std.Io.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: std.Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index d140145032..d02f21a2a8 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -232,7 +232,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration Io.File.stdout(); defer if (dep_file_name != null) file.close(io); - var file_writer = file.writer(&out_buf); + var file_writer = file.writer(io, &out_buf); dep_file.write(&file_writer.interface) catch return d.fatal("unable to write dependency file: {s}", .{aro.Driver.errorDescription(file_writer.err.?)}); } @@ -263,7 +263,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration out_file_path = path; } - var out_writer = out_file.writer(&out_buf); + var out_writer = out_file.writer(io, &out_buf); out_writer.interface.writeAll(rendered_zig) catch {}; out_writer.interface.flush() catch {}; if (out_writer.err) |write_err| diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 1eff8813e5..746b41860b 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1699,7 +1699,7 @@ pub fn addCheckFile( return Step.CheckFile.create(b, file_source, options); } -pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Dir.StatFileError)!void { +pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Dir.StatPathError)!void { const io = b.graph.io; if (b.verbose) log.info("truncate {s}", .{dest_path}); const cwd = Io.Dir.cwd(); diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig index 941948a9cd..759eb143b8 100644 --- a/lib/std/Build/Cache/Path.zig +++ b/lib/std/Build/Cache/Path.zig @@ -118,14 +118,14 @@ pub fn atomicFile( return p.root_dir.handle.atomicFile(joined_path, options); } -pub fn access(p: Path, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void { +pub fn access(p: Path, io: Io, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.access(joined_path, flags); + return p.root_dir.handle.access(io, joined_path, flags); } pub fn makePath(p: Path, io: Io, sub_path: []const u8) !void { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 2ec1c0ef31..f66f8df4c8 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -519,19 +519,21 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u /// Wrapper around `Io.Dir.makePathStatus` that handles verbose and error output. pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.MakePathStatus { const b = s.owner; + const io = b.graph.io; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); - return Io.Dir.cwd().makePathStatus(dest_path) catch |err| + return Io.Dir.cwd().makePathStatus(io, dest_path, .default_dir) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); } fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build.WebServer, gpa: Allocator) !?Path { const b = s.owner; const arena = b.allocator; + const io = b.graph.io; var timer = try std.time.Timer.start(); - try sendMessage(zp.child.stdin.?, .update); - if (!watch) try sendMessage(zp.child.stdin.?, .exit); + try sendMessage(io, zp.child.stdin.?, .update); + if (!watch) try sendMessage(io, zp.child.stdin.?, .exit); var result: ?Path = null; @@ -668,12 +670,12 @@ fn clearZigProcess(s: *Step, gpa: Allocator) void { } } -fn sendMessage(file: Io.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; diff --git a/lib/std/Build/Step/InstallDir.zig b/lib/std/Build/Step/InstallDir.zig index 788d5565a7..d03e72ca75 100644 --- a/lib/std/Build/Step/InstallDir.zig +++ b/lib/std/Build/Step/InstallDir.zig @@ -71,7 +71,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { defer src_dir.close(io); var it = try src_dir.walk(arena); var all_cached = true; - next_entry: while (try it.next()) |entry| { + next_entry: while (try it.next(io)) |entry| { for (install_dir.options.exclude_extensions) |ext| { if (mem.endsWith(u8, entry.path, ext)) continue :next_entry; } diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 54e77bd614..f6b29635c1 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1310,7 +1310,7 @@ fn runCommand( const need_cross_libc = exe.is_linking_libc and (root_target.isGnuLibC() or (root_target.isMuslLibC() and exe.linkage == .dynamic)); const other_target = exe.root_module.resolved_target.?.result; - switch (std.zig.system.getExternalExecutor(&b.graph.host.result, &other_target, .{ + switch (std.zig.system.getExternalExecutor(io, &b.graph.host.result, &other_target, .{ .qemu_fixes_dl = need_cross_libc and b.libc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -1702,7 +1702,7 @@ fn evalZigTest( }); var child_killed = false; defer if (!child_killed) { - _ = child.kill() catch {}; + _ = child.kill(io) catch {}; poller.deinit(); run.step.result_peak_rss = @max( run.step.result_peak_rss, @@ -1732,7 +1732,7 @@ fn evalZigTest( child.stdin = null; poller.deinit(); child_killed = true; - const term = try child.wait(); + const term = try child.wait(io); run.step.result_peak_rss = @max( run.step.result_peak_rss, child.resource_usage_statistics.getMaxRss() orelse 0, @@ -1752,7 +1752,7 @@ fn evalZigTest( child.stdin = null; poller.deinit(); child_killed = true; - const term = try child.wait(); + const term = try child.wait(io); run.step.result_peak_rss = @max( run.step.result_peak_rss, child.resource_usage_statistics.getMaxRss() orelse 0, @@ -1840,6 +1840,7 @@ fn pollZigTest( switch (ctx.fuzz.mode) { .forever => { sendRunFuzzTestMessage( + io, child.stdin.?, ctx.unit_test_index, .forever, @@ -1848,6 +1849,7 @@ fn pollZigTest( }, .limit => |limit| { sendRunFuzzTestMessage( + io, child.stdin.?, ctx.unit_test_index, .iterations, @@ -1857,11 +1859,11 @@ fn pollZigTest( } } else if (opt_metadata.*) |*md| { // Previous unit test process died or was killed; we're continuing where it left off - requestNextTest(child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; } else { // Running unit tests normally run.fuzz_tests.clearRetainingCapacity(); - sendMessage(child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err }; + sendMessage(io, child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err }; } var active_test_index: ?u32 = null; @@ -1977,7 +1979,7 @@ fn pollZigTest( active_test_index = null; if (timer) |*t| t.reset(); - requestNextTest(child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, .test_started => { active_test_index = opt_metadata.*.?.next_index - 1; @@ -2026,7 +2028,7 @@ fn pollZigTest( active_test_index = null; if (timer) |*t| md.ns_per_test[tr_hdr.index] = t.lap(); - requestNextTest(child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, .coverage_id => { coverage_id = body_r.takeInt(u64, .little) catch unreachable; @@ -2097,7 +2099,7 @@ pub const CachedTestMetadata = struct { } }; -fn requestNextTest(in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { +fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { while (metadata.next_index < metadata.names.len) { const i = metadata.next_index; metadata.next_index += 1; @@ -2108,31 +2110,31 @@ fn requestNextTest(in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Pr if (sub_prog_node.*) |n| n.end(); sub_prog_node.* = metadata.prog_node.start(name, 0); - try sendRunTestMessage(in, .run_test, i); + try sendRunTestMessage(io, in, .run_test, i); return; } else { metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done - try sendMessage(in, .exit); + try sendMessage(io, in, .exit); } } -fn sendMessage(file: Io.File, tag: std.zig.Client.Message.Tag) !void { +fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 0, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; } -fn sendRunTestMessage(file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void { +fn sendRunTestMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, .bytes_len = 4, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -2142,6 +2144,7 @@ fn sendRunTestMessage(file: Io.File, tag: std.zig.Client.Message.Tag, index: u32 } fn sendRunFuzzTestMessage( + io: Io, file: Io.File, index: u32, kind: std.Build.abi.fuzz.LimitKind, @@ -2151,7 +2154,7 @@ fn sendRunFuzzTestMessage( .tag = .start_fuzzing, .bytes_len = 4 + 1 + 8, }; - var w = file.writer(&.{}); + var w = file.writer(io, &.{}); w.interface.writeStruct(header, .little) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; @@ -2172,14 +2175,14 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { const arena = b.allocator; try child.spawn(); - errdefer _ = child.kill() catch {}; + errdefer _ = child.kill(io) catch {}; try child.waitForSpawn(); switch (run.stdin) { .bytes => |bytes| { - child.stdin.?.writeAll(bytes) catch |err| { - return run.step.fail("unable to write stdin: {s}", .{@errorName(err)}); + child.stdin.?.writeStreamingAll(io, bytes) catch |err| { + return run.step.fail("unable to write stdin: {t}", .{err}); }; child.stdin.?.close(io); child.stdin = null; @@ -2187,14 +2190,14 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { .lazy_path => |lazy_path| { const path = lazy_path.getPath3(b, &run.step); const file = path.root_dir.handle.openFile(io, path.subPathOrDot(), .{}) catch |err| { - return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)}); + return run.step.fail("unable to open stdin file: {t}", .{err}); }; defer file.close(io); // TODO https://github.com/ziglang/zig/issues/23955 var read_buffer: [1024]u8 = undefined; var file_reader = file.reader(io, &read_buffer); var write_buffer: [1024]u8 = undefined; - var stdin_writer = child.stdin.?.writer(&write_buffer); + var stdin_writer = child.stdin.?.writer(io, &write_buffer); _ = stdin_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) { error.ReadFailed => return run.step.fail("failed to read from {f}: {t}", .{ path, file_reader.err.?, @@ -2267,7 +2270,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { run.step.result_peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0; return .{ - .term = try child.wait(), + .term = try child.wait(io), .stdout = stdout_bytes, .stderr = stderr_bytes, }; diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 21346959e7..94b04b4212 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -228,7 +228,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var it = try src_dir.walk(gpa); defer it.deinit(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (!dir.options.pathIncluded(entry.path)) continue; switch (entry.kind) { @@ -259,11 +259,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); - var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| { - return step.fail("unable to make path '{f}{s}': {s}", .{ - b.cache_root, cache_path, @errorName(err), - }); - }; + var cache_dir = b.cache_root.handle.makeOpenPath(io, cache_path, .{}) catch |err| + return step.fail("unable to make path '{f}{s}': {t}", .{ b.cache_root, cache_path, err }); defer cache_dir.close(io); for (write_file.files.items) |file| { diff --git a/lib/std/Io.zig b/lib/std/Io.zig index ad0764ebe1..7f5f049d34 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -664,13 +664,13 @@ pub const VTable = struct { dirMake: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.MakeError!void, dirMakePath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.MakePathError!Dir.MakePathStatus, - dirMakeOpenPath: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.MakeOpenPathError!Dir, + dirMakeOpenPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions, Dir.OpenOptions) Dir.MakeOpenPathError!Dir, + dirOpenDir: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.OpenError!Dir, dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, dirStatPath: *const fn (?*anyopaque, Dir, []const u8, Dir.StatPathOptions) Dir.StatPathError!File.Stat, dirAccess: *const fn (?*anyopaque, Dir, []const u8, Dir.AccessOptions) Dir.AccessError!void, dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, File.CreateFlags) File.OpenError!File, dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, File.OpenFlags) File.OpenError!File, - dirOpenDir: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.OpenError!Dir, dirClose: *const fn (?*anyopaque, []const Dir) void, dirRead: *const fn (?*anyopaque, *Dir.Reader, []Dir.Entry) Dir.Reader.Error!usize, dirRealPath: *const fn (?*anyopaque, Dir, path_name: []const u8, out_buffer: []u8) Dir.RealPathError!usize, diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 58f81cbb90..755ce924ad 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -191,7 +191,7 @@ pub const SelectiveWalker = struct { 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 (top.iter.next(io) catch |err| { // If we get an error, then we want the user to be able to continue // walking if they want, which means that we need to pop the directory // that errored from the stack. Otherwise, all future `next` calls would @@ -302,7 +302,7 @@ pub const Walker = struct { dir: Dir, basename: [:0]const u8, path: [:0]const u8, - kind: Dir.Entry.Kind, + kind: File.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 @@ -320,10 +320,10 @@ pub const Walker = struct { /// 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(); + pub fn next(self: *Walker, io: Io) !?Walker.Entry { + const entry = try self.inner.next(io); if (entry != null and entry.?.kind == .directory) { - try self.inner.enter(entry.?); + try self.inner.enter(io, entry.?); } return entry; } @@ -495,7 +495,7 @@ pub const WriteFileOptions = struct { flags: File.CreateFlags = .{}, }; -pub const WriteFileError = File.WriteError || File.OpenError; +pub const WriteFileError = File.Writer.Error || File.OpenError; /// Writes content to the file system, using the file creation flags provided. pub fn writeFile(dir: Dir, io: Io, options: WriteFileOptions) WriteFileError!void { @@ -556,11 +556,11 @@ pub fn updateFile( } if (path.dirname(dest_path)) |dirname| { - try dest_dir.makePath(io, dirname, .default_dir); + try dest_dir.makePath(io, dirname); } var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. - var atomic_file = try Dir.atomicFile(dest_dir, dest_path, .{ + var atomic_file = try dest_dir.atomicFile(io, dest_path, .{ .permissions = actual_permissions, .write_buffer = &buffer, }); diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 4ee1d5db53..16e8930267 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -12,7 +12,7 @@ const std = @import("../std.zig"); const Io = std.Io; const net = std.Io.net; const File = std.Io.File; -const Dir = std.Dir; +const Dir = std.Io.Dir; const HostName = std.Io.net.HostName; const IpAddress = std.Io.net.IpAddress; const Allocator = std.mem.Allocator; @@ -1614,13 +1614,14 @@ fn dirMakeOpenPathPosix( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, + permissions: Dir.Permissions, options: Dir.OpenOptions, ) Dir.MakeOpenPathError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const t_io = ioBasic(t); - return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { + return dirOpenDirPosix(t, dir, sub_path, permissions, options) catch |err| switch (err) { error.FileNotFound => { - try dir.makePath(t_io, sub_path); + _ = try dir.makePathStatus(t_io, sub_path, permissions); return dirOpenDirPosix(t, dir, sub_path, options); }, else => |e| return e, @@ -1631,12 +1632,15 @@ fn dirMakeOpenPathWindows( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, + permissions: Dir.Permissions, options: Dir.OpenOptions, ) Dir.MakeOpenPathError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); const w = windows; + _ = permissions; // TODO apply these permissions + var it = std.fs.path.componentIterator(sub_path); // If there are no components in the path, then create a dummy component with the full path. var component: std.fs.path.NativeComponentIterator.Component = it.last() orelse .{ @@ -1746,13 +1750,14 @@ fn dirMakeOpenPathWasi( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, + permissions: Dir.Permissions, options: Dir.OpenOptions, ) Dir.MakeOpenPathError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const t_io = ioBasic(t); return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { error.FileNotFound => { - try dir.makePath(t_io, sub_path); + _ = try dir.makePathStatus(t_io, sub_path, permissions); return dirOpenDirWasi(t, dir, sub_path, options); }, else => |e| return e, diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index e911031c7f..9763fb2397 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -30,7 +30,7 @@ test "write a file, read it, then delete it" { var file = try tmp.dir.createFile(io, tmp_file_name, .{}); defer file.close(io); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const st = &file_writer.interface; try st.print("begin", .{}); try st.writeAll(&data); diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 34f740bfee..39207f938d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1279,7 +1279,7 @@ test printLineFromFile { const overlap = 10; var buf: [16]u8 = undefined; - var file_writer = file.writer(&buf); + var file_writer = file.writer(io, &buf); const writer = &file_writer.interface; try writer.splatByteAll('a', std.heap.page_size_min - overlap); try writer.writeByte('\n'); @@ -1296,7 +1296,7 @@ test printLineFromFile { const path = try fs.path.join(gpa, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; try writer.splatByteAll('a', std.heap.page_size_max); @@ -1310,7 +1310,7 @@ test printLineFromFile { const path = try fs.path.join(gpa, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; try writer.splatByteAll('a', 3 * std.heap.page_size_max); @@ -1336,7 +1336,7 @@ test printLineFromFile { const path = try fs.path.join(gpa, &.{ test_dir_path, "file_of_newlines.zig" }); defer gpa.free(path); - var file_writer = file.writer(&.{}); + var file_writer = file.writer(io, &.{}); const writer = &file_writer.interface; const real_file_start = 3 * std.heap.page_size_min; try writer.splatByteAll('\n', real_file_start); diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index bc84500419..59bacff2d0 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -1206,8 +1206,8 @@ test "deleteTree does not follow symlinks" { try tmp.dir.deleteTree("a"); - try testing.expectError(error.FileNotFound, tmp.dir.access("a", .{})); - try tmp.dir.access("b", .{}); + try testing.expectError(error.FileNotFound, tmp.dir.access(io, "a", .{})); + try tmp.dir.access(io, "b", .{}); } test "deleteTree on a symlink" { @@ -1221,16 +1221,16 @@ test "deleteTree on a symlink" { try setupSymlink(tmp.dir, "file", "filelink", .{}); try tmp.dir.deleteTree("filelink"); - try testing.expectError(error.FileNotFound, tmp.dir.access("filelink", .{})); - try tmp.dir.access("file", .{}); + try testing.expectError(error.FileNotFound, tmp.dir.access(io, "filelink", .{})); + try tmp.dir.access(io, "file", .{}); // Symlink to a directory try tmp.dir.makePath(io, "dir"); try setupSymlink(tmp.dir, "dir", "dirlink", .{ .is_directory = true }); try tmp.dir.deleteTree("dirlink"); - try testing.expectError(error.FileNotFound, tmp.dir.access("dirlink", .{})); - try tmp.dir.access("dir", .{}); + try testing.expectError(error.FileNotFound, tmp.dir.access(io, "dirlink", .{})); + try tmp.dir.access(io, "dir", .{}); } test "makePath, put some files in it, deleteTree" { @@ -1358,8 +1358,8 @@ test "makepath relative walks" { // On Windows, .. is resolved before passing the path to NtCreateFile, // meaning everything except `first/C` drops out. try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); - try testing.expectError(error.FileNotFound, tmp.dir.access("second", .{})); - try testing.expectError(error.FileNotFound, tmp.dir.access("third", .{})); + try testing.expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); + try testing.expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); }, else => { try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "A"); @@ -1561,10 +1561,10 @@ test "access file" { const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); try ctx.dir.makePath(io, dir_path); - try testing.expectError(error.FileNotFound, ctx.dir.access(file_path, .{})); + try testing.expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); try ctx.dir.writeFile(.{ .sub_path = file_path, .data = "" }); - try ctx.dir.access(file_path, .{}); + try ctx.dir.access(io, file_path, .{}); try ctx.dir.deleteTree(dir_path); } }.impl); @@ -2036,13 +2036,13 @@ test "'.' and '..' in Io.Dir functions" { const update_path = try ctx.transformPath("./subdir/../update"); try ctx.dir.makeDir(subdir_path); - try ctx.dir.access(subdir_path, .{}); + try ctx.dir.access(io, subdir_path, .{}); var created_subdir = try ctx.dir.openDir(io, subdir_path, .{}); created_subdir.close(io); const created_file = try ctx.dir.createFile(io, file_path, .{}); created_file.close(io); - try ctx.dir.access(file_path, .{}); + try ctx.dir.access(io, file_path, .{}); try ctx.dir.copyFile(file_path, ctx.dir, copy_path, .{}); try ctx.dir.rename(copy_path, rename_path); diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 42429a4993..609cf62e82 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -2842,67 +2842,6 @@ pub fn msync(memory: []align(page_size_min) u8, flags: i32) MSyncError!void { } } -pub const AccessError = error{ - AccessDenied, - PermissionDenied, - FileNotFound, - NameTooLong, - InputOutput, - SystemResources, - FileBusy, - SymLinkLoop, - ReadOnlyFileSystem, - /// WASI: file paths must be valid UTF-8. - /// Windows: file paths provided by the user must be valid WTF-8. - /// https://wtf-8.codeberg.page/ - BadPathName, - Canceled, -} || UnexpectedError; - -/// check user's permissions for a file -/// -/// * On Windows, asserts `path` is valid [WTF-8](https://wtf-8.codeberg.page/). -/// * On WASI, invalid UTF-8 passed to `path` causes `error.BadPathName`. -/// * On other platforms, `path` is an opaque sequence of bytes with no particular encoding. -/// -/// On Windows, `mode` is ignored. This is a POSIX API that is only partially supported by -/// Windows. See `fs` for the cross-platform file system API. -pub fn access(path: []const u8, mode: u32) AccessError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - @compileError("wasi doesn't support absolute paths"); - } - const path_c = try toPosixPath(path); - return accessZ(&path_c, mode); -} - -/// Same as `access` except `path` is null-terminated. -pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { - if (native_os == .windows) { - @compileError("use std.Io instead"); - } else if (native_os == .wasi and !builtin.link_libc) { - return access(mem.sliceTo(path, 0), mode); - } - switch (errno(system.access(path, mode))) { - .SUCCESS => return, - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, - .ROFS => return error.ReadOnlyFileSystem, - .LOOP => return error.SymLinkLoop, - .TXTBSY => return error.FileBusy, - .NOTDIR => return error.FileNotFound, - .NOENT => return error.FileNotFound, - .NAMETOOLONG => return error.NameTooLong, - .INVAL => unreachable, - .FAULT => unreachable, - .IO => return error.InputOutput, - .NOMEM => return error.SystemResources, - .ILSEQ => return error.BadPathName, - else => |err| return unexpectedErrno(err), - } -} - pub const PipeError = error{ SystemFdQuotaExceeded, ProcessFdQuotaExceeded, diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 169c5a70c2..af17f1f9ff 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -376,7 +376,7 @@ test "mmap" { const file = try tmp.dir.createFile(io, test_out_file, .{}); defer file.close(io); - var stream = file.writer(&.{}); + var stream = file.writer(io, &.{}); var i: usize = 0; while (i < alloc_size / @sizeOf(u32)) : (i += 1) { @@ -741,6 +741,8 @@ test "access smoke test" { if (native_os == .windows) return error.SkipZigTest; if (native_os == .openbsd) return error.SkipZigTest; + const io = testing.io; + var tmp = tmpDir(.{}); defer tmp.cleanup(); @@ -761,9 +763,9 @@ test "access smoke test" { const file_path = try fs.path.join(a, &.{ base_path, "some_file" }); defer a.free(file_path); if (native_os == .windows) { - try posix.access(file_path, posix.F_OK); + try posix.access(io, file_path, posix.F_OK); } else { - try posix.access(file_path, posix.F_OK | posix.W_OK | posix.R_OK); + try posix.access(io, file_path, posix.F_OK | posix.W_OK | posix.R_OK); } } @@ -771,7 +773,7 @@ test "access smoke test" { // Try to access() a non-existent file - should fail with error.FileNotFound const file_path = try fs.path.join(a, &.{ base_path, "some_other_file" }); defer a.free(file_path); - try expectError(error.FileNotFound, posix.access(file_path, posix.F_OK)); + try expectError(error.FileNotFound, posix.access(io, file_path, posix.F_OK)); } { @@ -786,7 +788,7 @@ test "access smoke test" { const file_path = try fs.path.join(a, &.{ base_path, "some_dir" }); defer a.free(file_path); - try posix.access(file_path, posix.F_OK); + try posix.access(io, file_path, posix.F_OK); } } diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index a5c55d3522..f3dc73838f 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -357,7 +357,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F } if (self.sys_include_dir == null) { - if (search_dir.access(sys_include_dir_example_file, .{})) |_| { + if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| { self.sys_include_dir = try allocator.dupeZ(u8, search_path); } else |err| switch (err) { error.FileNotFound => {}, @@ -402,7 +402,7 @@ fn findNativeIncludeDirWindows( }; defer dir.close(io); - dir.access("stdlib.h", .{}) catch |err| switch (err) { + dir.access(io, "stdlib.h", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -450,7 +450,7 @@ fn findNativeCrtDirWindows( }; defer dir.close(io); - dir.access("ucrt.lib", .{}) catch |err| switch (err) { + dir.access(io, "ucrt.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -518,7 +518,7 @@ fn findNativeKernel32LibDir( }; defer dir.close(io); - dir.access("kernel32.lib", .{}) catch |err| switch (err) { + dir.access(io, "kernel32.lib", .{}) catch |err| switch (err) { error.FileNotFound => continue, else => return error.FileSystem, }; @@ -554,7 +554,7 @@ fn findNativeMsvcIncludeDir( }; defer dir.close(io); - dir.access("vcruntime.h", .{}) catch |err| switch (err) { + dir.access(io, "vcruntime.h", .{}) catch |err| switch (err) { error.FileNotFound => return error.LibCStdLibHeaderNotFound, else => return error.FileSystem, }; diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 443bdcc391..251c87defc 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -9589,8 +9589,8 @@ pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void try b.printToFile(io, file, &buffer); } -pub fn printToFile(b: *Builder, file: Io.File, buffer: []u8) !void { - var fw = file.writer(buffer); +pub fn printToFile(b: *Builder, io: Io, file: Io.File, buffer: []u8) !void { + var fw = file.writer(io, buffer); try print(b, &fw.interface); try fw.interface.flush(); } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 9fa0546c3b..feed21efec 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -40,6 +40,7 @@ pub const GetExternalExecutorOptions = struct { /// Return whether or not the given host is capable of running executables of /// the other target. pub fn getExternalExecutor( + io: Io, host: *const std.Target, candidate: *const std.Target, options: GetExternalExecutorOptions, @@ -70,7 +71,7 @@ pub fn getExternalExecutor( if (os_match and cpu_ok) native: { if (options.link_libc) { if (candidate.dynamic_linker.get()) |candidate_dl| { - Io.Dir.cwd().access(candidate_dl, .{}) catch { + Io.Dir.cwd().access(io, candidate_dl, .{}) catch { bad_result = .{ .bad_dl = candidate_dl }; break :native; }; diff --git a/src/Compilation.zig b/src/Compilation.zig index 280d34cdbf..36429a42f8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -788,7 +788,7 @@ pub const Directories = struct { const local_cache: Cache.Directory = switch (local_cache_strat) { .override => |path| openUnresolved(arena, io, cwd, path, .@"local cache"), .search => d: { - const maybe_path = introspect.resolveSuitableLocalCacheDir(arena, cwd) catch |err| { + const maybe_path = introspect.resolveSuitableLocalCacheDir(arena, io, cwd) catch |err| { fatal("unable to resolve zig cache directory: {s}", .{@errorName(err)}); }; const path = maybe_path orelse break :d global_cache; diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index e54dcb9914..860fb8974e 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -418,7 +418,7 @@ pub fn run(f: *Fetch) RunError!void { const prefixed_pkg_sub_path = prefixed_pkg_sub_path_buffer[0 .. 2 + hash_slice.len]; const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0; const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..]; - if (cache_root.handle.access(pkg_sub_path, .{})) |_| { + if (cache_root.handle.access(io, pkg_sub_path, .{})) |_| { assert(f.lazy_status != .unavailable); f.package_root = .{ .root_dir = cache_root, @@ -637,8 +637,9 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash { /// `computeHash` gets a free check for the existence of `build.zig`, but when /// not computing a hash, we need to do a syscall to check for it. fn checkBuildFileExistence(f: *Fetch) RunError!void { + const io = f.job_queue.io; const eb = &f.error_bundle; - if (f.package_root.access(Package.build_zig_basename, .{})) |_| { + if (f.package_root.access(io, Package.build_zig_basename, .{})) |_| { f.has_build_zig = true; } else |err| switch (err) { error.FileNotFound => {}, diff --git a/src/introspect.zig b/src/introspect.zig index a56a214cbe..3f8308961f 100644 --- a/src/introspect.zig +++ b/src/introspect.zig @@ -202,11 +202,11 @@ pub const default_local_zig_cache_basename = ".zig-cache"; /// Searches upwards from `cwd` for a directory containing a `build.zig` file. /// If such a directory is found, returns the path to it joined to the `.zig_cache` name. /// Otherwise, returns `null`, indicating no suitable local cache location. -pub fn resolveSuitableLocalCacheDir(arena: Allocator, cwd: []const u8) Allocator.Error!?[]u8 { +pub fn resolveSuitableLocalCacheDir(arena: Allocator, io: Io, cwd: []const u8) Allocator.Error!?[]u8 { var cur_dir = cwd; while (true) { const joined = try fs.path.join(arena, &.{ cur_dir, Package.build_zig_basename }); - if (Io.Dir.cwd().access(joined, .{})) |_| { + if (Io.Dir.cwd().access(io, joined, .{})) |_| { return try fs.path.join(arena, &.{ cur_dir, default_local_zig_cache_basename }); } else |err| switch (err) { error.FileNotFound => { diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index b3ca51e833..93f88b9689 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -242,7 +242,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const def_file_path = findDef(arena, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) { + const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) { error.FileNotFound => { log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name }); // In this case we will end up putting foo.lib onto the linker line and letting the linker @@ -402,11 +402,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { pub fn libExists( allocator: Allocator, + io: Io, target: *const std.Target, zig_lib_directory: Cache.Directory, lib_name: []const u8, ) !bool { - const s = findDef(allocator, target, zig_lib_directory, lib_name) catch |err| switch (err) { + const s = findDef(allocator, io, target, zig_lib_directory, lib_name) catch |err| switch (err) { error.FileNotFound => return false, else => |e| return e, }; @@ -418,6 +419,7 @@ pub fn libExists( /// see if a .def file exists. fn findDef( allocator: Allocator, + io: Io, target: *const std.Target, zig_lib_directory: Cache.Directory, lib_name: []const u8, @@ -443,7 +445,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{ lib_path, lib_name }); } - if (Io.Dir.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -460,7 +462,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (Io.Dir.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, @@ -477,7 +479,7 @@ fn findDef( } else { try override_path.print(fmt_path, .{lib_name}); } - if (Io.Dir.cwd().access(override_path.items, .{})) |_| { + if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| { return override_path.toOwnedSlice(); } else |err| switch (err) { error.FileNotFound => {}, diff --git a/src/link/C.zig b/src/link/C.zig index a001f8fdd9..db5acebf07 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -371,6 +371,7 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P const comp = self.base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; + const io = comp.io; const zcu = self.base.comp.zcu.?; const ip = &zcu.intern_pool; const pt: Zcu.PerThread = .activate(zcu, tid); @@ -509,7 +510,7 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P const file = self.base.file.?; file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)}); - var fw = file.writer(&.{}); + var fw = file.writer(io, &.{}); var w = &fw.interface; w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{ diff --git a/src/link/Lld.zig b/src/link/Lld.zig index b25b9da9d9..ca15a38bb0 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -359,6 +359,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { fn coffLink(lld: *Lld, arena: Allocator) !void { const comp = lld.base.comp; const gpa = comp.gpa; + const io = comp.io; const base = &lld.base; const coff = &lld.ofmt.coff; @@ -718,13 +719,13 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { argv.appendAssumeCapacity(try crt_file.full_object_path.toString(arena)); continue; } - if (try findLib(arena, lib_basename, coff.lib_directories)) |full_path| { + if (try findLib(arena, io, lib_basename, coff.lib_directories)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } if (target.abi.isGnu()) { const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key}); - if (try findLib(arena, fallback_name, coff.lib_directories)) |full_path| { + if (try findLib(arena, io, fallback_name, coff.lib_directories)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } @@ -741,9 +742,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { try spawnLld(comp, arena, argv.items); } } -fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 { +fn findLib(arena: Allocator, io: Io, name: []const u8, lib_directories: []const Cache.Directory) !?[]const u8 { for (lib_directories) |lib_directory| { - lib_directory.handle.access(name, .{}) catch |err| switch (err) { + lib_directory.handle.access(io, name, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 78e035e2ad..6cd906340a 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -829,7 +829,8 @@ pub fn resolveLibSystem( comp: *Compilation, out_libs: anytype, ) !void { - const diags = &self.base.comp.link_diags; + const io = comp.io; + const diags = &comp.link_diags; var test_path = std.array_list.Managed(u8).init(arena); var checked_paths = std.array_list.Managed([]const u8).init(arena); @@ -838,16 +839,16 @@ pub fn resolveLibSystem( if (self.sdk_layout) |sdk_layout| switch (sdk_layout) { .sdk => { const dir = try fs.path.join(arena, &.{ comp.sysroot.?, "usr", "lib" }); - if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, dir, "System")) break :success; }, .vendored => { const dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "darwin" }); - if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, dir, "System")) break :success; }, }; for (self.lib_directories) |directory| { - if (try accessLibPath(arena, &test_path, &checked_paths, directory.path orelse ".", "System")) break :success; + if (try accessLibPath(arena, io, &test_path, &checked_paths, directory.path orelse ".", "System")) break :success; } diags.addMissingLibraryError(checked_paths.items, "unable to find libSystem system library", .{}); @@ -1074,6 +1075,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool { /// TODO delete this, libraries must be instead resolved when instantiating the compilation pipeline fn accessLibPath( arena: Allocator, + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed([]const u8), search_dir: []const u8, @@ -1085,7 +1087,7 @@ fn accessLibPath( test_path.clearRetainingCapacity(); try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1097,6 +1099,7 @@ fn accessLibPath( fn accessFrameworkPath( arena: Allocator, + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed([]const u8), search_dir: []const u8, @@ -1113,7 +1116,7 @@ fn accessFrameworkPath( ext, }); try checked_paths.append(try arena.dupe(u8, test_path.items)); - Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -1172,14 +1175,14 @@ fn parseDependentDylibs(self: *MachO) !void { // Framework for (framework_dirs) |dir| { test_path.clearRetainingCapacity(); - if (try accessFrameworkPath(arena, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items; + if (try accessFrameworkPath(arena, io, &test_path, &checked_paths, dir, stem)) break :full_path test_path.items; } // Library const lib_name = eatPrefix(stem, "lib") orelse stem; for (lib_directories) |lib_directory| { test_path.clearRetainingCapacity(); - if (try accessLibPath(arena, &test_path, &checked_paths, lib_directory.path orelse ".", lib_name)) break :full_path test_path.items; + if (try accessLibPath(arena, io, &test_path, &checked_paths, lib_directory.path orelse ".", lib_name)) break :full_path test_path.items; } } @@ -1194,7 +1197,7 @@ fn parseDependentDylibs(self: *MachO) !void { try test_path.print("{s}{s}", .{ path, ext }); } try checked_paths.append(try arena.dupe(u8, test_path.items)); - Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; diff --git a/src/main.zig b/src/main.zig index a063591b64..99850f5ffe 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3208,6 +3208,7 @@ fn buildOutputType( for (create_module.framework_dirs.items) |framework_dir_path| { if (try accessFrameworkPath( + io, &test_path, &checked_paths, framework_dir_path, @@ -6626,7 +6627,7 @@ fn warnAboutForeignBinaries( const host_query: std.Target.Query = .{}; const host_target = std.zig.resolveTargetQueryOrFatal(io, host_query); - switch (std.zig.system.getExternalExecutor(&host_target, target, .{ .link_libc = link_libc })) { + switch (std.zig.system.getExternalExecutor(io, &host_target, target, .{ .link_libc = link_libc })) { .native => return, .rosetta => { const host_name = try host_target.zigTriple(arena); @@ -6832,6 +6833,7 @@ const ClangSearchSanitizer = struct { }; fn accessFrameworkPath( + io: Io, test_path: *std.array_list.Managed(u8), checked_paths: *std.array_list.Managed(u8), framework_dir_path: []const u8, @@ -6845,7 +6847,7 @@ fn accessFrameworkPath( framework_dir_path, framework_name, framework_name, ext, }); try checked_paths.print("\n {s}", .{test_path.items}); - Io.Dir.cwd().access(test_path.items, .{}) catch |err| switch (err) { + Io.Dir.cwd().access(io, test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{ ext, test_path.items, @errorName(e), @@ -7280,7 +7282,7 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !Build var dirname: []const u8 = cwd_path; while (true) { const joined_path = try fs.path.join(arena, &[_][]const u8{ dirname, build_zig_basename }); - if (Io.Dir.cwd().access(joined_path, .{})) |_| { + if (Io.Dir.cwd().access(io, joined_path, .{})) |_| { const dir = Io.Dir.cwd().openDir(io, dirname, .{}) catch |err| { fatal("unable to open directory while searching for build.zig file, '{s}': {s}", .{ dirname, @errorName(err) }); }; -- cgit v1.2.3 From 3725f72293c87a73e0c11e74739574c7b78bb53d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Dec 2025 18:46:55 -0800 Subject: update std.process.Child.run occurences to use io --- lib/compiler/libc.zig | 11 ++- lib/compiler/reduce.zig | 7 +- lib/std/Build/Step.zig | 4 +- lib/std/zig/LibCInstallation.zig | 118 ++++++++++++------------------ lib/std/zig/system/darwin.zig | 29 ++++---- src/main.zig | 3 +- test/standalone/child_process/main.zig | 2 +- test/standalone/windows_bat_args/fuzz.zig | 17 +++-- test/standalone/windows_bat_args/test.zig | 11 +-- test/standalone/windows_paths/test.zig | 48 ++++++------ 10 files changed, 115 insertions(+), 135 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/libc.zig b/lib/compiler/libc.zig index 142b87062e..7a6edf0c44 100644 --- a/lib/compiler/libc.zig +++ b/lib/compiler/libc.zig @@ -78,7 +78,7 @@ pub fn main() !void { if (input_file) |libc_file| { const libc = try arena.create(LibCInstallation); libc.* = LibCInstallation.parse(arena, libc_file, &target) catch |err| { - fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); + fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err }); }; break :libc libc; } else { @@ -97,7 +97,7 @@ pub fn main() !void { libc_installation, ) catch |err| { const zig_target = try target.zigTriple(arena); - fatal("unable to detect libc for target {s}: {s}", .{ zig_target, @errorName(err) }); + fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err }); }; if (libc_dirs.libc_include_dir_list.len == 0) { @@ -115,19 +115,18 @@ pub fn main() !void { if (input_file) |libc_file| { var libc = LibCInstallation.parse(gpa, libc_file, &target) catch |err| { - fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); + fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err }); }; defer libc.deinit(gpa); } else { if (!target_query.canDetectLibC()) { fatal("unable to detect libc for non-native target", .{}); } - var libc = LibCInstallation.findNative(.{ - .allocator = gpa, + var libc = LibCInstallation.findNative(gpa, io, .{ .verbose = true, .target = &target, }) catch |err| { - fatal("unable to detect native libc: {s}", .{@errorName(err)}); + fatal("unable to detect native libc: {t}", .{err}); }; defer libc.deinit(gpa); diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index 0bfa1902ab..f10bd12e9d 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -307,11 +307,8 @@ fn termToInteresting(term: std.process.Child.Term) Interestingness { }; } -fn runCheck(arena: std.mem.Allocator, argv: []const []const u8) !Interestingness { - const result = try std.process.Child.run(.{ - .allocator = arena, - .argv = argv, - }); +fn runCheck(arena: Allocator, io: Io, argv: []const []const u8) !Interestingness { + const result = try std.process.Child.run(arena, io, .{ .argv = argv }); if (result.stderr.len != 0) std.debug.print("{s}", .{result.stderr}); return termToInteresting(result.term); diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index f66f8df4c8..8115aaa1a1 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -350,6 +350,7 @@ pub fn captureChildProcess( argv: []const []const u8, ) !std.process.Child.RunResult { const arena = s.owner.allocator; + const io = s.owner.graph.io; // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); @@ -358,8 +359,7 @@ pub fn captureChildProcess( try handleChildProcUnsupported(s); try handleVerbose(s.owner, null, argv); - const result = std.process.Child.run(.{ - .allocator = arena, + const result = std.process.Child.run(arena, io, .{ .argv = argv, .progress_node = progress_node, }) catch |err| return s.fail("failed to run {s}: {t}", .{ argv[0], err }); diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index 1463ff4a40..6051eecb94 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -166,8 +166,6 @@ pub fn render(self: LibCInstallation, out: *std.Io.Writer) !void { } pub const FindNativeOptions = struct { - allocator: Allocator, - io: Io, target: *const std.Target, /// If enabled, will print human-friendly errors to stderr. @@ -175,10 +173,7 @@ pub const FindNativeOptions = struct { }; /// Finds the default, native libc. -pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { - const gpa = args.allocator; - const io = args.io; - +pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!LibCInstallation { var self: LibCInstallation = .{}; if (is_darwin and args.target.os.tag.isDarwin()) { @@ -203,14 +198,14 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { }; defer sdk.free(gpa); - try self.findNativeMsvcIncludeDir(args, sdk); - try self.findNativeMsvcLibDir(args, sdk); - try self.findNativeKernel32LibDir(args, sdk); - try self.findNativeIncludeDirWindows(args, sdk); - try self.findNativeCrtDirWindows(args, sdk); + try self.findNativeMsvcIncludeDir(gpa, io, sdk); + try self.findNativeMsvcLibDir(gpa, sdk); + try self.findNativeKernel32LibDir(gpa, io, args, sdk); + try self.findNativeIncludeDirWindows(gpa, io, args, sdk); + try self.findNativeCrtDirWindows(gpa, io, args.target, sdk); } else if (is_haiku) { try self.findNativeIncludeDirPosix(args); - try self.findNativeGccDirHaiku(args); + try self.findNativeGccDirHaiku(gpa, io, args); self.crt_dir = try gpa.dupeZ(u8, "/system/develop/lib"); } else if (builtin.target.os.tag == .illumos) { // There is only one libc, and its headers/libraries are always in the same spot. @@ -221,7 +216,7 @@ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { try self.findNativeIncludeDirPosix(args); switch (builtin.target.os.tag) { .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try gpa.dupeZ(u8, "/usr/lib"), - .linux => try self.findNativeCrtDirPosix(args), + .linux => try self.findNativeCrtDirPosix(gpa, io, args), else => {}, } } else { @@ -241,12 +236,9 @@ pub fn deinit(self: *LibCInstallation, allocator: Allocator) void { self.* = undefined; } -fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - const allocator = args.allocator; - const io = args.io; - +fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { // Detect infinite loops. - var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { + var env_map = std.process.getEnvMap(gpa) catch |err| switch (err) { error.Unexpected => unreachable, // WASI-only else => |e| return e, }; @@ -265,7 +257,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F const dev_null = if (is_windows) "nul" else "/dev/null"; - var argv = std.array_list.Managed([]const u8).init(allocator); + var argv = std.array_list.Managed([]const u8).init(gpa); defer argv.deinit(); try appendCcExe(&argv, skip_cc_env_var); @@ -276,8 +268,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F dev_null, }); - const run_res = std.process.Child.run(.{ - .allocator = allocator, + const run_res = std.process.Child.run(gpa, io, .{ .argv = argv.items, .max_output_bytes = 1024 * 1024, .env_map = &env_map, @@ -294,8 +285,8 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F }, }; defer { - allocator.free(run_res.stdout); - allocator.free(run_res.stderr); + gpa.free(run_res.stdout); + gpa.free(run_res.stderr); } switch (run_res.term) { .Exited => |code| if (code != 0) { @@ -309,7 +300,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F } var it = std.mem.tokenizeAny(u8, run_res.stderr, "\n\r"); - var search_paths = std.array_list.Managed([]const u8).init(allocator); + var search_paths = std.array_list.Managed([]const u8).init(gpa); defer search_paths.deinit(); while (it.next()) |line| { if (line.len != 0 and line[0] == ' ') { @@ -345,7 +336,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F if (self.include_dir == null) { if (search_dir.access(include_dir_example_file, .{})) |_| { - self.include_dir = try allocator.dupeZ(u8, search_path); + self.include_dir = try gpa.dupeZ(u8, search_path); } else |err| switch (err) { error.FileNotFound => {}, else => return error.FileSystem, @@ -354,7 +345,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F if (self.sys_include_dir == null) { if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| { - self.sys_include_dir = try allocator.dupeZ(u8, search_path); + self.sys_include_dir = try gpa.dupeZ(u8, search_path); } else |err| switch (err) { error.FileNotFound => {}, else => return error.FileSystem, @@ -372,16 +363,14 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) F fn findNativeIncludeDirWindows( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - const io = args.io; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); for (installs) |install| { @@ -412,19 +401,18 @@ fn findNativeIncludeDirWindows( fn findNativeCrtDirWindows( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, + target: *const std.Target, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - const io = args.io; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); - const arch_sub_dir = switch (args.target.cpu.arch) { + const arch_sub_dir = switch (target.cpu.arch) { .x86 => "x86", .x86_64 => "x64", .arm, .armeb => "arm", @@ -457,9 +445,8 @@ fn findNativeCrtDirWindows( return error.LibCRuntimeNotFound; } -fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - self.crt_dir = try ccPrintFileName(.{ - .allocator = args.allocator, +fn findNativeCrtDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { + self.crt_dir = try ccPrintFileName(gpa, io, .{ .search_basename = switch (args.target.os.tag) { .linux => if (args.target.abi.isAndroid()) "crtbegin_dynamic.o" else "crt1.o", else => "crt1.o", @@ -469,9 +456,8 @@ fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindE }); } -fn findNativeGccDirHaiku(self: *LibCInstallation, args: FindNativeOptions) FindError!void { - self.gcc_dir = try ccPrintFileName(.{ - .allocator = args.allocator, +fn findNativeGccDirHaiku(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { + self.gcc_dir = try ccPrintFileName(gpa, io, .{ .search_basename = "crtbeginS.o", .want_dirname = .only_dir, .verbose = args.verbose, @@ -480,16 +466,15 @@ fn findNativeGccDirHaiku(self: *LibCInstallation, args: FindNativeOptions) FindE fn findNativeKernel32LibDir( self: *LibCInstallation, + gpa: Allocator, + io: Io, args: FindNativeOptions, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - const io = args.io; - var install_buf: [2]std.zig.WindowsSdk.Installation = undefined; const installs = fillInstallations(&install_buf, sdk); - var result_buf = std.array_list.Managed(u8).init(allocator); + var result_buf = std.array_list.Managed(u8).init(gpa); defer result_buf.deinit(); const arch_sub_dir = switch (args.target.cpu.arch) { @@ -527,18 +512,16 @@ fn findNativeKernel32LibDir( fn findNativeMsvcIncludeDir( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, + io: Io, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; - const io = args.io; - const msvc_lib_dir = sdk.msvc_lib_dir orelse return error.LibCStdLibHeaderNotFound; const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; - const dir_path = try fs.path.join(allocator, &[_][]const u8{ up2, "include" }); - errdefer allocator.free(dir_path); + const dir_path = try fs.path.join(gpa, &[_][]const u8{ up2, "include" }); + errdefer gpa.free(dir_path); var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch |err| switch (err) { error.FileNotFound, @@ -560,27 +543,23 @@ fn findNativeMsvcIncludeDir( fn findNativeMsvcLibDir( self: *LibCInstallation, - args: FindNativeOptions, + gpa: Allocator, sdk: std.zig.WindowsSdk, ) FindError!void { - const allocator = args.allocator; const msvc_lib_dir = sdk.msvc_lib_dir orelse return error.LibCRuntimeNotFound; - self.msvc_lib_dir = try allocator.dupe(u8, msvc_lib_dir); + self.msvc_lib_dir = try gpa.dupe(u8, msvc_lib_dir); } pub const CCPrintFileNameOptions = struct { - allocator: Allocator, search_basename: []const u8, want_dirname: enum { full_path, only_dir }, verbose: bool = false, }; /// caller owns returned memory -fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { - const allocator = args.allocator; - +fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8 { // Detect infinite loops. - var env_map = std.process.getEnvMap(allocator) catch |err| switch (err) { + var env_map = std.process.getEnvMap(gpa) catch |err| switch (err) { error.Unexpected => unreachable, // WASI-only else => |e| return e, }; @@ -597,17 +576,16 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { break :blk false; }; - var argv = std.array_list.Managed([]const u8).init(allocator); + var argv = std.array_list.Managed([]const u8).init(gpa); defer argv.deinit(); - const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={s}", .{args.search_basename}); - defer allocator.free(arg1); + const arg1 = try std.fmt.allocPrint(gpa, "-print-file-name={s}", .{args.search_basename}); + defer gpa.free(arg1); try appendCcExe(&argv, skip_cc_env_var); try argv.append(arg1); - const run_res = std.process.Child.run(.{ - .allocator = allocator, + const run_res = std.process.Child.run(gpa, io, .{ .argv = argv.items, .max_output_bytes = 1024 * 1024, .env_map = &env_map, @@ -621,8 +599,8 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { else => return error.UnableToSpawnCCompiler, }; defer { - allocator.free(run_res.stdout); - allocator.free(run_res.stderr); + gpa.free(run_res.stdout); + gpa.free(run_res.stderr); } switch (run_res.term) { .Exited => |code| if (code != 0) { @@ -641,10 +619,10 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { // So we detect failure by checking if the output matches exactly the input. if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound; switch (args.want_dirname) { - .full_path => return allocator.dupeZ(u8, line), + .full_path => return gpa.dupeZ(u8, line), .only_dir => { const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; - return allocator.dupeZ(u8, dirname); + return gpa.dupeZ(u8, dirname); }, } } diff --git a/lib/std/zig/system/darwin.zig b/lib/std/zig/system/darwin.zig index fbd6da2a9e..b493ccf0ec 100644 --- a/lib/std/zig/system/darwin.zig +++ b/lib/std/zig/system/darwin.zig @@ -1,28 +1,29 @@ const std = @import("std"); +const Io = std.Io; const mem = std.mem; -const Allocator = mem.Allocator; +const Allocator = std.mem.Allocator; const Target = std.Target; const Version = std.SemanticVersion; pub const macos = @import("darwin/macos.zig"); /// Check if SDK is installed on Darwin without triggering CLT installation popup window. -/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup. +/// +/// Simply invoking `xcrun` will inevitably trigger the CLT installation popup. /// Therefore, we resort to invoking `xcode-select --print-path` and checking /// if the status is nonzero. +/// /// stderr from xcode-select is ignored. +/// /// If error.OutOfMemory occurs in Allocator, this function returns null. -pub fn isSdkInstalled(allocator: Allocator) bool { - const result = std.process.Child.run(.{ - .allocator = allocator, +pub fn isSdkInstalled(gpa: Allocator, io: Io) bool { + const result = std.process.Child.run(gpa, io, .{ .argv = &.{ "xcode-select", "--print-path" }, }) catch return false; - defer { - allocator.free(result.stderr); - allocator.free(result.stdout); + gpa.free(result.stderr); + gpa.free(result.stdout); } - return switch (result.term) { .Exited => |code| if (code == 0) result.stdout.len > 0 else false, else => false, @@ -34,7 +35,7 @@ pub fn isSdkInstalled(allocator: Allocator) bool { /// Caller owns the memory. /// stderr from xcrun is ignored. /// If error.OutOfMemory occurs in Allocator, this function returns null. -pub fn getSdk(allocator: Allocator, target: *const Target) ?[]const u8 { +pub fn getSdk(gpa: Allocator, io: Io, target: *const Target) ?[]const u8 { const is_simulator_abi = target.abi == .simulator; const sdk = switch (target.os.tag) { .driverkit => "driverkit", @@ -46,16 +47,16 @@ pub fn getSdk(allocator: Allocator, target: *const Target) ?[]const u8 { else => return null, }; const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" }; - const result = std.process.Child.run(.{ .allocator = allocator, .argv = argv }) catch return null; + const result = std.process.Child.run(gpa, io, .{ .argv = argv }) catch return null; defer { - allocator.free(result.stderr); - allocator.free(result.stdout); + gpa.free(result.stderr); + gpa.free(result.stdout); } switch (result.term) { .Exited => |code| if (code != 0) return null, else => return null, } - return allocator.dupe(u8, mem.trimEnd(u8, result.stdout, "\r\n")) catch null; + return gpa.dupe(u8, mem.trimEnd(u8, result.stdout, "\r\n")) catch null; } test { diff --git a/src/main.zig b/src/main.zig index 9bb88d373b..58f0e68301 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4017,8 +4017,7 @@ fn createModule( any_name_queries_remaining) { if (create_module.libc_installation == null) { - create_module.libc_installation = LibCInstallation.findNative(.{ - .allocator = arena, + create_module.libc_installation = LibCInstallation.findNative(arena, io, .{ .verbose = true, .target = target, }) catch |err| { diff --git a/test/standalone/child_process/main.zig b/test/standalone/child_process/main.zig index 755beacb6d..2a28845a56 100644 --- a/test/standalone/child_process/main.zig +++ b/test/standalone/child_process/main.zig @@ -57,7 +57,7 @@ pub fn main() !void { // Check that FileNotFound is consistent across platforms when trying to spawn an executable that doesn't exist const missing_child_path = try std.mem.concat(gpa, u8, &.{ child_path, "_intentionally_missing" }); defer gpa.free(missing_child_path); - try std.testing.expectError(error.FileNotFound, std.process.Child.run(.{ .allocator = gpa, .argv = &.{missing_child_path} })); + try std.testing.expectError(error.FileNotFound, std.process.Child.run(gpa, io, .{ .argv = &.{missing_child_path} })); } var parent_test_error = false; diff --git a/test/standalone/windows_bat_args/fuzz.zig b/test/standalone/windows_bat_args/fuzz.zig index 8b9895b52d..bbc0d94077 100644 --- a/test/standalone/windows_bat_args/fuzz.zig +++ b/test/standalone/windows_bat_args/fuzz.zig @@ -1,5 +1,7 @@ -const std = @import("std"); const builtin = @import("builtin"); + +const std = @import("std"); +const Io = std.Io; const Allocator = std.mem.Allocator; pub fn main() anyerror!void { @@ -78,13 +80,13 @@ pub fn main() anyerror!void { } } -fn testExec(gpa: std.mem.Allocator, args: []const []const u8, env: ?*std.process.EnvMap) !void { - try testExecBat(gpa, "args1.bat", args, env); - try testExecBat(gpa, "args2.bat", args, env); - try testExecBat(gpa, "args3.bat", args, env); +fn testExec(gpa: Allocator, io: Io, args: []const []const u8, env: ?*std.process.EnvMap) !void { + try testExecBat(gpa, io, "args1.bat", args, env); + try testExecBat(gpa, io, "args2.bat", args, env); + try testExecBat(gpa, io, "args3.bat", args, env); } -fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { +fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { const argv = try gpa.alloc([]const u8, 1 + args.len); defer gpa.free(argv); argv[0] = bat; @@ -92,8 +94,7 @@ fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8 const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); - const result = try std.process.Child.run(.{ - .allocator = gpa, + const result = try std.process.Child.run(gpa, io, .{ .env_map = env, .argv = argv, }); diff --git a/test/standalone/windows_bat_args/test.zig b/test/standalone/windows_bat_args/test.zig index 4690d983f3..558adc248f 100644 --- a/test/standalone/windows_bat_args/test.zig +++ b/test/standalone/windows_bat_args/test.zig @@ -1,4 +1,6 @@ const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; pub fn main() anyerror!void { var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init; @@ -121,17 +123,17 @@ pub fn main() anyerror!void { try std.testing.expectError(error.FileNotFound, tmp.dir.access("file.txt", .{})); } -fn testExecError(err: anyerror, gpa: std.mem.Allocator, args: []const []const u8) !void { +fn testExecError(err: anyerror, gpa: Allocator, args: []const []const u8) !void { return std.testing.expectError(err, testExec(gpa, args, null)); } -fn testExec(gpa: std.mem.Allocator, args: []const []const u8, env: ?*std.process.EnvMap) !void { +fn testExec(gpa: Allocator, args: []const []const u8, env: ?*std.process.EnvMap) !void { try testExecBat(gpa, "args1.bat", args, env); try testExecBat(gpa, "args2.bat", args, env); try testExecBat(gpa, "args3.bat", args, env); } -fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { +fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8, env: ?*std.process.EnvMap) !void { const argv = try gpa.alloc([]const u8, 1 + args.len); defer gpa.free(argv); argv[0] = bat; @@ -139,8 +141,7 @@ fn testExecBat(gpa: std.mem.Allocator, bat: []const u8, args: []const []const u8 const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); - const result = try std.process.Child.run(.{ - .allocator = gpa, + const result = try std.process.Child.run(gpa, io, .{ .env_map = env, .argv = argv, }); diff --git a/test/standalone/windows_paths/test.zig b/test/standalone/windows_paths/test.zig index 2ec23417e6..f5fa594766 100644 --- a/test/standalone/windows_paths/test.zig +++ b/test/standalone/windows_paths/test.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; pub fn main() anyerror!void { var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); @@ -9,6 +10,9 @@ pub fn main() anyerror!void { if (args.len < 2) return error.MissingArgs; + var threaded: Io.Threaded = .init_single_threaded; + const io = threaded.io(); + const exe_path = args[1]; const cwd_path = try std.process.getCwdAlloc(arena); @@ -33,39 +37,39 @@ pub fn main() anyerror!void { // With the special =X: environment variable set, drive-relative paths that // don't match the CWD's drive letter are resolved against that env var. - try checkRelative(arena, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &alt_drive_env_map); // Without that environment variable set, drive-relative paths that don't match the // CWD's drive letter are resolved against the root of the drive. - try checkRelative(arena, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); - try checkRelative(arena, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); + try checkRelative(arena, io, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); // Bare drive-relative path with no components - try checkRelative(arena, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &empty_env); - try checkRelative(arena, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &empty_env); + try checkRelative(arena, io, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &empty_env); // Bare drive-relative path with no components, drive-CWD set - try checkRelative(arena, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &alt_drive_env_map); // Bare drive-relative path relative to the CWD should be equivalent if drive-CWD is set - try checkRelative(arena, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, null, &alt_drive_env_map); // Bare drive-relative should always be equivalent to itself - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); - try checkRelative(arena, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); } if (parsed_cwd_path.kind == .unc_absolute) { const drive_abs_path = try std.fmt.allocPrint(arena, "{c}:\\foo\\bar", .{alt_drive_letter}); { - try checkRelative(arena, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, null, &empty_env); - try checkRelative(arena, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, null, &empty_env); + try checkRelative(arena, io, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, null, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, null, &empty_env); } } else if (parsed_cwd_path.kind == .drive_absolute) { const cur_drive_letter = parsed_cwd_path.root[0]; @@ -73,14 +77,14 @@ pub fn main() anyerror!void { const unc_cwd = try std.fmt.allocPrint(arena, "\\\\127.0.0.1\\{c}$\\{s}", .{ cur_drive_letter, path_beyond_root }); { - try checkRelative(arena, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, null, &empty_env); - try checkRelative(arena, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, null, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, null, &empty_env); + try checkRelative(arena, io, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, null, &empty_env); } { const drive_abs = cwd_path; const drive_rel = parsed_cwd_path.root[0..2]; - try checkRelative(arena, "", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); - try checkRelative(arena, "", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); } } else { return error.UnexpectedPathType; @@ -89,13 +93,13 @@ pub fn main() anyerror!void { fn checkRelative( allocator: std.mem.Allocator, + io: Io, expected_stdout: []const u8, argv: []const []const u8, cwd: ?[]const u8, env_map: ?*const std.process.EnvMap, ) !void { - const result = try std.process.Child.run(.{ - .allocator = allocator, + const result = try std.process.Child.run(allocator, io, .{ .argv = argv, .cwd = cwd, .env_map = env_map, -- cgit v1.2.3 From 4a53e5b0b4131c6b8e18bb551e8215e425f8ac71 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Dec 2025 20:03:50 -0800 Subject: fix a handful of compilation errors related to std.fs migration --- lib/compiler/resinator/cli.zig | 2 +- lib/compiler/resinator/main.zig | 2 +- lib/compiler/std-docs.zig | 18 +++---- lib/std/Build.zig | 2 +- lib/std/Build/Cache.zig | 2 +- lib/std/Build/Step.zig | 2 +- lib/std/Build/Step/Run.zig | 4 +- lib/std/Build/WebServer.zig | 2 +- lib/std/Io/Dir.zig | 7 +-- lib/std/Io/File.zig | 4 ++ lib/std/Io/File/Atomic.zig | 7 ++- lib/std/Io/net/test.zig | 2 +- lib/std/Io/test.zig | 2 +- lib/std/fs/test.zig | 26 +++++----- lib/std/posix/test.zig | 2 +- lib/std/process/Child.zig | 94 +++++++++++++++++----------------- lib/std/tar.zig | 36 ++++++------- src/Compilation.zig | 15 +++--- src/Package/Fetch.zig | 12 ++--- src/link.zig | 14 +++-- src/link/Lld.zig | 8 +-- src/main.zig | 13 ++--- test/src/Cases.zig | 3 +- test/standalone/child_process/main.zig | 2 +- 24 files changed, 148 insertions(+), 133 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 5588390197..d2dd71b1f6 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -2010,7 +2010,7 @@ test "maybeAppendRC" { // Now delete the file and try again. But this time change the input format // to non-rc. - try tmp.dir.deleteFile("foo"); + try tmp.dir.deleteFile(io, "foo"); options.input_format = .res; try options.maybeAppendRC(io, tmp.dir); try std.testing.expectEqualStrings("foo", options.input_source.filename); diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index afe1dcbe91..6c12903f06 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -440,7 +440,7 @@ const IoStream = struct { // Delete the output file on error file.close(io); // Failing to delete is not really a big deal, so swallow any errors - Io.Dir.cwd().deleteFile(self.name) catch {}; + Io.Dir.cwd().deleteFile(io, self.name) catch {}; }, .stdio, .memory, .closed => return, } diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index 6452496305..538558fe48 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -72,8 +72,8 @@ pub fn main() !void { const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port}); std.Io.File.stdout().writeAll(url_with_newline) catch {}; if (should_open_browser) { - openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { - std.log.err("unable to open browser: {s}", .{@errorName(err)}); + openBrowserTab(gpa, io, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { + std.log.err("unable to open browser: {t}", .{err}); }; } @@ -89,7 +89,7 @@ pub fn main() !void { while (true) { const connection = try http_server.accept(); _ = std.Thread.spawn(.{}, accept, .{ &context, connection }) catch |err| { - std.log.err("unable to accept connection: {s}", .{@errorName(err)}); + std.log.err("unable to accept connection: {t}", .{err}); connection.stream.close(io); continue; }; @@ -328,7 +328,7 @@ fn buildWasmBinary( child.stdin_behavior = .Pipe; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; - try child.spawn(); + try child.spawn(io); var poller = std.Io.poll(gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, @@ -434,13 +434,13 @@ fn sendMessage(io: Io, file: std.Io.File, tag: std.zig.Client.Message.Tag) !void }; } -fn openBrowserTab(gpa: Allocator, url: []const u8) !void { +fn openBrowserTab(gpa: Allocator, io: Io, url: []const u8) !void { // Until https://github.com/ziglang/zig/issues/19205 is implemented, we // spawn a thread for this child process. - _ = try std.Thread.spawn(.{}, openBrowserTabThread, .{ gpa, url }); + _ = try std.Thread.spawn(.{}, openBrowserTabThread, .{ gpa, io, url }); } -fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { +fn openBrowserTabThread(gpa: Allocator, io: Io, url: []const u8) !void { const main_exe = switch (builtin.os.tag) { .windows => "explorer", .macos => "open", @@ -450,6 +450,6 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void { child.stdin_behavior = .Ignore; child.stdout_behavior = .Ignore; child.stderr_behavior = .Ignore; - try child.spawn(); - _ = try child.wait(); + try child.spawn(io); + _ = try child.wait(io); } diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 746b41860b..ae2ab1c4d0 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1838,7 +1838,7 @@ pub fn runAllowFail( child.env_map = &b.graph.env_map; try Step.handleVerbose2(b, null, child.env_map, argv); - try child.spawn(); + try child.spawn(io); var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); const stdout = stdout_reader.interface.allocRemaining(b.allocator, .limited(max_output_size)) catch { diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index d2ba33c74d..b97efc7677 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -1300,7 +1300,7 @@ fn testGetCurrentFileTimestamp(io: Io, dir: Io.Dir) !Io.Timestamp { }); defer { file.close(io); - dir.deleteFile(test_out_file) catch {}; + dir.deleteFile(io, test_out_file) catch {}; } return (try file.stat(io)).mtime; diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 8115aaa1a1..9c7fcc757f 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -455,7 +455,7 @@ pub fn evalZigProcess( child.request_resource_usage_statistics = true; child.progress_node = prog_node; - child.spawn() catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err }); + child.spawn(io) catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err }); const zp = try gpa.create(ZigProcess); zp.* = .{ diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 19d2e7e61c..95024061d8 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1689,7 +1689,7 @@ fn evalZigTest( }; while (true) { - try child.spawn(); + try child.spawn(io); var poller = std.Io.poll(gpa, StdioPollEnum, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, @@ -2168,7 +2168,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult { const io = b.graph.io; const arena = b.allocator; - try child.spawn(); + try child.spawn(io); errdefer _ = child.kill(io) catch {}; try child.waitForSpawn(); diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 72306cbab9..5f633c5948 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -580,7 +580,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim child.stdin_behavior = .Pipe; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; - try child.spawn(); + try child.spawn(io); var poller = Io.poll(gpa, enum { stdout, stderr }, .{ .stdout = child.stdout.?, diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index cf5e2b4c72..d6d6aa1be2 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -1366,7 +1366,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void { => |e| return e, }; } else { - if (parent_dir.deleteFile(name)) { + if (parent_dir.deleteFile(io, name)) { continue :process_stack; } else |err| switch (err) { error.FileNotFound => continue :process_stack, @@ -1477,7 +1477,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8, dir_name = result; continue :scan_dir; } else { - if (dir.deleteFile(entry.name)) { + if (dir.deleteFile(io, entry.name)) { continue :dir_it; } else |err| switch (err) { error.FileNotFound => continue :dir_it, @@ -1567,7 +1567,7 @@ fn deleteTreeOpenInitialSubpath(dir: Dir, io: Io, sub_path: []const u8, kind_hin => |e| return e, }; } else { - if (dir.deleteFile(sub_path)) { + if (dir.deleteFile(io, sub_path)) { return null; } else |err| switch (err) { error.FileNotFound => return null, @@ -1588,6 +1588,7 @@ fn deleteTreeOpenInitialSubpath(dir: Dir, io: Io, sub_path: []const u8, kind_hin error.FileBusy, error.BadPathName, error.NetworkNotFound, + error.Canceled, error.Unexpected, => |e| return e, } diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index 302d2a8ca5..6d4dd4f323 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -407,6 +407,10 @@ pub const Permissions = std.options.FilePermissions orelse if (is_windows) enum( return @intFromEnum(self); } + pub fn fromMode(mode: std.posix.mode_t) @This() { + return @enumFromInt(mode); + } + /// Returns `true` if and only if no class has write permissions. pub fn readOnly(self: @This()) bool { const mode = toMode(self); diff --git a/lib/std/Io/File/Atomic.zig b/lib/std/Io/File/Atomic.zig index ccb81815ed..7d412703ed 100644 --- a/lib/std/Io/File/Atomic.zig +++ b/lib/std/Io/File/Atomic.zig @@ -20,7 +20,7 @@ pub const InitError = File.OpenError; pub fn init( io: Io, dest_basename: []const u8, - mode: File.Mode, + permissions: File.Permissions, dir: Dir, close_dir_on_deinit: bool, write_buffer: []u8, @@ -28,7 +28,10 @@ pub fn init( while (true) { const random_integer = std.crypto.random.int(u64); const tmp_sub_path = std.fmt.hex(random_integer); - const file = dir.createFile(io, &tmp_sub_path, .{ .mode = mode, .exclusive = true }) catch |err| switch (err) { + const file = dir.createFile(io, &tmp_sub_path, .{ + .permissions = permissions, + .exclusive = true, + }) catch |err| switch (err) { error.PathAlreadyExists => continue, else => |e| return e, }; diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig index c9ed0d3284..23edab5a5d 100644 --- a/lib/std/Io/net/test.zig +++ b/lib/std/Io/net/test.zig @@ -278,7 +278,7 @@ test "listen on a unix socket, send bytes, receive bytes" { defer testing.allocator.free(socket_path); const socket_addr = try net.UnixAddress.init(socket_path); - defer Io.Dir.cwd().deleteFile(socket_path) catch {}; + defer Io.Dir.cwd().deleteFile(io, socket_path) catch {}; var server = try socket_addr.listen(io, .{}); defer server.socket.close(io); diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig index 9763fb2397..02bdb591d0 100644 --- a/lib/std/Io/test.zig +++ b/lib/std/Io/test.zig @@ -60,7 +60,7 @@ test "write a file, read it, then delete it" { try expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], &data)); try expect(mem.eql(u8, contents[contents.len - "end".len ..], "end")); } - try tmp.dir.deleteFile(tmp_file_name); + try tmp.dir.deleteFile(io, tmp_file_name); } test "File seek ops" { diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index edc15526b2..da0a0cff79 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -873,7 +873,7 @@ test "file operations on directories" { try ctx.dir.makeDir(io, test_dir_name, .default_dir); try testing.expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); - try testing.expectError(error.IsDir, ctx.dir.deleteFile(test_dir_name)); + try testing.expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); switch (native_os) { .dragonfly, .netbsd => { // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 @@ -942,7 +942,7 @@ test "deleteDir" { try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(test_dir_path)); // deleting an empty directory - try ctx.dir.deleteFile(test_file_path); + try ctx.dir.deleteFile(io, test_file_path); try ctx.dir.deleteDir(test_dir_path); } }.impl); @@ -1671,13 +1671,13 @@ test "copyFile" { const dest_file2 = try ctx.transformPath("tmp_test_copy_file3.txt"); try ctx.dir.writeFile(io, .{ .sub_path = src_file, .data = data }); - defer ctx.dir.deleteFile(src_file) catch {}; + defer ctx.dir.deleteFile(io, src_file) catch {}; try ctx.dir.copyFile(src_file, ctx.dir, dest_file, .{}); - defer ctx.dir.deleteFile(dest_file) catch {}; + defer ctx.dir.deleteFile(io, dest_file) catch {}; try ctx.dir.copyFile(src_file, ctx.dir, dest_file2, .{ .override_mode = File.default_mode }); - defer ctx.dir.deleteFile(dest_file2) catch {}; + defer ctx.dir.deleteFile(io, dest_file2) catch {}; try expectFileContents(io, ctx.dir, dest_file, data); try expectFileContents(io, ctx.dir, dest_file2, data); @@ -1713,7 +1713,7 @@ test "AtomicFile" { const content = try ctx.dir.readFileAlloc(io, test_out_file, allocator, .limited(9999)); try testing.expectEqualStrings(test_content, content); - try ctx.dir.deleteFile(test_out_file); + try ctx.dir.deleteFile(io, test_out_file); } }.impl); } @@ -2055,7 +2055,7 @@ test "'.' and '..' in Io.Dir functions" { try ctx.dir.rename(copy_path, ctx.dir, rename_path, io); const renamed_file = try ctx.dir.openFile(io, rename_path, .{}); renamed_file.close(io); - try ctx.dir.deleteFile(rename_path); + try ctx.dir.deleteFile(io, rename_path); try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); var dir = ctx.dir; @@ -2113,19 +2113,19 @@ test "chmod" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - const file = try tmp.dir.createFile(io, "test_file", .{ .mode = 0o600 }); + const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) }); defer file.close(io); - try testing.expectEqual(@as(File.Mode, 0o600), (try file.stat(io)).mode & 0o7777); + try testing.expectEqual(@as(posix.mode_t, 0o600), (try file.stat(io)).permissions.toMode() & 0o7777); - try file.chmod(0o644); - try testing.expectEqual(@as(File.Mode, 0o644), (try file.stat(io)).mode & 0o7777); + try file.setPermissions(io, .fromMode(0o644)); + try testing.expectEqual(@as(posix.mode_t, 0o644), (try file.stat(io)).permissions.toMode() & 0o7777); try tmp.dir.makeDir(io, "test_dir", .default_dir); var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); defer dir.close(io); - try dir.chmod(0o700); - try testing.expectEqual(@as(File.Mode, 0o700), (try dir.stat(io)).mode & 0o7777); + try dir.setPermissions(io, .fromMode(0o700)); + try testing.expectEqual(@as(posix.mode_t, 0o700), (try dir.stat(io)).permissions.toMode() & 0o7777); } test "chown" { diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 756ecfd63f..b5255ad2a1 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -144,7 +144,7 @@ test "linkat with different directories" { const subdir = try tmp.dir.makeOpenPath("subdir", .{}); - defer tmp.dir.deleteFile(target_name) catch {}; + defer tmp.dir.deleteFile(io, target_name) catch {}; try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); // Test 1: link from file in subdir back up to target in parent directory diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index dbbacc496c..17139e66b8 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -1,4 +1,4 @@ -const ChildProcess = @This(); +const Child = @This(); const builtin = @import("builtin"); const native_os = builtin.os.tag; @@ -31,7 +31,7 @@ pub const Id = switch (native_os) { id: Id, thread_handle: if (native_os == .windows) windows.HANDLE else void, -allocator: mem.Allocator, +allocator: Allocator, /// The writing end of the child process's standard input pipe. /// Usage requires `stdin_behavior == StdIo.Pipe`. @@ -229,7 +229,7 @@ pub const StdIo = enum { }; /// First argument in argv is the executable. -pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess { +pub fn init(argv: []const []const u8, allocator: Allocator) Child { return .{ .allocator = allocator, .argv = argv, @@ -252,7 +252,7 @@ pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess { }; } -pub fn setUserName(self: *ChildProcess, name: []const u8) !void { +pub fn setUserName(self: *Child, name: []const u8) !void { const user_info = try process.getUserInfo(name); self.uid = user_info.uid; self.gid = user_info.gid; @@ -260,7 +260,7 @@ pub fn setUserName(self: *ChildProcess, name: []const u8) !void { /// On success must call `kill` or `wait`. /// After spawning the `id` is available. -pub fn spawn(self: *ChildProcess) SpawnError!void { +pub fn spawn(self: *Child, io: Io) SpawnError!void { if (!process.can_spawn) { @compileError("the target operating system cannot spawn processes"); } @@ -268,17 +268,17 @@ pub fn spawn(self: *ChildProcess) SpawnError!void { if (native_os == .windows) { return self.spawnWindows(); } else { - return self.spawnPosix(); + return self.spawnPosix(io); } } -pub fn spawnAndWait(self: *ChildProcess) SpawnError!Term { - try self.spawn(); - return self.wait(); +pub fn spawnAndWait(child: *Child, io: Io) SpawnError!Term { + try child.spawn(io); + return child.wait(io); } /// Forcibly terminates child process and then cleans up all resources. -pub fn kill(self: *ChildProcess, io: Io) !Term { +pub fn kill(self: *Child, io: Io) !Term { if (native_os == .windows) { return self.killWindows(io, 1); } else { @@ -286,7 +286,7 @@ pub fn kill(self: *ChildProcess, io: Io) !Term { } } -pub fn killWindows(self: *ChildProcess, io: Io, exit_code: windows.UINT) !Term { +pub fn killWindows(self: *Child, io: Io, exit_code: windows.UINT) !Term { if (self.term) |term| { self.cleanupStreams(io); return term; @@ -308,7 +308,7 @@ pub fn killWindows(self: *ChildProcess, io: Io, exit_code: windows.UINT) !Term { return self.term.?; } -pub fn killPosix(self: *ChildProcess, io: Io) !Term { +pub fn killPosix(self: *Child, io: Io) !Term { if (self.term) |term| { self.cleanupStreams(io); return term; @@ -325,7 +325,7 @@ pub const WaitError = SpawnError || std.os.windows.GetProcessMemoryInfoError; /// On some targets, `spawn` may not report all spawn errors, such as `error.InvalidExe`. /// This function will block until any spawn errors can be reported, and return them. -pub fn waitForSpawn(self: *ChildProcess) SpawnError!void { +pub fn waitForSpawn(self: *Child) SpawnError!void { if (native_os == .windows) return; // `spawn` reports everything if (self.term) |term| { _ = term catch |spawn_err| return spawn_err; @@ -355,7 +355,7 @@ pub fn waitForSpawn(self: *ChildProcess) SpawnError!void { } /// Blocks until child process terminates and then cleans up all resources. -pub fn wait(self: *ChildProcess, io: Io) WaitError!Term { +pub fn wait(self: *Child, io: Io) WaitError!Term { try self.waitForSpawn(); // report spawn errors if (self.term) |term| { self.cleanupStreams(io); @@ -381,7 +381,7 @@ pub const RunResult = struct { /// /// The process must be started with stdout_behavior and stderr_behavior == .Pipe pub fn collectOutput( - child: ChildProcess, + child: Child, /// Used for `stdout` and `stderr`. allocator: Allocator, stdout: *ArrayList(u8), @@ -446,7 +446,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct { expand_arg0: Arg0Expand = .no_expand, progress_node: std.Progress.Node = std.Progress.Node.none, }) RunError!RunResult { - var child = ChildProcess.init(args.argv, allocator); + var child = Child.init(args.argv, allocator); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; @@ -461,7 +461,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct { var stderr: ArrayList(u8) = .empty; defer stderr.deinit(allocator); - try child.spawn(); + try child.spawn(io); errdefer { _ = child.kill(io) catch {}; } @@ -474,7 +474,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct { }; } -fn waitUnwrappedWindows(self: *ChildProcess, io: Io) WaitError!void { +fn waitUnwrappedWindows(self: *Child, io: Io) WaitError!void { const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false); self.term = @as(SpawnError!Term, x: { @@ -496,7 +496,7 @@ fn waitUnwrappedWindows(self: *ChildProcess, io: Io) WaitError!void { return result; } -fn waitUnwrappedPosix(self: *ChildProcess, io: Io) void { +fn waitUnwrappedPosix(self: *Child, io: Io) void { const res: posix.WaitPidResult = res: { if (self.request_resource_usage_statistics) { switch (native_os) { @@ -531,11 +531,11 @@ fn waitUnwrappedPosix(self: *ChildProcess, io: Io) void { self.handleWaitResult(status); } -fn handleWaitResult(self: *ChildProcess, status: u32) void { +fn handleWaitResult(self: *Child, status: u32) void { self.term = statusToTerm(status); } -fn cleanupStreams(self: *ChildProcess, io: Io) void { +fn cleanupStreams(self: *Child, io: Io) void { if (self.stdin) |*stdin| { stdin.close(io); self.stdin = null; @@ -561,7 +561,7 @@ fn statusToTerm(status: u32) Term { Term{ .Unknown = status }; } -fn spawnPosix(self: *ChildProcess) SpawnError!void { +fn spawnPosix(self: *Child, io: Io) SpawnError!void { // The child process does need to access (one end of) these pipes. However, // we must initially set CLOEXEC to avoid a race condition. If another thread // is racing to spawn a different child process, we don't want it to inherit @@ -659,7 +659,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { })).ptr; } else { // TODO come up with a solution for this. - @panic("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process"); + @panic("missing std lib enhancement: std.process.Child implementation has no way to collect the environment variables to forward to the child process"); } }; @@ -671,41 +671,41 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { const pid_result = try posix.fork(); if (pid_result == 0) { // we are the child - setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); - setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); - setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); + setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err); + setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err); + setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err); if (self.cwd_dir) |cwd| { - posix.fchdir(cwd.handle) catch |err| forkChildErrReport(err_pipe[1], err); + posix.fchdir(cwd.handle) catch |err| forkChildErrReport(io, err_pipe[1], err); } else if (self.cwd) |cwd| { - posix.chdir(cwd) catch |err| forkChildErrReport(err_pipe[1], err); + posix.chdir(cwd) catch |err| forkChildErrReport(io, err_pipe[1], err); } // Must happen after fchdir above, the cwd file descriptor might be // equal to prog_fileno and be clobbered by this dup2 call. - if (prog_pipe[1] != -1) posix.dup2(prog_pipe[1], prog_fileno) catch |err| forkChildErrReport(err_pipe[1], err); + if (prog_pipe[1] != -1) posix.dup2(prog_pipe[1], prog_fileno) catch |err| forkChildErrReport(io, err_pipe[1], err); if (self.gid) |gid| { - posix.setregid(gid, gid) catch |err| forkChildErrReport(err_pipe[1], err); + posix.setregid(gid, gid) catch |err| forkChildErrReport(io, err_pipe[1], err); } if (self.uid) |uid| { - posix.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); + posix.setreuid(uid, uid) catch |err| forkChildErrReport(io, err_pipe[1], err); } if (self.pgid) |pid| { - posix.setpgid(0, pid) catch |err| forkChildErrReport(err_pipe[1], err); + posix.setpgid(0, pid) catch |err| forkChildErrReport(io, err_pipe[1], err); } if (self.start_suspended) { - posix.kill(posix.getpid(), .STOP) catch |err| forkChildErrReport(err_pipe[1], err); + posix.kill(posix.getpid(), .STOP) catch |err| forkChildErrReport(io, err_pipe[1], err); } const err = switch (self.expand_arg0) { .expand => posix.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), .no_expand => posix.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), }; - forkChildErrReport(err_pipe[1], err); + forkChildErrReport(io, err_pipe[1], err); } // we are the parent @@ -750,7 +750,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void { self.progress_node.setIpcFd(prog_pipe[0]); } -fn spawnWindows(self: *ChildProcess) SpawnError!void { +fn spawnWindows(self: *Child) SpawnError!void { var saAttr = windows.SECURITY_ATTRIBUTES{ .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), .bInheritHandle = windows.TRUE, @@ -880,7 +880,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { const app_name_wtf8 = self.argv[0]; const app_name_is_absolute = fs.path.isAbsolute(app_name_wtf8); - // the cwd set in ChildProcess is in effect when choosing the executable path + // the cwd set in Child is in effect when choosing the executable path // to match posix semantics var cwd_path_w_needs_free = false; const cwd_path_w = x: { @@ -965,7 +965,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { // If the app name had path separators, that disallows PATH searching, // and there's no need to search the PATH if the app name is absolute. // We still search the path if the cwd is absolute because of the - // "cwd set in ChildProcess is in effect when choosing the executable path + // "cwd set in Child is in effect when choosing the executable path // to match posix semantics" behavior--we don't want to skip searching // the PATH just because we were trying to set the cwd of the child process. if (app_dirname_w != null or app_name_is_absolute) { @@ -1039,8 +1039,8 @@ fn destroyPipe(pipe: [2]posix.fd_t) void { // Child of fork calls this to report an error to the fork parent. // Then the child exits. -fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { - writeIntFd(fd, @as(ErrInt, @intFromError(err))) catch {}; +fn forkChildErrReport(io: Io, fd: i32, err: Child.SpawnError) noreturn { + writeIntFd(io, fd, @as(ErrInt, @intFromError(err))) catch {}; // If we're linking libc, some naughty applications may have registered atexit handlers // which we really do not want to run in the fork child. I caught LLVM doing this and // it caused a deadlock instead of doing an exit syscall. In the words of Avril Lavigne, @@ -1052,9 +1052,9 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { posix.system.exit(1); } -fn writeIntFd(fd: i32, value: ErrInt) !void { +fn writeIntFd(io: Io, fd: i32, value: ErrInt) !void { var buffer: [8]u8 = undefined; - var fw: File.Writer = .initStreaming(.{ .handle = fd }, &buffer); + var fw: File.Writer = .initStreaming(.{ .handle = fd }, io, &buffer); fw.interface.writeInt(u64, value, .little) catch unreachable; fw.interface.flush() catch return error.SystemResources; } @@ -1078,7 +1078,7 @@ const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8); /// Note: `app_buf` should not contain any leading path separators. /// Note: If the dir is the cwd, dir_buf should be empty (len = 0). fn windowsCreateProcessPathExt( - allocator: mem.Allocator, + allocator: Allocator, dir_buf: *ArrayList(u16), app_buf: *ArrayList(u16), pathext: [:0]const u16, @@ -1525,9 +1525,9 @@ const WindowsCommandLineCache = struct { script_cmd_line: ?[:0]u16 = null, cmd_exe_path: ?[:0]u16 = null, argv: []const []const u8, - allocator: mem.Allocator, + allocator: Allocator, - fn init(allocator: mem.Allocator, argv: []const []const u8) WindowsCommandLineCache { + fn init(allocator: Allocator, argv: []const []const u8) WindowsCommandLineCache { return .{ .allocator = allocator, .argv = argv, @@ -1571,7 +1571,7 @@ const WindowsCommandLineCache = struct { /// Returns the absolute path of `cmd.exe` within the Windows system directory. /// The caller owns the returned slice. -fn windowsCmdExePath(allocator: mem.Allocator) error{ OutOfMemory, Unexpected }![:0]u16 { +fn windowsCmdExePath(allocator: Allocator) error{ OutOfMemory, Unexpected }![:0]u16 { var buf = try ArrayList(u16).initCapacity(allocator, 128); errdefer buf.deinit(allocator); while (true) { @@ -1608,7 +1608,7 @@ const ArgvToCommandLineError = error{ OutOfMemory, InvalidWtf8, InvalidArg0 }; /// /// When executing `.bat`/`.cmd` scripts, use `argvToScriptCommandLineWindows` instead. fn argvToCommandLineWindows( - allocator: mem.Allocator, + allocator: Allocator, argv: []const []const u8, ) ArgvToCommandLineError![:0]u16 { var buf = std.array_list.Managed(u8).init(allocator); @@ -1784,7 +1784,7 @@ const ArgvToScriptCommandLineError = error{ /// Should only be used when spawning `.bat`/`.cmd` scripts, see `argvToCommandLineWindows` otherwise. /// The `.bat`/`.cmd` file must be known to both have the `.bat`/`.cmd` extension and exist on the filesystem. fn argvToScriptCommandLineWindows( - allocator: mem.Allocator, + allocator: Allocator, /// Path to the `.bat`/`.cmd` script. If this path is relative, it is assumed to be relative to the CWD. /// The script must have been verified to exist at this path before calling this function. script_path: []const u16, diff --git a/lib/std/tar.zig b/lib/std/tar.zig index 5e7215f1d7..7bb20a9959 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -610,7 +610,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp } }, .file => { - if (createDirAndFile(io, dir, file_name, fileMode(file.mode, options))) |fs_file| { + if (createDirAndFile(io, dir, file_name, filePermissions(file.mode, options))) |fs_file| { defer fs_file.close(io); var file_writer = fs_file.writer(io, &file_contents_buffer); try it.streamRemaining(file, &file_writer.interface); @@ -638,12 +638,12 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp } } -fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mode) !Io.File { - const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }) catch |err| { +fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, permissions: Io.File.Permissions) !Io.File { + const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { try dir.makePath(io, dir_name); - return try dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }); + return try dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }); } } return err; @@ -880,9 +880,9 @@ test "create file and symlink" { var root = testing.tmpDir(.{}); defer root.cleanup(); - var file = try createDirAndFile(io, root.dir, "file1", default_mode); + var file = try createDirAndFile(io, root.dir, "file1", .default_file); file.close(io); - file = try createDirAndFile(io, root.dir, "a/b/c/file2", default_mode); + file = try createDirAndFile(io, root.dir, "a/b/c/file2", .default_file); file.close(io); createDirAndSymlink(io, root.dir, "a/b/c/file2", "symlink1") catch |err| { @@ -894,7 +894,7 @@ test "create file and symlink" { // Danglink symlnik, file created later try createDirAndSymlink(io, root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); - file = try createDirAndFile(io, root.dir, "g/h/i/file4", default_mode); + file = try createDirAndFile(io, root.dir, "g/h/i/file4", .default_file); file.close(io); } @@ -1118,30 +1118,30 @@ fn normalizePath(bytes: []u8) []u8 { return bytes; } -const default_mode = Io.File.default_mode; - // File system mode based on tar header mode and mode_mode options. -fn fileMode(mode: u32, options: PipeOptions) Io.File.Mode { +fn filePermissions(mode: u32, options: PipeOptions) Io.File.Permissions { + const default_mode = 0o666; + if (!std.fs.has_executable_bit or options.mode_mode == .ignore) - return default_mode; + return .fromMode(default_mode); const S = std.posix.S; // The mode from the tar file is inspected for the owner executable bit. if (mode & S.IXUSR == 0) - return default_mode; + return .fromMode(default_mode); // This bit is copied to the group and other executable bits. // Other bits of the mode are left as the default when creating files. - return default_mode | S.IXUSR | S.IXGRP | S.IXOTH; + return .fromMode(default_mode | S.IXUSR | S.IXGRP | S.IXOTH); } -test fileMode { +test filePermissions { if (!std.fs.has_executable_bit) return error.SkipZigTest; - try testing.expectEqual(default_mode, fileMode(0o744, PipeOptions{ .mode_mode = .ignore })); - try testing.expectEqual(0o777, fileMode(0o744, PipeOptions{})); - try testing.expectEqual(0o666, fileMode(0o644, PipeOptions{})); - try testing.expectEqual(0o666, fileMode(0o655, PipeOptions{})); + try testing.expectEqual(0o666, filePermissions(0o744, PipeOptions{ .mode_mode = .ignore })); + try testing.expectEqual(0o777, filePermissions(0o744, PipeOptions{})); + try testing.expectEqual(0o666, filePermissions(0o644, PipeOptions{})); + try testing.expectEqual(0o666, filePermissions(0o655, PipeOptions{})); } test "executable bit" { diff --git a/src/Compilation.zig b/src/Compilation.zig index 617421e279..c63fa9a3c1 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5782,7 +5782,7 @@ pub fn translateC( } // Just to save disk space, we delete the file because it is never needed again. - cache_tmp_dir.deleteFile(dep_basename) catch |err| { + cache_tmp_dir.deleteFile(io, dep_basename) catch |err| { log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); }; } @@ -6314,11 +6314,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr } // Just to save disk space, we delete the files that are never needed again. - defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(diag_file_path)) catch |err| switch (err) { + defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(diag_file_path)) catch |err| switch (err) { error.FileNotFound => {}, // the file wasn't created due to an error we reported else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }), }; - defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(dep_file_path)) catch |err| switch (err) { + defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(dep_file_path)) catch |err| switch (err) { error.FileNotFound => {}, // the file wasn't created due to an error we reported else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }), }; @@ -6329,7 +6329,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr child.stdout_behavior = .Inherit; child.stderr_behavior = .Inherit; - const term = child.spawnAndWait() catch |err| { + const term = child.spawnAndWait(io) catch |err| { return comp.failCObj(c_object, "failed to spawn zig clang (passthrough mode) {s}: {s}", .{ argv.items[0], @errorName(err) }); }; switch (term) { @@ -6347,7 +6347,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr child.stdout_behavior = .Ignore; child.stderr_behavior = .Pipe; - try child.spawn(); + try child.spawn(io); var stderr_reader = child.stderr.?.readerStreaming(io, &.{}); const stderr = try stderr_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); @@ -6723,6 +6723,7 @@ fn spawnZigRc( argv: []const []const u8, child_progress_node: std.Progress.Node, ) !void { + const io = comp.io; var node_name: std.ArrayList(u8) = .empty; defer node_name.deinit(arena); @@ -6732,8 +6733,8 @@ fn spawnZigRc( child.stderr_behavior = .Pipe; child.progress_node = child_progress_node; - child.spawn() catch |err| { - return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) }); + child.spawn(io) catch |err| { + return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {t}", .{ argv[0], err }); }; var poller = std.Io.poll(comp.gpa, enum { stdout, stderr }, .{ diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 3552a7fc06..e9753734e9 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -1347,7 +1347,7 @@ fn unzip( .diagnostics = &diagnostics, }) catch |err| return f.fail(f.location_tok, try eb.printString("zip extract failed: {t}", .{err})); - cache_root.handle.deleteFile(&zip_path) catch |err| + cache_root.handle.deleteFile(io, &zip_path) catch |err| return f.fail(f.location_tok, try eb.printString("delete temporary zip failed: {t}", .{err})); return .{ .root_dir = diagnostics.root_dir }; @@ -1547,7 +1547,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute .fs_path = fs_path, .failure = undefined, // to be populated by the worker }; - group.async(io, workerDeleteFile, .{ root_dir, deleted_file }); + group.async(io, workerDeleteFile, .{ io, root_dir, deleted_file }); try deleted_files.append(deleted_file); continue; } @@ -1669,8 +1669,8 @@ fn workerHashFile(dir: Io.Dir, hashed_file: *HashedFile) void { hashed_file.failure = hashFileFallible(dir, hashed_file); } -fn workerDeleteFile(dir: Io.Dir, deleted_file: *DeletedFile) void { - deleted_file.failure = deleteFileFallible(dir, deleted_file); +fn workerDeleteFile(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) void { + deleted_file.failure = deleteFileFallible(io, dir, deleted_file); } fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Error!void { @@ -1712,8 +1712,8 @@ fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Er hashed_file.size = file_size; } -fn deleteFileFallible(dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { - try dir.deleteFile(deleted_file.fs_path); +fn deleteFileFallible(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { + try dir.deleteFile(io, deleted_file.fs_path); } fn setExecutable(file: Io.File) !void { diff --git a/src/link.zig b/src/link.zig index ff6d938e6f..7ebe1c6ba2 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1235,22 +1235,26 @@ pub const File = struct { ty: InternPool.Index, }; - pub fn determineMode( + pub fn determinePermissions( output_mode: std.builtin.OutputMode, link_mode: std.builtin.LinkMode, - ) Io.File.Mode { + ) Io.File.Permissions { // On common systems with a 0o022 umask, 0o777 will still result in a file created // with 0o755 permissions, but it works appropriately if the system is configured // more leniently. As another data point, C's fopen seems to open files with the // 666 mode. - const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777; + const executable_mode: Io.FilePermissions = if (builtin.target.os.tag == .windows) + .default_file + else + .fromMode(0o777); + switch (output_mode) { .Lib => return switch (link_mode) { .dynamic => executable_mode, - .static => Io.File.default_mode, + .static => .default_file, }, .Exe => return executable_mode, - .Obj => return Io.File.default_mode, + .Obj => return .default_file, } } diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 6920c12762..e3127b24bf 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -1608,13 +1608,13 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi child.stdout_behavior = .Inherit; child.stderr_behavior = .Inherit; - break :term child.spawnAndWait(); + break :term child.spawnAndWait(io); } else term: { child.stdin_behavior = .Ignore; child.stdout_behavior = .Ignore; child.stderr_behavior = .Pipe; - child.spawn() catch |err| break :term err; + child.spawn(io) catch |err| break :term err; var stderr_reader = child.stderr.?.readerStreaming(io, &.{}); stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited); break :term child.wait(); @@ -1658,13 +1658,13 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi rsp_child.stdout_behavior = .Inherit; rsp_child.stderr_behavior = .Inherit; - break :term rsp_child.spawnAndWait() catch |err| break :err err; + break :term rsp_child.spawnAndWait(io) catch |err| break :err err; } else { rsp_child.stdin_behavior = .Ignore; rsp_child.stdout_behavior = .Ignore; rsp_child.stderr_behavior = .Pipe; - rsp_child.spawn() catch |err| break :err err; + rsp_child.spawn(io) catch |err| break :err err; var stderr_reader = rsp_child.stderr.?.readerStreaming(io, &.{}); stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited); break :term rsp_child.wait() catch |err| break :err err; diff --git a/src/main.zig b/src/main.zig index a832a79dbe..3835e75949 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4457,7 +4457,7 @@ fn runOrTest( const term_result = t: { std.debug.lockStdErr(); defer std.debug.unlockStdErr(); - break :t child.spawnAndWait(); + break :t child.spawnAndWait(io); }; const term = term_result catch |err| { try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); @@ -4512,6 +4512,7 @@ fn runOrTestHotSwap( all_args: []const []const u8, runtime_args_start: ?usize, ) !std.process.Child.Id { + const io = comp.io; const lf = comp.bin_file.?; const exe_path = switch (builtin.target.os.tag) { @@ -4593,7 +4594,7 @@ fn runOrTestHotSwap( child.stdout_behavior = .Inherit; child.stderr_behavior = .Inherit; - try child.spawn(); + try child.spawn(io); return child.id; }, @@ -5419,8 +5420,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) const term = t: { std.debug.lockStdErr(); defer std.debug.unlockStdErr(); - break :t child.spawnAndWait() catch |err| { - fatal("failed to spawn build runner {s}: {s}", .{ child_argv.items[0], @errorName(err) }); + break :t child.spawnAndWait(io) catch |err| { + fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err }); }; }; @@ -5444,7 +5445,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) dirs.local_cache, tmp_sub_path, @errorName(err), }); }; - dirs.local_cache.handle.deleteFile(tmp_sub_path) catch {}; + dirs.local_cache.handle.deleteFile(io, tmp_sub_path) catch {}; var it = mem.splitScalar(u8, stdout, '\n'); var any_errors = false; @@ -5685,7 +5686,7 @@ fn jitCmd( child.stdout_behavior = if (options.capture == null) .Inherit else .Pipe; child.stderr_behavior = .Inherit; - try child.spawn(); + try child.spawn(io); if (options.capture) |ptr| { var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); diff --git a/test/src/Cases.zig b/test/src/Cases.zig index bf3eade8f4..82b59f722d 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -461,6 +461,7 @@ pub fn lowerToBuildSteps( parent_step: *std.Build.Step, options: CaseTestOptions, ) void { + const io = self.io; const host = b.resolveTargetQuery(.{}); const cases_dir_path = b.build_root.join(b.allocator, &.{ "test", "cases" }) catch @panic("OOM"); @@ -595,7 +596,7 @@ pub fn lowerToBuildSteps( }, .Execution => |expected_stdout| no_exec: { const run = if (case.target.result.ofmt == .c) run_step: { - if (getExternalExecutor(&host.result, &case.target.result, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(io, &host.result, &case.target.result, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; } diff --git a/test/standalone/child_process/main.zig b/test/standalone/child_process/main.zig index 2a28845a56..3aaec0f2b2 100644 --- a/test/standalone/child_process/main.zig +++ b/test/standalone/child_process/main.zig @@ -29,7 +29,7 @@ pub fn main() !void { child.stdin_behavior = .Pipe; child.stdout_behavior = .Pipe; child.stderr_behavior = .Inherit; - try child.spawn(); + try child.spawn(io); const child_stdin = child.stdin.?; try child_stdin.writeAll("hello from stdin"); // verified in child child_stdin.close(io); -- cgit v1.2.3 From b042e935228db5d46271d4d3d17afeb9ba5d7ce3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 10 Dec 2025 20:55:11 -0800 Subject: std: update tty config references in the build system --- lib/compiler/build_runner.zig | 208 ++++++++++++++++++++--------------------- lib/std/Build.zig | 60 ++++++------ lib/std/Build/Fuzz.zig | 20 ++-- lib/std/Build/Step.zig | 9 +- lib/std/Build/Step/Compile.zig | 10 +- lib/std/Build/Step/Run.zig | 68 +++++++------- lib/std/Build/WebServer.zig | 4 - lib/std/Io/File/Writer.zig | 41 +++++++- lib/std/debug.zig | 2 +- lib/std/log.zig | 30 +----- lib/std/testing.zig | 42 ++++----- lib/std/zig.zig | 12 +-- lib/std/zig/ErrorBundle.zig | 59 ++++++------ 13 files changed, 271 insertions(+), 294 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 05cd21ecdb..acba1a4621 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -14,7 +14,6 @@ const WebServer = std.Build.WebServer; const Allocator = std.mem.Allocator; const fatal = std.process.fatal; const Writer = std.Io.Writer; -const tty = std.Io.tty; pub const root = @import("@build"); pub const dependencies = @import("@dependencies"); @@ -435,9 +434,7 @@ pub fn main() !void { if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{}); } - const ttyconf = color.detectTtyConf(io); - - const main_progress_node = std.Progress.start(.{ + const main_progress_node = std.Progress.start(io, .{ .disable_printing = (color == .off), }); defer main_progress_node.end(); @@ -509,8 +506,6 @@ pub fn main() !void { .error_style = error_style, .multiline_errors = multiline_errors, .summary = summary orelse if (watch or webui_listen != null) .line else .failures, - - .ttyconf = ttyconf, }; defer { run.memory_blocked_steps.deinit(gpa); @@ -524,10 +519,10 @@ pub fn main() !void { prepare(arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) { error.DependencyLoopDetected => { - // Perhaps in the future there could be an Advanced Options flag such as - // --debug-build-runner-leaks which would make this code return instead of - // calling exit. - std.debug.lockStdErr(); + // Perhaps in the future there could be an Advanced Options flag + // such as --debug-build-runner-leaks which would make this code + // return instead of calling exit. + _ = std.debug.lockStderrWriter(&.{}); process.exit(1); }, else => |e| return e, @@ -545,7 +540,6 @@ pub fn main() !void { if (builtin.single_threaded) unreachable; // `fatal` above break :ws .init(.{ .gpa = gpa, - .ttyconf = ttyconf, .graph = &graph, .all_steps = run.step_stack.keys(), .root_prog_node = main_progress_node, @@ -560,9 +554,9 @@ pub fn main() !void { } rebuild: while (true) : (if (run.error_style.clearOnUpdate()) { - const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); - try bw.writeAll("\x1B[2J\x1B[3J\x1B[H"); + try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H"); }) { if (run.web_server) |*ws| ws.startBuild(); @@ -663,9 +657,6 @@ const Run = struct { memory_blocked_steps: std.ArrayList(*Step), /// Allocated into `gpa`. step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), - /// Similar to the `tty.Config` returned by `std.debug.lockStderrWriter`, - /// but also respects the '--color' flag. - ttyconf: tty.Config, claimed_rss: usize, error_style: ErrorStyle, @@ -839,7 +830,6 @@ fn runStepNames( var f = std.Build.Fuzz.init( gpa, io, - run.ttyconf, step_stack.keys(), parent_prog_node, mode, @@ -866,18 +856,20 @@ fn runStepNames( .none => break :summary, } - const w, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); - const ttyconf = run.ttyconf; + + const w = &stderr.interface; + const fwm = stderr.mode; const total_count = success_count + failure_count + pending_count + skipped_count; - ttyconf.setColor(w, .cyan) catch {}; - ttyconf.setColor(w, .bold) catch {}; + fwm.setColor(w, .cyan) catch {}; + fwm.setColor(w, .bold) catch {}; w.writeAll("Build Summary: ") catch {}; - ttyconf.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; w.print("{d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; { - ttyconf.setColor(w, .dim) catch {}; + fwm.setColor(w, .dim) catch {}; var first = true; if (skipped_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", skipped_count }) catch {}; @@ -888,12 +880,12 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - ttyconf.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; } if (test_count > 0) { w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; - ttyconf.setColor(w, .dim) catch {}; + fwm.setColor(w, .dim) catch {}; var first = true; if (test_skip_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", test_skip_count }) catch {}; @@ -912,7 +904,7 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - ttyconf.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; } w.writeAll("\n") catch {}; @@ -926,7 +918,7 @@ fn runStepNames( var print_node: PrintNode = .{ .parent = null }; if (step_names.len == 0) { print_node.last = true; - printTreeStep(b, b.default_step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, b.default_step, run, w, fwm, &print_node, &step_stack_copy) catch {}; } else { const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { var i: usize = step_names.len; @@ -945,7 +937,7 @@ fn runStepNames( for (step_names, 0..) |step_name, i| { const tls = b.top_level_steps.get(step_name).?; print_node.last = i + 1 == last_index; - printTreeStep(b, &tls.step, run, w, ttyconf, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, &tls.step, run, w, fwm, &print_node, &step_stack_copy) catch {}; } } w.writeByte('\n') catch {}; @@ -962,7 +954,7 @@ fn runStepNames( if (run.error_style.verboseContext()) break :code 1; // failure; print build command break :code 2; // failure; do not print build command }; - std.debug.lockStdErr(); + _ = std.debug.lockStderrWriter(&.{}); process.exit(code); } @@ -971,31 +963,31 @@ const PrintNode = struct { last: bool = false, }; -fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: tty.Config) !void { +fn printPrefix(node: *PrintNode, w: *Writer, fwm: File.Writer.Mode) !void { const parent = node.parent orelse return; if (parent.parent == null) return; - try printPrefix(parent, stderr, ttyconf); + try printPrefix(parent, w, fwm); if (parent.last) { - try stderr.writeAll(" "); + try w.writeAll(" "); } else { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "| ", - .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ + try w.writeAll(switch (fwm) { + .terminal_escaped => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ + else => "| ", }); } } -fn printChildNodePrefix(stderr: *Writer, ttyconf: tty.Config) !void { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "+- ", - .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ +fn printChildNodePrefix(w: *Writer, fwm: File.Writer.Mode) !void { + try w.writeAll(switch (fwm) { + .terminal_escaped => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ + else => "+- ", }); } fn printStepStatus( s: *Step, stderr: *Writer, - ttyconf: tty.Config, + fwm: File.Writer.Mode, run: *const Run, ) !void { switch (s.state) { @@ -1005,13 +997,13 @@ fn printStepStatus( .running => unreachable, .dependency_failure => { - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); try stderr.writeAll(" transitive failure\n"); - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); }, .success => { - try ttyconf.setColor(stderr, .green); + try fwm.setColor(stderr, .green); if (s.result_cached) { try stderr.writeAll(" cached"); } else if (s.test_results.test_count > 0) { @@ -1019,19 +1011,19 @@ fn printStepStatus( assert(s.test_results.test_count == pass_count + s.test_results.skip_count); try stderr.print(" {d} pass", .{pass_count}); if (s.test_results.skip_count > 0) { - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .yellow); + try fwm.setColor(stderr, .yellow); try stderr.print("{d} skip", .{s.test_results.skip_count}); } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); try stderr.print(" ({d} total)", .{s.test_results.test_count}); } else { try stderr.writeAll(" success"); } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); if (s.result_duration_ns) |ns| { - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); if (ns >= std.time.ns_per_min) { try stderr.print(" {d}m", .{ns / std.time.ns_per_min}); } else if (ns >= std.time.ns_per_s) { @@ -1043,11 +1035,11 @@ fn printStepStatus( } else { try stderr.print(" {d}ns", .{ns}); } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); } if (s.result_peak_rss != 0) { const rss = s.result_peak_rss; - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); if (rss >= 1000_000_000) { try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); } else if (rss >= 1000_000) { @@ -1057,25 +1049,25 @@ fn printStepStatus( } else { try stderr.print(" MaxRSS:{d}B", .{rss}); } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); } try stderr.writeAll("\n"); }, .skipped, .skipped_oom => |skip| { - try ttyconf.setColor(stderr, .yellow); + try fwm.setColor(stderr, .yellow); try stderr.writeAll(" skipped"); if (skip == .skipped_oom) { try stderr.writeAll(" (not enough memory)"); - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); - try ttyconf.setColor(stderr, .yellow); + try fwm.setColor(stderr, .yellow); } try stderr.writeAll("\n"); - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); }, .failure => { - try printStepFailure(s, stderr, ttyconf, false); - try ttyconf.setColor(stderr, .reset); + try printStepFailure(s, stderr, fwm, false); + try fwm.setColor(stderr, .reset); }, } } @@ -1083,48 +1075,48 @@ fn printStepStatus( fn printStepFailure( s: *Step, stderr: *Writer, - ttyconf: tty.Config, + fwm: File.Writer.Mode, dim: bool, ) !void { if (s.result_error_bundle.errorMessageCount() > 0) { - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print(" {d} errors\n", .{ s.result_error_bundle.errorMessageCount(), }); } else if (!s.test_results.isSuccess()) { // These first values include all of the test "statuses". Every test is either passsed, // skipped, failed, crashed, or timed out. - try ttyconf.setColor(stderr, .green); + try fwm.setColor(stderr, .green); try stderr.print(" {d} pass", .{s.test_results.passCount()}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); if (s.test_results.skip_count > 0) { try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .yellow); + try fwm.setColor(stderr, .yellow); try stderr.print("{d} skip", .{s.test_results.skip_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } if (s.test_results.fail_count > 0) { try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print("{d} fail", .{s.test_results.fail_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } if (s.test_results.crash_count > 0) { try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print("{d} crash", .{s.test_results.crash_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } if (s.test_results.timeout_count > 0) { try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print("{d} timeout", .{s.test_results.timeout_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } try stderr.print(" ({d} total)", .{s.test_results.test_count}); @@ -1134,10 +1126,10 @@ fn printStepFailure( // 2 pass, 1 skip, 2 fail (5 total); 2 leaks if (s.test_results.leak_count > 0) { try stderr.writeAll("; "); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print("{d} leaks", .{s.test_results.leak_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } // It's usually not helpful to know how many error logs there were because they tend to @@ -1151,19 +1143,19 @@ fn printStepFailure( }; if (show_err_logs) { try stderr.writeAll("; "); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.print("{d} error logs", .{s.test_results.log_err_count}); - try ttyconf.setColor(stderr, .reset); - if (dim) try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .reset); + if (dim) try fwm.setColor(stderr, .dim); } try stderr.writeAll("\n"); } else if (s.result_error_msgs.items.len > 0) { - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.writeAll(" failure\n"); } else { assert(s.result_stderr.len > 0); - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.writeAll(" stderr\n"); } } @@ -1173,7 +1165,7 @@ fn printTreeStep( s: *Step, run: *const Run, stderr: *Writer, - ttyconf: tty.Config, + fwm: File.Writer.Mode, parent_node: *PrintNode, step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), ) !void { @@ -1186,26 +1178,26 @@ fn printTreeStep( .failures => s.state == .success, }; if (skip) return; - try printPrefix(parent_node, stderr, ttyconf); + try printPrefix(parent_node, stderr, fwm); if (parent_node.parent != null) { if (parent_node.last) { - try printChildNodePrefix(stderr, ttyconf); + try printChildNodePrefix(stderr, fwm); } else { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "+- ", - .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ + try stderr.writeAll(switch (fwm) { + .terminal_escaped => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ + else => "+- ", }); } } - if (!first) try ttyconf.setColor(stderr, .dim); + if (!first) try fwm.setColor(stderr, .dim); // dep_prefix omitted here because it is redundant with the tree. try stderr.writeAll(s.name); if (first) { - try printStepStatus(s, stderr, ttyconf, run); + try printStepStatus(s, stderr, fwm, run); const last_index = if (summary == .all) s.dependencies.items.len -| 1 else blk: { var i: usize = s.dependencies.items.len; @@ -1227,7 +1219,7 @@ fn printTreeStep( .parent = parent_node, .last = i == last_index, }; - try printTreeStep(b, dep, run, stderr, ttyconf, &print_node, step_stack); + try printTreeStep(b, dep, run, stderr, fwm, &print_node, step_stack); } } else { if (s.dependencies.items.len == 0) { @@ -1237,7 +1229,7 @@ fn printTreeStep( s.dependencies.items.len, }); } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); } } @@ -1368,7 +1360,6 @@ fn workerMakeOneStep( .progress_node = sub_prog_node, .watch = run.watch, .web_server = if (run.web_server) |*ws| ws else null, - .ttyconf = run.ttyconf, .unit_test_timeout_ns = run.unit_test_timeout_ns, .gpa = gpa, }); @@ -1378,10 +1369,9 @@ fn workerMakeOneStep( const show_error_msgs = s.result_error_msgs.items.len > 0; const show_stderr = s.result_stderr.len > 0; if (show_error_msgs or show_compile_errors or show_stderr) { - const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const stderr = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); - const ttyconf = run.ttyconf; - printErrorMessages(gpa, s, .{}, bw, ttyconf, run.error_style, run.multiline_errors) catch {}; + printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {}; } handle_result: { @@ -1449,7 +1439,7 @@ pub fn printErrorMessages( failing_step: *Step, options: std.zig.ErrorBundle.RenderOptions, stderr: *Writer, - ttyconf: tty.Config, + fwm: File.Writer.Mode, error_style: ErrorStyle, multiline_errors: MultilineErrors, ) !void { @@ -1464,29 +1454,29 @@ pub fn printErrorMessages( } // Now, `step_stack` has the subtree that we want to print, in reverse order. - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); var indent: usize = 0; while (step_stack.pop()) |s| : (indent += 1) { if (indent > 0) { try stderr.splatByteAll(' ', (indent - 1) * 3); - try printChildNodePrefix(stderr, ttyconf); + try printChildNodePrefix(stderr, fwm); } try stderr.writeAll(s.name); if (s == failing_step) { - try printStepFailure(s, stderr, ttyconf, true); + try printStepFailure(s, stderr, fwm, true); } else { try stderr.writeAll("\n"); } } - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); } else { // Just print the failing step itself. - try ttyconf.setColor(stderr, .dim); + try fwm.setColor(stderr, .dim); try stderr.writeAll(failing_step.name); - try printStepFailure(failing_step, stderr, ttyconf, true); - try ttyconf.setColor(stderr, .reset); + try printStepFailure(failing_step, stderr, fwm, true); + try fwm.setColor(stderr, .reset); } if (failing_step.result_stderr.len > 0) { @@ -1496,12 +1486,12 @@ pub fn printErrorMessages( } } - try failing_step.result_error_bundle.renderToWriter(options, stderr, ttyconf); + try failing_step.result_error_bundle.renderToWriter(options, stderr, fwm); for (failing_step.result_error_msgs.items) |msg| { - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.writeAll("error:"); - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); if (std.mem.indexOfScalar(u8, msg, '\n') == null) { try stderr.print(" {s}\n", .{msg}); } else switch (multiline_errors) { @@ -1519,9 +1509,9 @@ pub fn printErrorMessages( if (error_style.verboseContext()) { if (failing_step.result_failed_command) |cmd_str| { - try ttyconf.setColor(stderr, .red); + try fwm.setColor(stderr, .red); try stderr.writeAll("failed command: "); - try ttyconf.setColor(stderr, .reset); + try fwm.setColor(stderr, .reset); try stderr.writeAll(cmd_str); try stderr.writeByte('\n'); } diff --git a/lib/std/Build.zig b/lib/std/Build.zig index ae2ab1c4d0..085254fdde 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -5,9 +5,8 @@ const std = @import("std.zig"); const Io = std.Io; const fs = std.fs; const mem = std.mem; -const debug = std.debug; const panic = std.debug.panic; -const assert = debug.assert; +const assert = std.debug.assert; const log = std.log; const StringHashMap = std.StringHashMap; const Allocator = std.mem.Allocator; @@ -2090,7 +2089,7 @@ pub fn dependencyFromBuildZig( } const full_path = b.pathFromRoot("build.zig.zon"); - debug.panic("'{}' is not a build.zig struct of a dependency in '{s}'", .{ build_zig, full_path }); + std.debug.panic("'{}' is not a build.zig struct of a dependency in '{s}'", .{ build_zig, full_path }); } fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { @@ -2249,9 +2248,9 @@ pub const GeneratedFile = struct { pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { return gen.path orelse { - const w, const ttyconf = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.step, w, ttyconf, src_builder, asking_step) catch {}; - debug.unlockStderrWriter(); + const stderr = std.debug.lockStderrWriter(&.{}); + dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {}; + std.debug.unlockStderrWriter(); @panic("misconfigured build script"); }; } @@ -2458,9 +2457,9 @@ pub const LazyPath = union(enum) { var file_path: Cache.Path = .{ .root_dir = Cache.Directory.cwd(), .sub_path = gen.file.path orelse { - const w, const ttyconf = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.file.step, w, ttyconf, src_builder, asking_step) catch {}; - debug.unlockStderrWriter(); + const stderr = std.debug.lockStderrWriter(&.{}); + dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {}; + std.debug.unlockStderrWriter(); @panic("misconfigured build script"); }, }; @@ -2550,37 +2549,40 @@ fn dumpBadDirnameHelp( comptime msg: []const u8, args: anytype, ) anyerror!void { - const w, const tty_config = debug.lockStderrWriter(&.{}); - defer debug.unlockStderrWriter(); + const stderr = std.debug.lockStderrWriter(&.{}); + defer std.debug.unlockStderrWriter(); + + const w = &stderr.interface; + const fwm = stderr.mode; try w.print(msg, args); if (fail_step) |s| { - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; - s.dump(w, tty_config); + s.dump(w, fwm); } if (asking_step) |as| { - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; - as.dump(w, tty_config); + as.dump(w, fwm); } - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; } /// In this function the stderr mutex has already been locked. pub fn dumpBadGetPathHelp( s: *Step, - w: *std.Io.Writer, - tty_config: std.Io.tty.Config, + w: *Io.Writer, + fwm: File.Writer.Mode, src_builder: *Build, asking_step: ?*Step, ) anyerror!void { @@ -2594,21 +2596,21 @@ pub fn dumpBadGetPathHelp( s.name, }); - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; - s.dump(w, tty_config); + s.dump(w, fwm); if (asking_step) |as| { - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; - as.dump(w, tty_config); + as.dump(w, fwm); } - tty_config.setColor(w, .red) catch {}; + fwm.setColor(w, .red) catch {}; try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; } pub const InstallDir = union(enum) { diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index 8837d7d527..c2b7d1e9e9 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -9,14 +9,12 @@ const Allocator = std.mem.Allocator; const log = std.log; const Coverage = std.debug.Coverage; const abi = Build.abi.fuzz; -const tty = std.Io.tty; const Fuzz = @This(); const build_runner = @import("root"); gpa: Allocator, io: Io, -ttyconf: tty.Config, mode: Mode, /// Allocated into `gpa`. @@ -77,7 +75,6 @@ const CoverageMap = struct { pub fn init( gpa: Allocator, io: Io, - ttyconf: tty.Config, all_steps: []const *Build.Step, root_prog_node: std.Progress.Node, mode: Mode, @@ -95,7 +92,7 @@ pub fn init( if (run.producer == null) continue; if (run.fuzz_tests.items.len == 0) continue; try steps.append(gpa, run); - rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, ttyconf, rebuild_node }); + rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, rebuild_node }); } if (steps.items.len == 0) fatal("no fuzz tests found", .{}); @@ -115,7 +112,6 @@ pub fn init( return .{ .gpa = gpa, .io = io, - .ttyconf = ttyconf, .mode = mode, .run_steps = run_steps, .group = .init, @@ -154,14 +150,14 @@ pub fn deinit(fuzz: *Fuzz) void { fuzz.gpa.free(fuzz.run_steps); } -fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) void { - rebuildTestsWorkerRunFallible(run, gpa, ttyconf, parent_prog_node) catch |err| { +fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) void { + rebuildTestsWorkerRunFallible(run, gpa, parent_prog_node) catch |err| { const compile = run.producer.?; log.err("step '{s}': failed to rebuild in fuzz mode: {t}", .{ compile.step.name, err }); }; } -fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) !void { +fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void { const compile = run.producer.?; const prog_node = parent_prog_node.start(compile.step.name, 0); defer prog_node.end(); @@ -174,9 +170,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Co if (show_error_msgs or show_compile_errors or show_stderr) { var buf: [256]u8 = undefined; - const w, _ = std.debug.lockStderrWriter(&buf); + const stderr = std.debug.lockStderrWriter(&buf); defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &compile.step, .{}, w, ttyconf, .verbose, .indent) catch {}; + build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {}; } const rebuilt_bin_path = result catch |err| switch (err) { @@ -200,9 +196,9 @@ fn fuzzWorkerRun( run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) { error.MakeFailed => { var buf: [256]u8 = undefined; - const w, _ = std.debug.lockStderrWriter(&buf); + const stderr = std.debug.lockStderrWriter(&buf); defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &run.step, .{}, w, fuzz.ttyconf, .verbose, .indent) catch {}; + build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {}; return; }, else => { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 9c7fcc757f..0df58b24b7 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -117,7 +117,6 @@ pub const MakeOptions = struct { // it currently breaks because `std.net.Address` doesn't work there. Work around for now. .wasm32 => void, }, - ttyconf: std.Io.tty.Config, /// If set, this is a timeout to enforce on all individual unit tests, in nanoseconds. unit_test_timeout_ns: ?u64, /// Not to be confused with `Build.allocator`, which is an alias of `Build.graph.arena`. @@ -329,16 +328,16 @@ pub fn cast(step: *Step, comptime T: type) ?*T { } /// For debugging purposes, prints identifying information about this Step. -pub fn dump(step: *Step, w: *Io.Writer, tty_config: Io.tty.Config) void { +pub fn dump(step: *Step, w: *Io.Writer, fwm: Io.File.Writer.Mode) void { if (step.debug_stack_trace.instruction_addresses.len > 0) { w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; - std.debug.writeStackTrace(&step.debug_stack_trace, w, tty_config) catch {}; + std.debug.writeStackTrace(&step.debug_stack_trace, w, fwm) catch {}; } else { const field = "debug_stack_frames_count"; comptime assert(@hasField(Build, field)); - tty_config.setColor(w, .yellow) catch {}; + fwm.setColor(w, .yellow) catch {}; w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {}; - tty_config.setColor(w, .reset) catch {}; + fwm.setColor(w, .reset) catch {}; } } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index dfa5460981..d703e55b87 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -926,15 +926,15 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking const maybe_path: ?*GeneratedFile = @field(compile, tag_name); const generated_file = maybe_path orelse { - const w, const ttyconf = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; + const stderr = std.debug.lockStderrWriter(&.{}); + std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {}; std.debug.unlockStderrWriter(); @panic("missing emit option for " ++ tag_name); }; const path = generated_file.path orelse { - const w, const ttyconf = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; + const stderr = std.debug.lockStderrWriter(&.{}); + std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {}; std.debug.unlockStderrWriter(); @panic(tag_name ++ " is null. Is there a missing step dependency?"); }; @@ -1904,7 +1904,7 @@ fn checkCompileErrors(compile: *Compile) !void { try actual_eb.renderToWriter(.{ .include_reference_trace = false, .include_source_line = false, - }, &aw.writer, .no_color); + }, &aw.writer, .streaming); break :ae try aw.toOwnedSlice(); }; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 95024061d8..8aafc77820 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -5,7 +5,7 @@ const std = @import("std"); const Io = std.Io; const Build = std.Build; const Step = std.Build.Step; -const fs = std.fs; +const Dir = std.Io.Dir; const mem = std.mem; const process = std.process; const EnvMap = std.process.EnvMap; @@ -26,19 +26,7 @@ cwd: ?Build.LazyPath, env_map: ?*EnvMap, /// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables. -color: enum { - /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset. - enable, - /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset. - disable, - /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`. - inherit, - /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`. - auto, - /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables. - /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`. - manual, -} = .auto, +color: Color = .auto, /// When `true` prevents `ZIG_PROGRESS` environment variable from being passed /// to the child process, which otherwise would be used for the child to send @@ -112,6 +100,20 @@ rebuilt_executable: ?Path, /// If this Run step was produced by a Compile step, it is tracked here. producer: ?*Step.Compile, +pub const Color = enum { + /// `CLICOLOR_FORCE` is set, and `NO_COLOR` is unset. + enable, + /// `NO_COLOR` is set, and `CLICOLOR_FORCE` is unset. + disable, + /// If the build runner is using color, equivalent to `.enable`. Otherwise, equivalent to `.disable`. + inherit, + /// If stderr is captured or checked, equivalent to `.disable`. Otherwise, equivalent to `.inherit`. + auto, + /// The build runner does not modify the `CLICOLOR_FORCE` or `NO_COLOR` environment variables. + /// They are treated like normal variables, so can be controlled through `setEnvironmentVariable`. + manual, +}; + pub const StdIn = union(enum) { none, bytes: []const u8, @@ -565,7 +567,7 @@ pub fn addPathDir(run: *Run, search_path: []const u8) void { if (prev_path) |pp| { const new_path = b.fmt("{s}{c}{s}", .{ pp, - if (use_wine) fs.path.delimiter_windows else fs.path.delimiter, + if (use_wine) Dir.path.delimiter_windows else Dir.path.delimiter, search_path, }); env_map.put(key, new_path) catch @panic("OOM"); @@ -748,7 +750,7 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { const b = run.step.owner; const path_str = path.toString(b.graph.arena) catch @panic("OOM"); - if (std.fs.path.isAbsolute(path_str)) { + if (Dir.path.isAbsolute(path_str)) { // Absolute paths don't need changing. return path_str; } @@ -756,19 +758,19 @@ fn convertPathArg(run: *Run, path: Build.Cache.Path) []const u8 { const child_lazy_cwd = run.cwd orelse break :rel path_str; const child_cwd = child_lazy_cwd.getPath3(b, &run.step).toString(b.graph.arena) catch @panic("OOM"); // Convert it from relative to *our* cwd, to relative to the *child's* cwd. - break :rel std.fs.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM"); + break :rel Dir.path.relative(b.graph.arena, child_cwd, path_str) catch @panic("OOM"); }; // Not every path can be made relative, e.g. if the path and the child cwd are on different // disk designators on Windows. In that case, `relative` will return an absolute path which we can // just return. - if (std.fs.path.isAbsolute(child_cwd_rel)) { + if (Dir.path.isAbsolute(child_cwd_rel)) { return child_cwd_rel; } // We're not done yet. In some cases this path must be prefixed with './': // * On POSIX, the executable name cannot be a single component like 'foo' // * Some executables might treat a leading '-' like a flag, which we must avoid // There's no harm in it, so just *always* apply this prefix. - return std.fs.path.join(b.graph.arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); + return Dir.path.join(b.graph.arena, &.{ ".", child_cwd_rel }) catch @panic("OOM"); } const IndexedOutput = struct { @@ -965,11 +967,11 @@ fn make(step: *Step, options: Step.MakeOptions) !void { &digest, ); - const output_dir_path = "o" ++ fs.path.sep_str ++ &digest; + const output_dir_path = "o" ++ Dir.path.sep_str ++ &digest; for (output_placeholders.items) |placeholder| { const output_sub_path = b.pathJoin(&.{ output_dir_path, placeholder.output.basename }); const output_sub_dir_path = switch (placeholder.tag) { - .output_file => fs.path.dirname(output_sub_path).?, + .output_file => Dir.path.dirname(output_sub_path).?, .output_directory => output_sub_path, else => unreachable, }; @@ -995,13 +997,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { // We do not know the final output paths yet, use temp paths to run the command. const rand_int = std.crypto.random.int(u64); - const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); + const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); for (output_placeholders.items) |placeholder| { const output_components = .{ tmp_dir_path, placeholder.output.basename }; const output_sub_path = b.pathJoin(&output_components); const output_sub_dir_path = switch (placeholder.tag) { - .output_file => fs.path.dirname(output_sub_path).?, + .output_file => Dir.path.dirname(output_sub_path).?, .output_directory => output_sub_path, else => unreachable, }; @@ -1023,7 +1025,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, options, null); - const dep_file_dir = Io.Dir.cwd(); + const dep_file_dir = Dir.cwd(); const dep_file_basename = dep_output_file.generated_file.getPath2(b, step); if (has_side_effects) try man.addDepFile(dep_file_dir, dep_file_basename) @@ -1040,7 +1042,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { // Rename into place if (any_output) { - const o_sub_path = "o" ++ fs.path.sep_str ++ &digest; + const o_sub_path = "o" ++ Dir.path.sep_str ++ &digest; b.cache_root.handle.rename(tmp_dir_path, b.cache_root.handle, o_sub_path, io) catch |err| { if (err == error.PathAlreadyExists) { @@ -1139,12 +1141,11 @@ pub fn rerunInFuzzMode( const has_side_effects = false; const rand_int = std.crypto.random.int(u64); - const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); + const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, .{ .progress_node = prog_node, .watch = undefined, // not used by `runCommand` .web_server = null, // only needed for time reports - .ttyconf = fuzz.ttyconf, .unit_test_timeout_ns = null, // don't time out fuzz tests for now .gpa = fuzz.gpa, }, .{ @@ -1266,10 +1267,7 @@ fn runCommand( try env_map.put("NO_COLOR", "1"); env_map.remove("CLICOLOR_FORCE"); }, - .inherit => switch (options.ttyconf) { - .no_color, .windows_api => continue :color .disable, - .escape_codes => continue :color .enable, - }, + .inherit => {}, .auto => { const capture_stderr = run.captured_stderr != null or switch (run.stdio) { .check => |checks| checksContainStderr(checks.items), @@ -1464,7 +1462,7 @@ fn runCommand( captured.output.generated_file.path = output_path; const sub_path = b.pathJoin(&output_components); - const sub_path_dirname = fs.path.dirname(sub_path).?; + const sub_path_dirname = Dir.path.dirname(sub_path).?; b.cache_root.handle.makePath(io, sub_path_dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, sub_path_dirname, @errorName(err), @@ -1650,8 +1648,8 @@ fn spawnChildAndCollect( if (!run.disable_zig_progress and !inherit) { child.progress_node = options.progress_node; } - if (inherit) std.debug.lockStdErr(); - defer if (inherit) std.debug.unlockStdErr(); + if (inherit) _ = std.debug.lockStderrWriter(&.{}); + defer if (inherit) std.debug.unlockStderrWriter(); var timer = try std.time.Timer.start(); const res = try evalGeneric(run, &child); run.step.result_duration_ns = timer.read(); @@ -2277,7 +2275,7 @@ fn addPathForDynLibs(run: *Run, artifact: *Step.Compile) void { if (compile.root_module.resolved_target.?.result.os.tag == .windows and compile.isDynamicLibrary()) { - addPathDir(run, fs.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); + addPathDir(run, Dir.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?); } } } diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 5f633c5948..ccb7159192 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -2,7 +2,6 @@ gpa: Allocator, graph: *const Build.Graph, all_steps: []const *Build.Step, listen_address: net.IpAddress, -ttyconf: Io.tty.Config, root_prog_node: std.Progress.Node, watch: bool, @@ -52,7 +51,6 @@ pub fn notifyUpdate(ws: *WebServer) void { pub const Options = struct { gpa: Allocator, - ttyconf: Io.tty.Config, graph: *const std.Build.Graph, all_steps: []const *Build.Step, root_prog_node: std.Progress.Node, @@ -98,7 +96,6 @@ pub fn init(opts: Options) WebServer { return .{ .gpa = opts.gpa, - .ttyconf = opts.ttyconf, .graph = opts.graph, .all_steps = all_steps, .listen_address = opts.listen_address, @@ -233,7 +230,6 @@ pub fn finishBuild(ws: *WebServer, opts: struct { ws.fuzz = Fuzz.init( ws.gpa, ws.graph.io, - ws.ttyconf, ws.all_steps, ws.root_prog_node, .{ .forever = .{ .ws = ws } }, diff --git a/lib/std/Io/File/Writer.zig b/lib/std/Io/File/Writer.zig index 8f9f573a4b..03e4ad8a15 100644 --- a/lib/std/Io/File/Writer.zig +++ b/lib/std/Io/File/Writer.zig @@ -99,7 +99,7 @@ pub const Mode = union(enum) { pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || Io.Writer.Error; - pub fn setColor(mode: Mode, io_w: *Io.Writer, color: Color) Mode.SetColorError!void { + pub fn setColor(mode: Mode, io_w: *Io.Writer, color: Color) SetColorError!void { switch (mode) { .streaming, .positional, .streaming_simple, .positional_simple, .failure => return, .terminal_escaped => { @@ -155,6 +155,34 @@ pub const Mode = union(enum) { }, } } + + fn DecorateArgs(comptime Args: type) type { + const fields = @typeInfo(Args).@"struct".fields; + var new_fields: [fields.len]type = undefined; + for (fields, &new_fields) |old, *new| { + if (old.type == std.debug.FormatStackTrace) { + new.* = std.debug.FormatStackTrace.Decorated; + } else { + new.* = old.type; + } + } + return @Tuple(&new_fields); + } + + pub fn decorateArgs(file_writer_mode: std.Io.File.Writer.Mode, args: anytype) DecorateArgs(@TypeOf(args)) { + var new_args: DecorateArgs(@TypeOf(args)) = undefined; + inline for (args, &new_args) |old, *new| { + if (@TypeOf(old) == std.debug.FormatStackTrace) { + new.* = .{ + .stack_trace = old.stack_trace, + .file_writer_mode = file_writer_mode, + }; + } else { + new.* = old; + } + } + return new_args; + } }; pub const Error = error{ @@ -426,6 +454,8 @@ pub fn end(w: *Writer) EndError!void { .streaming, .streaming_simple, + .terminal_escaped, + .terminal_winapi, .failure, => {}, } @@ -453,10 +483,11 @@ pub const Color = enum { reset, }; -pub const SetColorError = Mode.SetColorError; - -pub fn setColor(w: *Writer, color: Color) SetColorError!void { - return w.mode.setColor(&w.interface, color); +pub fn setColor(w: *Writer, color: Color) Io.Writer.Error!void { + return w.mode.setColor(&w.interface, color) catch |err| switch (err) { + error.WriteFailed => |e| return e, + else => |e| w.err = e, + }; } pub fn disableEscape(w: *Writer) Mode { diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 69d8c942c4..67f7d3a9fe 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -306,7 +306,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void { var buffer: [64]u8 = undefined; const stderr = lockStderrWriter(&buffer); defer unlockStderrWriter(); - stderr.interface.print(fmt, args) catch return; + stderr.interface.print(fmt, stderr.mode.decorateArgs(args)) catch return; } } diff --git a/lib/std/log.zig b/lib/std/log.zig index 029f724f44..b75bada580 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -120,35 +120,7 @@ pub fn defaultLogFileWriter( } fw.interface.writeAll(": ") catch return; fw.setColor(.reset) catch {}; - fw.interface.print(format ++ "\n", decorateArgs(args, fw.mode)) catch return; -} - -fn DecorateArgs(comptime Args: type) type { - const fields = @typeInfo(Args).@"struct".fields; - var new_fields: [fields.len]type = undefined; - for (fields, &new_fields) |old, *new| { - if (old.type == std.debug.FormatStackTrace) { - new.* = std.debug.FormatStackTrace.Decorated; - } else { - new.* = old.type; - } - } - return @Tuple(&new_fields); -} - -fn decorateArgs(args: anytype, file_writer_mode: std.Io.File.Writer.Mode) DecorateArgs(@TypeOf(args)) { - var new_args: DecorateArgs(@TypeOf(args)) = undefined; - inline for (args, &new_args) |old, *new| { - if (@TypeOf(old) == std.debug.FormatStackTrace) { - new.* = .{ - .stack_trace = old.stack_trace, - .file_writer_mode = file_writer_mode, - }; - } else { - new.* = old; - } - } - return new_args; + fw.interface.print(format ++ "\n", fw.mode.decorateArgs(args)) catch return; } /// Returns a scoped logging namespace that logs all messages using the scope diff --git a/lib/std/testing.zig b/lib/std/testing.zig index ab9f1f73c3..092b65d71a 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -354,11 +354,10 @@ test expectApproxEqRel { } } -/// This function is intended to be used only in tests. When the two slices are not -/// equal, prints diagnostics to stderr to show exactly how they are not equal (with -/// the differences highlighted in red), then returns a test failure error. -/// The colorized output is optional and controlled by the return of `Io.tty.Config.detect`. -/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead. +/// This function is intended to be used only in tests. When the two slices are +/// not equal, prints diagnostics to stderr to show exactly how they are not +/// equal (with the differences highlighted in red), then returns a test +/// failure error. pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void { const diff_index: usize = diff_index: { const shortest = @min(expected.len, actual.len); @@ -369,20 +368,13 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const break :diff_index if (expected.len == actual.len) return else shortest; }; if (!backend_can_print) return error.TestExpectedEqual; - const stderr_w, const ttyconf = std.debug.lockStderrWriter(&.{}); + const stderr = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); - failEqualSlices(T, expected, actual, diff_index, stderr_w, ttyconf) catch {}; + failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {}; return error.TestExpectedEqual; } -fn failEqualSlices( - comptime T: type, - expected: []const T, - actual: []const T, - diff_index: usize, - w: *Io.Writer, - ttyconf: Io.tty.Config, -) !void { +fn failEqualSlices(comptime T: type, expected: []const T, actual: []const T, diff_index: usize, w: *Io.Writer, fwm: Io.File.Writer.Mode) !void { try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); // TODO: Should this be configurable by the caller? @@ -404,12 +396,12 @@ fn failEqualSlices( var differ = if (T == u8) BytesDiffer{ .expected = expected_window, .actual = actual_window, - .ttyconf = ttyconf, + .file_writer_mode = fwm, } else SliceDiffer(T){ .start_index = window_start, .expected = expected_window, .actual = actual_window, - .ttyconf = ttyconf, + .file_writer_mode = fwm, }; // Print indexes as hex for slices of u8 since it's more likely to be binary data where @@ -466,7 +458,7 @@ fn SliceDiffer(comptime T: type) type { start_index: usize, expected: []const T, actual: []const T, - ttyconf: Io.tty.Config, + file_writer_mode: Io.File.Writer.Mode, const Self = @This(); @@ -474,13 +466,13 @@ fn SliceDiffer(comptime T: type) type { for (self.expected, 0..) |value, i| { const full_index = self.start_index + i; const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; - if (diff) try self.ttyconf.setColor(writer, .red); + if (diff) try self.file_writer_mode.setColor(writer, .red); if (@typeInfo(T) == .pointer) { try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value }); } else { try writer.print("[{}]: {any}\n", .{ full_index, value }); } - if (diff) try self.ttyconf.setColor(writer, .reset); + if (diff) try self.file_writer_mode.setColor(writer, .reset); } } }; @@ -489,7 +481,7 @@ fn SliceDiffer(comptime T: type) type { const BytesDiffer = struct { expected: []const u8, actual: []const u8, - ttyconf: Io.tty.Config, + file_writer_mode: Io.File.Writer.Mode, pub fn write(self: BytesDiffer, writer: *Io.Writer) !void { var expected_iterator = std.mem.window(u8, self.expected, 16, 16); @@ -516,7 +508,7 @@ const BytesDiffer = struct { try self.writeDiff(writer, "{c}", .{byte}, diff); } else { // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed - if (self.ttyconf == .windows_api) { + if (self.file_writer_mode == .terminal_winapi) { try self.writeDiff(writer, ".", .{}, diff); continue; } @@ -538,9 +530,9 @@ const BytesDiffer = struct { } fn writeDiff(self: BytesDiffer, writer: *Io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void { - if (diff) try self.ttyconf.setColor(writer, .red); + if (diff) try self.file_writer_mode.setColor(writer, .red); try writer.print(fmt, args); - if (diff) try self.ttyconf.setColor(writer, .reset); + if (diff) try self.file_writer_mode.setColor(writer, .reset); } }; @@ -1162,7 +1154,6 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime } else |err| switch (err) { error.OutOfMemory => { if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) { - const tty_config: Io.tty.Config = .detect(.stderr()); print( "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}", .{ @@ -1174,7 +1165,6 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime failing_allocator_inst.deallocations, std.debug.FormatStackTrace{ .stack_trace = failing_allocator_inst.getStackTrace(), - .tty_config = tty_config, }, }, ); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index ac6a0787de..b6203326f2 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -53,18 +53,18 @@ pub const Color = enum { /// Assume stderr is a terminal. on, - pub fn getTtyConf(color: Color, detected: Io.tty.Config) Io.tty.Config { + pub fn getTtyConf(color: Color, detected: Io.File.Writer.Mode) Io.File.Writer.Mode { return switch (color) { .auto => detected, - .on => .escape_codes, - .off => .no_color, + .on => .terminal_escaped, + .off => .streaming, }; } - pub fn detectTtyConf(color: Color, io: Io) Io.tty.Config { + pub fn detectTtyConf(color: Color, io: Io) Io.File.Writer.Mode { return switch (color) { .auto => .detect(io, .stderr()), - .on => .escape_codes, - .off => .no_color, + .on => .terminal_escaped, + .off => .streaming, }; } }; diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index ef6203cbe8..cc6182c8aa 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -164,15 +164,20 @@ pub const RenderOptions = struct { pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions, color: std.zig.Color) void { var buffer: [256]u8 = undefined; - const w, const ttyconf = std.debug.lockStderrWriter(&buffer); + const stderr = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); - renderToWriter(eb, options, w, color.getTtyConf(ttyconf)) catch return; + renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode)) catch return; } -pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer, ttyconf: Io.tty.Config) (Writer.Error || std.posix.UnexpectedError)!void { +pub fn renderToWriter( + eb: ErrorBundle, + options: RenderOptions, + w: *Writer, + fwm: Io.File.Writer.Mode, +) Io.File.Writer.Mode.SetColorError!void { if (eb.extra.len == 0) return; for (eb.getMessages()) |err_msg| { - try renderErrorMessageToWriter(eb, options, err_msg, w, ttyconf, "error", .red, 0); + try renderErrorMessageToWriter(eb, options, err_msg, w, fwm, "error", .red, 0); } if (options.include_log_text) { @@ -189,18 +194,18 @@ fn renderErrorMessageToWriter( options: RenderOptions, err_msg_index: MessageIndex, w: *Writer, - ttyconf: Io.tty.Config, + fwm: Io.File.Writer.Mode, kind: []const u8, - color: Io.tty.Color, + color: Io.File.Writer.Color, indent: usize, -) (Writer.Error || std.posix.UnexpectedError)!void { +) Io.File.Writer.Mode.SetColorError!void { const err_msg = eb.getErrorMessage(err_msg_index); if (err_msg.src_loc != .none) { const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); var prefix: Writer.Discarding = .init(&.{}); try w.splatByteAll(' ', indent); prefix.count += indent; - try ttyconf.setColor(w, .bold); + try fwm.setColor(w, .bold); try w.print("{s}:{d}:{d}: ", .{ eb.nullTerminatedString(src.data.src_path), src.data.line + 1, @@ -211,7 +216,7 @@ fn renderErrorMessageToWriter( src.data.line + 1, src.data.column + 1, }); - try ttyconf.setColor(w, color); + try fwm.setColor(w, color); try w.writeAll(kind); prefix.count += kind.len; try w.writeAll(": "); @@ -219,17 +224,17 @@ fn renderErrorMessageToWriter( // This is the length of the part before the error message: // e.g. "file.zig:4:5: error: " const prefix_len: usize = @intCast(prefix.count); - try ttyconf.setColor(w, .reset); - try ttyconf.setColor(w, .bold); + try fwm.setColor(w, .reset); + try fwm.setColor(w, .bold); if (err_msg.count == 1) { try writeMsg(eb, err_msg, w, prefix_len); try w.writeByte('\n'); } else { try writeMsg(eb, err_msg, w, prefix_len); - try ttyconf.setColor(w, .dim); + try fwm.setColor(w, .dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try ttyconf.setColor(w, .reset); + try fwm.setColor(w, .reset); if (src.data.source_line != 0 and options.include_source_line) { const line = eb.nullTerminatedString(src.data.source_line); for (line) |b| switch (b) { @@ -242,19 +247,19 @@ fn renderErrorMessageToWriter( // -1 since span.main includes the caret const after_caret = src.data.span_end -| src.data.span_main -| 1; try w.splatByteAll(' ', src.data.column - before_caret); - try ttyconf.setColor(w, .green); + try fwm.setColor(w, .green); try w.splatByteAll('~', before_caret); try w.writeByte('^'); try w.splatByteAll('~', after_caret); try w.writeByte('\n'); - try ttyconf.setColor(w, .reset); + try fwm.setColor(w, .reset); } for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent); + try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent); } if (src.data.reference_trace_len > 0 and options.include_reference_trace) { - try ttyconf.setColor(w, .reset); - try ttyconf.setColor(w, .dim); + try fwm.setColor(w, .reset); + try fwm.setColor(w, .dim); try w.print("referenced by:\n", .{}); var ref_index = src.end; for (0..src.data.reference_trace_len) |_| { @@ -281,25 +286,25 @@ fn renderErrorMessageToWriter( ); } } - try ttyconf.setColor(w, .reset); + try fwm.setColor(w, .reset); } } else { - try ttyconf.setColor(w, color); + try fwm.setColor(w, color); try w.splatByteAll(' ', indent); try w.writeAll(kind); try w.writeAll(": "); - try ttyconf.setColor(w, .reset); + try fwm.setColor(w, .reset); const msg = eb.nullTerminatedString(err_msg.msg); if (err_msg.count == 1) { try w.print("{s}\n", .{msg}); } else { try w.print("{s}", .{msg}); - try ttyconf.setColor(w, .dim); + try fwm.setColor(w, .dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try ttyconf.setColor(w, .reset); + try fwm.setColor(w, .reset); for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent + 4); + try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent + 4); } } } @@ -806,12 +811,10 @@ pub const Wip = struct { }; defer bundle.deinit(std.testing.allocator); - const ttyconf: Io.tty.Config = .no_color; - var bundle_buf: Writer.Allocating = .init(std.testing.allocator); const bundle_bw = &bundle_buf.interface; defer bundle_buf.deinit(); - try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw); + try bundle.renderToWriter(bundle_bw); var copy = copy: { var wip: ErrorBundle.Wip = undefined; @@ -827,7 +830,7 @@ pub const Wip = struct { var copy_buf: Writer.Allocating = .init(std.testing.allocator); const copy_bw = ©_buf.interface; defer copy_buf.deinit(); - try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw); + try copy.renderToWriter(copy_bw); try std.testing.expectEqualStrings(bundle_bw.written(), copy_bw.written()); } -- cgit v1.2.3 From 608145c2f07d90c46cdaa8bc2013f31b965a5b8b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 17 Dec 2025 17:00:41 -0800 Subject: fix more fallout from locking stderr --- lib/compiler/aro/aro/Diagnostics.zig | 28 ++- lib/compiler/build_runner.zig | 338 +++++++++++++++++------------------ lib/compiler/resinator/cli.zig | 10 +- lib/compiler/resinator/errors.zig | 6 +- lib/compiler/resinator/main.zig | 31 ++-- lib/compiler/test_runner.zig | 8 +- lib/std/Build.zig | 73 ++++---- lib/std/Build/Fuzz.zig | 18 +- lib/std/Build/Step.zig | 9 +- lib/std/Build/Step/Compile.zig | 17 +- lib/std/Build/Step/Run.zig | 22 +-- lib/std/Io.zig | 2 +- lib/std/Io/File/Writer.zig | 2 +- lib/std/Io/Terminal.zig | 22 --- lib/std/Io/Threaded.zig | 6 +- lib/std/debug.zig | 24 +-- lib/std/debug/simple_panic.zig | 6 +- lib/std/json/dynamic.zig | 6 +- lib/std/log.zig | 2 +- lib/std/process.zig | 2 +- lib/std/testing.zig | 21 +-- lib/std/zig.zig | 21 +-- lib/std/zig/ErrorBundle.zig | 72 ++++---- lib/std/zig/parser_test.zig | 16 +- src/Air/print.zig | 12 +- src/Compilation.zig | 45 +++-- src/InternPool.zig | 10 +- src/Zcu/PerThread.zig | 8 +- src/codegen/aarch64/Select.zig | 7 +- src/crash_report.zig | 6 +- src/libs/mingw.zig | 24 +-- src/libs/mingw/def.zig | 6 +- src/link/Coff.zig | 6 +- src/link/Elf2.zig | 6 +- src/main.zig | 12 +- 35 files changed, 446 insertions(+), 458 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/aro/aro/Diagnostics.zig b/lib/compiler/aro/aro/Diagnostics.zig index bebcf4e3d2..b33efa3f85 100644 --- a/lib/compiler/aro/aro/Diagnostics.zig +++ b/lib/compiler/aro/aro/Diagnostics.zig @@ -24,20 +24,21 @@ pub const Message = struct { @"fatal error", }; - pub fn write(msg: Message, w: *std.Io.Writer, config: std.Io.File.Writer.Mode, details: bool) std.Io.tty.Config.SetColorError!void { - try config.setColor(w, .bold); + pub fn write(msg: Message, t: std.Io.Terminal, details: bool) std.Io.Terminal.SetColorError!void { + const w = t.writer; + try t.setColor(.bold); if (msg.location) |loc| { try w.print("{s}:{d}:{d}: ", .{ loc.path, loc.line_no, loc.col }); } switch (msg.effective_kind) { - .@"fatal error", .@"error" => try config.setColor(w, .bright_red), - .note => try config.setColor(w, .bright_cyan), - .warning => try config.setColor(w, .bright_magenta), + .@"fatal error", .@"error" => try t.setColor(.bright_red), + .note => try t.setColor(.bright_cyan), + .warning => try t.setColor(.bright_magenta), .off => unreachable, } try w.print("{s}: ", .{@tagName(msg.effective_kind)}); - try config.setColor(w, .white); + try t.setColor(.white); try w.writeAll(msg.text); if (msg.opt) |some| { if (msg.effective_kind == .@"error" and msg.kind != .@"error") { @@ -55,17 +56,17 @@ pub const Message = struct { if (!details or msg.location == null) { try w.writeAll("\n"); - try config.setColor(w, .reset); + try t.setColor(.reset); } else { const loc = msg.location.?; const trailer = if (loc.end_with_splice) "\\ " else ""; - try config.setColor(w, .reset); + try t.setColor(.reset); try w.print("\n{s}{s}\n", .{ loc.line, trailer }); try w.splatByteAll(' ', loc.width); - try config.setColor(w, .bold); - try config.setColor(w, .bright_green); + try t.setColor(.bold); + try t.setColor(.bright_green); try w.writeAll("^\n"); - try config.setColor(w, .reset); + try t.setColor(.reset); } try w.flush(); } @@ -290,10 +291,7 @@ pub const State = struct { const Diagnostics = @This(); output: union(enum) { - to_writer: struct { - writer: *std.Io.Writer, - color: std.Io.File.Writer.Mode, - }, + to_writer: std.Io.Terminal, to_list: struct { messages: std.ArrayList(Message) = .empty, arena: std.heap.ArenaAllocator, diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index d284d85747..1c30ecaadc 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -286,8 +286,8 @@ pub fn main() !void { const next_arg = nextArg(args, &arg_idx) orelse fatalWithHint("expected u16 after '{s}'", .{arg}); debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| { - fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {s}\n", .{ - next_arg, @errorName(err), + fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {t}\n", .{ + next_arg, err, }); }; } else if (mem.eql(u8, arg, "--webui")) { @@ -429,6 +429,12 @@ pub fn main() !void { } } + graph.stderr_mode = switch (color) { + .auto => try .detect(io, .stderr()), + .on => .escape_codes, + .off => .no_color, + }; + if (webui_listen != null) { if (watch) fatal("using '--webui' and '--watch' together is not yet supported; consider omitting '--watch' in favour of the web UI \"Rebuild\" button", .{}); if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{}); @@ -522,7 +528,7 @@ pub fn main() !void { // Perhaps in the future there could be an Advanced Options flag // such as --debug-build-runner-leaks which would make this code // return instead of calling exit. - _ = io.lockStderrWriter(&.{}) catch {}; + _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; process.exit(1); }, else => |e| return e, @@ -554,9 +560,9 @@ pub fn main() !void { } rebuild: while (true) : (if (run.error_style.clearOnUpdate()) { - const stderr = try io.lockStderrWriter(&stdio_buffer_allocation); - defer io.unlockStderrWriter(); - try stderr.writeAllUnescaped("\x1B[2J\x1B[3J\x1B[H"); + const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); + defer io.unlockStderr(); + try stderr.file_writer.interface.writeAll("\x1B[2J\x1B[3J\x1B[H"); }) { if (run.web_server) |*ws| ws.startBuild(); @@ -730,7 +736,8 @@ fn runStepNames( fuzz: ?std.Build.Fuzz.Mode, ) !void { const gpa = run.gpa; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const step_stack = &run.step_stack; { @@ -856,20 +863,19 @@ fn runStepNames( .none => break :summary, } - const stderr = try io.lockStderrWriter(&stdio_buffer_allocation); - defer io.unlockStderrWriter(); - - const w = &stderr.interface; - const fwm = stderr.mode; + const stderr = try io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode); + defer io.unlockStderr(); + const t = stderr.terminal(); + const w = &stderr.file_writer.interface; const total_count = success_count + failure_count + pending_count + skipped_count; - fwm.setColor(w, .cyan) catch {}; - fwm.setColor(w, .bold) catch {}; + t.setColor(.cyan) catch {}; + t.setColor(.bold) catch {}; w.writeAll("Build Summary: ") catch {}; - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; w.print("{d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; { - fwm.setColor(w, .dim) catch {}; + t.setColor(.dim) catch {}; var first = true; if (skipped_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", skipped_count }) catch {}; @@ -880,12 +886,12 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } if (test_count > 0) { w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; - fwm.setColor(w, .dim) catch {}; + t.setColor(.dim) catch {}; var first = true; if (test_skip_count > 0) { w.print("{s}{d} skipped", .{ if (first) " (" else ", ", test_skip_count }) catch {}; @@ -904,7 +910,7 @@ fn runStepNames( first = false; } if (!first) w.writeByte(')') catch {}; - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } w.writeAll("\n") catch {}; @@ -918,7 +924,7 @@ fn runStepNames( var print_node: PrintNode = .{ .parent = null }; if (step_names.len == 0) { print_node.last = true; - printTreeStep(b, b.default_step, run, w, fwm, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, b.default_step, run, t, &print_node, &step_stack_copy) catch {}; } else { const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { var i: usize = step_names.len; @@ -937,7 +943,7 @@ fn runStepNames( for (step_names, 0..) |step_name, i| { const tls = b.top_level_steps.get(step_name).?; print_node.last = i + 1 == last_index; - printTreeStep(b, &tls.step, run, w, fwm, &print_node, &step_stack_copy) catch {}; + printTreeStep(b, &tls.step, run, t, &print_node, &step_stack_copy) catch {}; } } w.writeByte('\n') catch {}; @@ -954,7 +960,7 @@ fn runStepNames( if (run.error_style.verboseContext()) break :code 1; // failure; print build command break :code 2; // failure; do not print build command }; - _ = io.lockStderrWriter(&.{}) catch {}; + _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; process.exit(code); } @@ -963,33 +969,30 @@ const PrintNode = struct { last: bool = false, }; -fn printPrefix(node: *PrintNode, w: *Writer, fwm: File.Writer.Mode) !void { +fn printPrefix(node: *PrintNode, stderr: Io.Terminal) !void { const parent = node.parent orelse return; + const writer = stderr.writer; if (parent.parent == null) return; - try printPrefix(parent, w, fwm); + try printPrefix(parent, stderr); if (parent.last) { - try w.writeAll(" "); + try writer.writeAll(" "); } else { - try w.writeAll(switch (fwm) { - .terminal_escaped => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ + try writer.writeAll(switch (stderr.mode) { + .escape_codes => "\x1B\x28\x30\x78\x1B\x28\x42 ", // │ else => "| ", }); } } -fn printChildNodePrefix(w: *Writer, fwm: File.Writer.Mode) !void { - try w.writeAll(switch (fwm) { - .terminal_escaped => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ +fn printChildNodePrefix(stderr: Io.Terminal) !void { + try stderr.writer.writeAll(switch (stderr.mode) { + .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ else => "+- ", }); } -fn printStepStatus( - s: *Step, - stderr: *Writer, - fwm: File.Writer.Mode, - run: *const Run, -) !void { +fn printStepStatus(s: *Step, stderr: Io.Terminal, run: *const Run) !void { + const writer = stderr.writer; switch (s.state) { .precheck_unstarted => unreachable, .precheck_started => unreachable, @@ -997,139 +1000,135 @@ fn printStepStatus( .running => unreachable, .dependency_failure => { - try fwm.setColor(stderr, .dim); - try stderr.writeAll(" transitive failure\n"); - try fwm.setColor(stderr, .reset); + try stderr.setColor(.dim); + try writer.writeAll(" transitive failure\n"); + try stderr.setColor(.reset); }, .success => { - try fwm.setColor(stderr, .green); + try stderr.setColor(.green); if (s.result_cached) { - try stderr.writeAll(" cached"); + try writer.writeAll(" cached"); } else if (s.test_results.test_count > 0) { const pass_count = s.test_results.passCount(); assert(s.test_results.test_count == pass_count + s.test_results.skip_count); - try stderr.print(" {d} pass", .{pass_count}); + try writer.print(" {d} pass", .{pass_count}); if (s.test_results.skip_count > 0) { - try fwm.setColor(stderr, .reset); - try stderr.writeAll(", "); - try fwm.setColor(stderr, .yellow); - try stderr.print("{d} skip", .{s.test_results.skip_count}); + try stderr.setColor(.reset); + try writer.writeAll(", "); + try stderr.setColor(.yellow); + try writer.print("{d} skip", .{s.test_results.skip_count}); } - try fwm.setColor(stderr, .reset); - try stderr.print(" ({d} total)", .{s.test_results.test_count}); + try stderr.setColor(.reset); + try writer.print(" ({d} total)", .{s.test_results.test_count}); } else { - try stderr.writeAll(" success"); + try writer.writeAll(" success"); } - try fwm.setColor(stderr, .reset); + try stderr.setColor(.reset); if (s.result_duration_ns) |ns| { - try fwm.setColor(stderr, .dim); + try stderr.setColor(.dim); if (ns >= std.time.ns_per_min) { - try stderr.print(" {d}m", .{ns / std.time.ns_per_min}); + try writer.print(" {d}m", .{ns / std.time.ns_per_min}); } else if (ns >= std.time.ns_per_s) { - try stderr.print(" {d}s", .{ns / std.time.ns_per_s}); + try writer.print(" {d}s", .{ns / std.time.ns_per_s}); } else if (ns >= std.time.ns_per_ms) { - try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms}); + try writer.print(" {d}ms", .{ns / std.time.ns_per_ms}); } else if (ns >= std.time.ns_per_us) { - try stderr.print(" {d}us", .{ns / std.time.ns_per_us}); + try writer.print(" {d}us", .{ns / std.time.ns_per_us}); } else { - try stderr.print(" {d}ns", .{ns}); + try writer.print(" {d}ns", .{ns}); } - try fwm.setColor(stderr, .reset); + try stderr.setColor(.reset); } if (s.result_peak_rss != 0) { const rss = s.result_peak_rss; - try fwm.setColor(stderr, .dim); + try stderr.setColor(.dim); if (rss >= 1000_000_000) { - try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); + try writer.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); } else if (rss >= 1000_000) { - try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000}); + try writer.print(" MaxRSS:{d}M", .{rss / 1000_000}); } else if (rss >= 1000) { - try stderr.print(" MaxRSS:{d}K", .{rss / 1000}); + try writer.print(" MaxRSS:{d}K", .{rss / 1000}); } else { - try stderr.print(" MaxRSS:{d}B", .{rss}); + try writer.print(" MaxRSS:{d}B", .{rss}); } - try fwm.setColor(stderr, .reset); + try stderr.setColor(.reset); } - try stderr.writeAll("\n"); + try writer.writeAll("\n"); }, .skipped, .skipped_oom => |skip| { - try fwm.setColor(stderr, .yellow); - try stderr.writeAll(" skipped"); + try stderr.setColor(.yellow); + try writer.writeAll(" skipped"); if (skip == .skipped_oom) { - try stderr.writeAll(" (not enough memory)"); - try fwm.setColor(stderr, .dim); - try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); - try fwm.setColor(stderr, .yellow); + try writer.writeAll(" (not enough memory)"); + try stderr.setColor(.dim); + try writer.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); + try stderr.setColor(.yellow); } - try stderr.writeAll("\n"); - try fwm.setColor(stderr, .reset); + try writer.writeAll("\n"); + try stderr.setColor(.reset); }, .failure => { - try printStepFailure(s, stderr, fwm, false); - try fwm.setColor(stderr, .reset); + try printStepFailure(s, stderr, false); + try stderr.setColor(.reset); }, } } -fn printStepFailure( - s: *Step, - stderr: *Writer, - fwm: File.Writer.Mode, - dim: bool, -) !void { +fn printStepFailure(s: *Step, stderr: Io.Terminal, dim: bool) !void { + const w = stderr.writer; if (s.result_error_bundle.errorMessageCount() > 0) { - try fwm.setColor(stderr, .red); - try stderr.print(" {d} errors\n", .{ + try stderr.setColor(.red); + try w.print(" {d} errors\n", .{ s.result_error_bundle.errorMessageCount(), }); } else if (!s.test_results.isSuccess()) { // These first values include all of the test "statuses". Every test is either passsed, // skipped, failed, crashed, or timed out. - try fwm.setColor(stderr, .green); - try stderr.print(" {d} pass", .{s.test_results.passCount()}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try stderr.setColor(.green); + try w.print(" {d} pass", .{s.test_results.passCount()}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); if (s.test_results.skip_count > 0) { - try stderr.writeAll(", "); - try fwm.setColor(stderr, .yellow); - try stderr.print("{d} skip", .{s.test_results.skip_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.yellow); + try w.print("{d} skip", .{s.test_results.skip_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.fail_count > 0) { - try stderr.writeAll(", "); - try fwm.setColor(stderr, .red); - try stderr.print("{d} fail", .{s.test_results.fail_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} fail", .{s.test_results.fail_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.crash_count > 0) { - try stderr.writeAll(", "); - try fwm.setColor(stderr, .red); - try stderr.print("{d} crash", .{s.test_results.crash_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} crash", .{s.test_results.crash_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } if (s.test_results.timeout_count > 0) { - try stderr.writeAll(", "); - try fwm.setColor(stderr, .red); - try stderr.print("{d} timeout", .{s.test_results.timeout_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll(", "); + try stderr.setColor(.red); + try w.print("{d} timeout", .{s.test_results.timeout_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } - try stderr.print(" ({d} total)", .{s.test_results.test_count}); + try w.print(" ({d} total)", .{s.test_results.test_count}); // Memory leaks are intentionally written after the total, because is isn't a test *status*, // but just a flag that any tests -- even passed ones -- can have. We also use a different // separator, so it looks like: // 2 pass, 1 skip, 2 fail (5 total); 2 leaks if (s.test_results.leak_count > 0) { - try stderr.writeAll("; "); - try fwm.setColor(stderr, .red); - try stderr.print("{d} leaks", .{s.test_results.leak_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll("; "); + try stderr.setColor(.red); + try w.print("{d} leaks", .{s.test_results.leak_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } // It's usually not helpful to know how many error logs there were because they tend to @@ -1142,21 +1141,21 @@ fn printStepFailure( break :show alt_results.isSuccess(); }; if (show_err_logs) { - try stderr.writeAll("; "); - try fwm.setColor(stderr, .red); - try stderr.print("{d} error logs", .{s.test_results.log_err_count}); - try fwm.setColor(stderr, .reset); - if (dim) try fwm.setColor(stderr, .dim); + try w.writeAll("; "); + try stderr.setColor(.red); + try w.print("{d} error logs", .{s.test_results.log_err_count}); + try stderr.setColor(.reset); + if (dim) try stderr.setColor(.dim); } - try stderr.writeAll("\n"); + try w.writeAll("\n"); } else if (s.result_error_msgs.items.len > 0) { - try fwm.setColor(stderr, .red); - try stderr.writeAll(" failure\n"); + try stderr.setColor(.red); + try w.writeAll(" failure\n"); } else { assert(s.result_stderr.len > 0); - try fwm.setColor(stderr, .red); - try stderr.writeAll(" stderr\n"); + try stderr.setColor(.red); + try w.writeAll(" w\n"); } } @@ -1164,11 +1163,11 @@ fn printTreeStep( b: *std.Build, s: *Step, run: *const Run, - stderr: *Writer, - fwm: File.Writer.Mode, + stderr: Io.Terminal, parent_node: *PrintNode, step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), ) !void { + const writer = stderr.writer; const first = step_stack.swapRemove(s); const summary = run.summary; const skip = switch (summary) { @@ -1178,26 +1177,26 @@ fn printTreeStep( .failures => s.state == .success, }; if (skip) return; - try printPrefix(parent_node, stderr, fwm); + try printPrefix(parent_node, stderr); if (parent_node.parent != null) { if (parent_node.last) { - try printChildNodePrefix(stderr, fwm); + try printChildNodePrefix(stderr); } else { - try stderr.writeAll(switch (fwm) { - .terminal_escaped => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ + try writer.writeAll(switch (stderr.mode) { + .escape_codes => "\x1B\x28\x30\x74\x71\x1B\x28\x42 ", // ├─ else => "+- ", }); } } - if (!first) try fwm.setColor(stderr, .dim); + if (!first) try stderr.setColor(.dim); // dep_prefix omitted here because it is redundant with the tree. - try stderr.writeAll(s.name); + try writer.writeAll(s.name); if (first) { - try printStepStatus(s, stderr, fwm, run); + try printStepStatus(s, stderr, run); const last_index = if (summary == .all) s.dependencies.items.len -| 1 else blk: { var i: usize = s.dependencies.items.len; @@ -1219,17 +1218,17 @@ fn printTreeStep( .parent = parent_node, .last = i == last_index, }; - try printTreeStep(b, dep, run, stderr, fwm, &print_node, step_stack); + try printTreeStep(b, dep, run, stderr, &print_node, step_stack); } } else { if (s.dependencies.items.len == 0) { - try stderr.writeAll(" (reused)\n"); + try writer.writeAll(" (reused)\n"); } else { - try stderr.print(" (+{d} more reused dependencies)\n", .{ + try writer.print(" (+{d} more reused dependencies)\n", .{ s.dependencies.items.len, }); } - try fwm.setColor(stderr, .reset); + try stderr.setColor(.reset); } } @@ -1300,7 +1299,8 @@ fn workerMakeOneStep( prog_node: std.Progress.Node, run: *Run, ) void { - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const gpa = run.gpa; // First, check the conditions for running this step. If they are not met, @@ -1369,11 +1369,11 @@ fn workerMakeOneStep( const show_error_msgs = s.result_error_msgs.items.len > 0; const show_stderr = s.result_stderr.len > 0; if (show_error_msgs or show_compile_errors or show_stderr) { - const stderr = io.lockStderrWriter(&stdio_buffer_allocation) catch |err| switch (err) { + const stderr = io.lockStderr(&stdio_buffer_allocation, graph.stderr_mode) catch |err| switch (err) { error.Canceled => return, }; - defer io.unlockStderrWriter(); - printErrorMessages(gpa, s, .{}, &stderr.interface, stderr.mode, run.error_style, run.multiline_errors) catch {}; + defer io.unlockStderr(); + printErrorMessages(gpa, s, .{}, stderr.terminal(), run.error_style, run.multiline_errors) catch {}; } handle_result: { @@ -1440,11 +1440,11 @@ pub fn printErrorMessages( gpa: Allocator, failing_step: *Step, options: std.zig.ErrorBundle.RenderOptions, - stderr: *Writer, - fwm: File.Writer.Mode, + stderr: Io.Terminal, error_style: ErrorStyle, multiline_errors: MultilineErrors, ) !void { + const writer = stderr.writer; if (error_style.verboseContext()) { // Provide context for where these error messages are coming from by // printing the corresponding Step subtree. @@ -1456,70 +1456,70 @@ pub fn printErrorMessages( } // Now, `step_stack` has the subtree that we want to print, in reverse order. - try fwm.setColor(stderr, .dim); + try stderr.setColor(.dim); var indent: usize = 0; while (step_stack.pop()) |s| : (indent += 1) { if (indent > 0) { - try stderr.splatByteAll(' ', (indent - 1) * 3); - try printChildNodePrefix(stderr, fwm); + try writer.splatByteAll(' ', (indent - 1) * 3); + try printChildNodePrefix(stderr); } - try stderr.writeAll(s.name); + try writer.writeAll(s.name); if (s == failing_step) { - try printStepFailure(s, stderr, fwm, true); + try printStepFailure(s, stderr, true); } else { - try stderr.writeAll("\n"); + try writer.writeAll("\n"); } } - try fwm.setColor(stderr, .reset); + try stderr.setColor(.reset); } else { // Just print the failing step itself. - try fwm.setColor(stderr, .dim); - try stderr.writeAll(failing_step.name); - try printStepFailure(failing_step, stderr, fwm, true); - try fwm.setColor(stderr, .reset); + try stderr.setColor(.dim); + try writer.writeAll(failing_step.name); + try printStepFailure(failing_step, stderr, true); + try stderr.setColor(.reset); } if (failing_step.result_stderr.len > 0) { - try stderr.writeAll(failing_step.result_stderr); + try writer.writeAll(failing_step.result_stderr); if (!mem.endsWith(u8, failing_step.result_stderr, "\n")) { - try stderr.writeAll("\n"); + try writer.writeAll("\n"); } } - try failing_step.result_error_bundle.renderToWriter(options, stderr, fwm); + try failing_step.result_error_bundle.renderToTerminal(options, stderr); for (failing_step.result_error_msgs.items) |msg| { - try fwm.setColor(stderr, .red); - try stderr.writeAll("error:"); - try fwm.setColor(stderr, .reset); + try stderr.setColor(.red); + try writer.writeAll("error:"); + try stderr.setColor(.reset); if (std.mem.indexOfScalar(u8, msg, '\n') == null) { - try stderr.print(" {s}\n", .{msg}); + try writer.print(" {s}\n", .{msg}); } else switch (multiline_errors) { .indent => { var it = std.mem.splitScalar(u8, msg, '\n'); - try stderr.print(" {s}\n", .{it.first()}); + try writer.print(" {s}\n", .{it.first()}); while (it.next()) |line| { - try stderr.print(" {s}\n", .{line}); + try writer.print(" {s}\n", .{line}); } }, - .newline => try stderr.print("\n{s}\n", .{msg}), - .none => try stderr.print(" {s}\n", .{msg}), + .newline => try writer.print("\n{s}\n", .{msg}), + .none => try writer.print(" {s}\n", .{msg}), } } if (error_style.verboseContext()) { if (failing_step.result_failed_command) |cmd_str| { - try fwm.setColor(stderr, .red); - try stderr.writeAll("failed command: "); - try fwm.setColor(stderr, .reset); - try stderr.writeAll(cmd_str); - try stderr.writeByte('\n'); + try stderr.setColor(.red); + try writer.writeAll("failed command: "); + try stderr.setColor(.reset); + try writer.writeAll(cmd_str); + try writer.writeByte('\n'); } } - try stderr.writeByte('\n'); + try writer.writeByte('\n'); } fn printSteps(builder: *std.Build, w: *Writer) !void { diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 08befbe1fa..ddf3ca18b7 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -126,14 +126,14 @@ pub const Diagnostics = struct { } pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void { - const stderr = io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - self.renderToWriter(args, &stderr.interface, stderr.mode) catch return; + const stderr = io.lockStderr(&.{}, null); + defer io.unlockStderr(); + self.renderToWriter(args, stderr.terminal()) catch return; } - pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void { + pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, t: Io.Terminal) !void { for (self.errors.items) |err_details| { - try renderErrorMessage(writer, config, err_details, args); + try renderErrorMessage(t, err_details, args); } } diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 031b5d3574..6146f777cd 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -69,10 +69,10 @@ pub const Diagnostics = struct { pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void { const io = self.io; - const stderr = io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); + const stderr = io.lockStderr(&.{}, null); + defer io.unlockStderr(); for (self.errors.items) |err_details| { - renderErrorMessage(io, &stderr.interface, stderr.mode, cwd, err_details, source, self.strings.items, source_mappings) catch return; + renderErrorMessage(io, stderr.terminal(), cwd, err_details, source, self.strings.items, source_mappings) catch return; } } diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index bd2fcc912e..81a3a8689a 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -35,8 +35,8 @@ pub fn main() !void { const args = try std.process.argsAlloc(arena); if (args.len < 2) { - const stderr = io.lockStderrWriter(&.{}); - try renderErrorMessage(&stderr.interface, stderr.mode, .err, "expected zig lib dir as first argument", .{}); + const stderr = try io.lockStderr(&.{}, null); + try renderErrorMessage(stderr.terminal(), .err, "expected zig lib dir as first argument", .{}); std.process.exit(1); } const zig_lib_dir = args[1]; @@ -80,9 +80,9 @@ pub fn main() !void { // so that there is a clear separation between the cli diagnostics and whatever // gets printed after if (cli_diagnostics.errors.items.len > 0) { - const stderr = io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - try stderr.interface.writeByte('\n'); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try stderr.file_writer.interface.writeByte('\n'); } } break :options options; @@ -130,15 +130,12 @@ pub fn main() !void { var stderr_buf: [512]u8 = undefined; var diagnostics: aro.Diagnostics = .{ .output = output: { if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } }; - const stderr = io.lockStderrWriter(&stderr_buf); - break :output .{ .to_writer = .{ - .writer = &stderr.interface, - .color = stderr.mode, - } }; + const stderr = try io.lockStderr(&stderr_buf, null); + break :output .{ .to_writer = stderr.terminal() }; } }; defer { diagnostics.deinit(); - if (!zig_integration) std.debug.unlockStderrWriter(); + if (!zig_integration) std.debug.unlockStderr(); } var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd()); @@ -699,9 +696,9 @@ const ErrorHandler = union(enum) { }, .stderr => { // aro errors have already been emitted - const stderr = io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - try renderErrorMessage(&stderr.interface, stderr.mode, .err, "{s}", .{fail_msg}); + const stderr = io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try renderErrorMessage(stderr.terminal(), .err, "{s}", .{fail_msg}); }, } } @@ -745,9 +742,9 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, .stderr => { - const stderr = io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - try renderErrorMessage(&stderr.interface, stderr.mode, msg_type, format, args); + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + try renderErrorMessage(stderr.terminal(), msg_type, format, args); }, } } diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 3a135ab8fd..3d97944a7f 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -405,18 +405,18 @@ pub fn fuzz( testOne(ctx, input.toSlice()) catch |err| switch (err) { error.SkipZigTest => return, else => { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr = std.debug.lockStderr(&.{}, null).terminal(); p: { if (@errorReturnTrace()) |trace| { - std.debug.writeStackTrace(trace, &stderr.interface, stderr.mode) catch break :p; + std.debug.writeStackTrace(trace, stderr) catch break :p; } - stderr.interface.print("failed with error.{t}\n", .{err}) catch break :p; + stderr.writer.print("failed with error.{t}\n", .{err}) catch break :p; } std.process.exit(1); }, }; if (log_err_count != 0) { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr = std.debug.lockStderr(&.{}, .no_color); stderr.interface.print("error logs detected\n", .{}) catch {}; std.process.exit(1); } diff --git a/lib/std/Build.zig b/lib/std/Build.zig index de2985d2b5..cf0b9e5b0d 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -129,6 +129,9 @@ pub const Graph = struct { dependency_cache: InitializedDepMap = .empty, allow_so_scripts: ?bool = null, time_report: bool, + /// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also + /// respects the '--color' flag. + stderr_mode: ?Io.Terminal.Mode = null, }; const AvailableDeps = []const struct { []const u8, []const u8 }; @@ -2255,9 +2258,10 @@ pub const GeneratedFile = struct { pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 { return gen.path orelse { - const io = gen.step.owner.graph.io; - const stderr = try io.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {}; + const graph = gen.step.owner.graph; + const io = graph.io; + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + dumpBadGetPathHelp(gen.step, stderr.terminal(), src_builder, asking_step) catch {}; @panic("misconfigured build script"); }; } @@ -2468,13 +2472,15 @@ pub const LazyPath = union(enum) { // TODO make gen.file.path not be absolute and use that as the // basis for not traversing up too many directories. + const graph = src_builder.graph; + var file_path: Cache.Path = .{ .root_dir = Cache.Directory.cwd(), .sub_path = gen.file.path orelse { - const io = src_builder.graph.io; - const stderr = try io.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.file.step, &stderr.interface, stderr.mode, src_builder, asking_step) catch {}; - io.unlockStderrWriter(); + const io = graph.io; + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + dumpBadGetPathHelp(gen.file.step, stderr.terminal(), src_builder, asking_step) catch {}; + io.unlockStderr(); @panic("misconfigured build script"); }, }; @@ -2564,43 +2570,36 @@ fn dumpBadDirnameHelp( comptime msg: []const u8, args: anytype, ) anyerror!void { - const stderr = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - - const w = &stderr.interface; - const fwm = stderr.mode; + const stderr = std.debug.lockStderr(&.{}).terminal(); + defer std.debug.unlockStderr(); + const w = stderr.writer; try w.print(msg, args); if (fail_step) |s| { - fwm.setColor(w, .red) catch {}; + stderr.setColor(.red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - fwm.setColor(w, .reset) catch {}; + stderr.setColor(.reset) catch {}; - s.dump(w, fwm); + s.dump(stderr); } if (asking_step) |as| { - fwm.setColor(w, .red) catch {}; + stderr.setColor(.red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - fwm.setColor(w, .reset) catch {}; + stderr.setColor(.reset) catch {}; - as.dump(w, fwm); + as.dump(stderr); } - fwm.setColor(w, .red) catch {}; - try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - fwm.setColor(w, .reset) catch {}; + stderr.setColor(.red) catch {}; + try w.writeAll(" Proceeding to panic.\n"); + stderr.setColor(.reset) catch {}; } /// In this function the stderr mutex has already been locked. -pub fn dumpBadGetPathHelp( - s: *Step, - w: *Io.Writer, - fwm: File.Writer.Mode, - src_builder: *Build, - asking_step: ?*Step, -) anyerror!void { +pub fn dumpBadGetPathHelp(s: *Step, t: Io.Terminal, src_builder: *Build, asking_step: ?*Step) anyerror!void { + const w = t.writer; try w.print( \\getPath() was called on a GeneratedFile that wasn't built yet. \\ source package path: {s} @@ -2611,21 +2610,21 @@ pub fn dumpBadGetPathHelp( s.name, }); - fwm.setColor(w, .red) catch {}; + t.setColor(.red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; - s.dump(w, fwm); + s.dump(t); if (asking_step) |as| { - fwm.setColor(w, .red) catch {}; + t.setColor(.red) catch {}; try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name}); - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; - as.dump(w, fwm); + as.dump(t); } - fwm.setColor(w, .red) catch {}; - try w.writeAll(" Hope that helps. Proceeding to panic.\n"); - fwm.setColor(w, .reset) catch {}; + t.setColor(.red) catch {}; + try w.writeAll(" Proceeding to panic.\n"); + t.setColor(.reset) catch {}; } pub const InstallDir = union(enum) { diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index 4770e03a0c..d308efdf70 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -158,7 +158,8 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, parent_prog_node: std.P } fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_node: std.Progress.Node) !void { - const io = run.step.owner.graph.io; + const graph = run.step.owner.graph; + const io = graph.io; const compile = run.producer.?; const prog_node = parent_prog_node.start(compile.step.name, 0); defer prog_node.end(); @@ -171,9 +172,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod if (show_error_msgs or show_compile_errors or show_stderr) { var buf: [256]u8 = undefined; - const stderr = try io.lockStderrWriter(&buf); - defer io.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &compile.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {}; + const stderr = try io.lockStderr(&buf, graph.stderr_mode); + defer io.unlockStderr(); + build_runner.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; } const rebuilt_bin_path = result catch |err| switch (err) { @@ -186,7 +187,8 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, parent_prog_nod fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void { const owner = run.step.owner; const gpa = owner.allocator; - const io = owner.graph.io; + const graph = owner.graph; + const io = graph.io; const test_name = run.cached_test_metadata.?.testName(unit_test_index); const prog_node = fuzz.prog_node.start(test_name, 0); @@ -195,11 +197,11 @@ fn fuzzWorkerRun(fuzz: *Fuzz, run: *Step.Run, unit_test_index: u32) void { run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) { error.MakeFailed => { var buf: [256]u8 = undefined; - const stderr = io.lockStderrWriter(&buf) catch |e| switch (e) { + const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) { error.Canceled => return, }; - defer io.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &run.step, .{}, &stderr.interface, stderr.mode, .verbose, .indent) catch {}; + defer io.unlockStderr(); + build_runner.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {}; return; }, else => { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 0df58b24b7..74b41634a7 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -328,16 +328,17 @@ pub fn cast(step: *Step, comptime T: type) ?*T { } /// For debugging purposes, prints identifying information about this Step. -pub fn dump(step: *Step, w: *Io.Writer, fwm: Io.File.Writer.Mode) void { +pub fn dump(step: *Step, t: Io.Terminal) void { + const w = t.writer; if (step.debug_stack_trace.instruction_addresses.len > 0) { w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; - std.debug.writeStackTrace(&step.debug_stack_trace, w, fwm) catch {}; + std.debug.writeStackTrace(&step.debug_stack_trace, t) catch {}; } else { const field = "debug_stack_frames_count"; comptime assert(@hasField(Build, field)); - fwm.setColor(w, .yellow) catch {}; + t.setColor(.yellow) catch {}; w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {}; - fwm.setColor(w, .reset) catch {}; + t.setColor(.reset) catch {}; } } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 888775884d..4752046089 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -925,20 +925,21 @@ const CliNamedModules = struct { fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 { const step = &compile.step; const b = step.owner; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; const maybe_path: ?*GeneratedFile = @field(compile, tag_name); const generated_file = maybe_path orelse { - const stderr = try io.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {}; - io.unlockStderrWriter(); + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {}; + io.unlockStderr(); @panic("missing emit option for " ++ tag_name); }; const path = generated_file.path orelse { - const stderr = try io.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, &stderr.interface, stderr.mode, compile.step.owner, asking_step) catch {}; - io.unlockStderrWriter(); + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {}; + io.unlockStderr(); @panic(tag_name ++ " is null. Is there a missing step dependency?"); }; @@ -1907,7 +1908,7 @@ fn checkCompileErrors(compile: *Compile) !void { try actual_eb.renderToWriter(.{ .include_reference_trace = false, .include_source_line = false, - }, &aw.writer, .streaming); + }, &aw.writer); break :ae try aw.toOwnedSlice(); }; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 67cf201374..157a0292e7 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1559,7 +1559,8 @@ fn spawnChildAndCollect( ) !?EvalGenericResult { const b = run.step.owner; const arena = b.allocator; - const io = b.graph.io; + const graph = b.graph; + const io = graph.io; if (fuzz_context != null) { assert(!has_side_effects); @@ -1625,11 +1626,12 @@ fn spawnChildAndCollect( if (!run.disable_zig_progress and !inherit) { child.progress_node = options.progress_node; } - if (inherit) { - const stderr = try io.lockStderrWriter(&.{}); - try setColorEnvironmentVariables(run, env_map, stderr.mode); - } - defer if (inherit) io.unlockStderrWriter(); + const terminal_mode: Io.Terminal.Mode = if (inherit) m: { + const stderr = try io.lockStderr(&.{}, graph.stderr_mode); + break :m stderr.terminal_mode; + } else .no_color; + defer if (inherit) io.unlockStderr(); + try setColorEnvironmentVariables(run, env_map, terminal_mode); var timer = try std.time.Timer.start(); const res = try evalGeneric(run, &child); run.step.result_duration_ns = timer.read(); @@ -1637,7 +1639,7 @@ fn spawnChildAndCollect( } } -fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, fwm: Io.File.Writer.Mode) !void { +fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, terminal_mode: Io.Terminal.Mode) !void { color: switch (run.color) { .manual => {}, .enable => { @@ -1648,9 +1650,9 @@ fn setColorEnvironmentVariables(run: *Run, env_map: *EnvMap, fwm: Io.File.Writer try env_map.put("NO_COLOR", "1"); env_map.remove("CLICOLOR_FORCE"); }, - .inherit => switch (fwm) { - .terminal_escaped => continue :color .enable, - else => continue :color .disable, + .inherit => switch (terminal_mode) { + .no_color, .windows_api => continue :color .disable, + .escape_codes => continue :color .enable, }, .auto => { const capture_stderr = run.captured_stderr != null or switch (run.stdio) { diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 6fa05b16d2..78049633a0 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -713,7 +713,7 @@ pub const VTable = struct { processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File, processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize, lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr, - tryLockStderr: *const fn (?*anyopaque, buffer: []u8) Cancelable!?LockedStderr, + tryLockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!?LockedStderr, unlockStderr: *const fn (?*anyopaque) void, now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp, diff --git a/lib/std/Io/File/Writer.zig b/lib/std/Io/File/Writer.zig index 1d0494c674..56a1c09340 100644 --- a/lib/std/Io/File/Writer.zig +++ b/lib/std/Io/File/Writer.zig @@ -229,7 +229,7 @@ pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void { .positional, .positional_simple => { w.pos = offset; }, - .streaming, .streaming_simple, .terminal_escaped, .terminal_winapi => { + .streaming, .streaming_simple => { if (w.seek_err) |err| return err; io.vtable.fileSeekTo(io.userdata, w.file, offset) catch |err| { w.seek_err = err; diff --git a/lib/std/Io/Terminal.zig b/lib/std/Io/Terminal.zig index cd0ec56caa..a39f2175d2 100644 --- a/lib/std/Io/Terminal.zig +++ b/lib/std/Io/Terminal.zig @@ -130,25 +130,3 @@ pub fn setColor(t: Terminal, color: Color) Io.Writer.Error!void { }, } } - -pub fn disableEscape(t: *Terminal) Mode { - const prev = t.mode; - t.mode = t.mode.toUnescaped(); - return prev; -} - -pub fn restoreEscape(t: *Terminal, mode: Mode) void { - t.mode = mode; -} - -pub fn writeAllUnescaped(t: *Terminal, bytes: []const u8) Io.Writer.Error!void { - const prev_mode = t.disableEscape(); - defer t.restoreEscape(prev_mode); - return t.interface.writeAll(bytes); -} - -pub fn printUnescaped(t: *Terminal, comptime fmt: []const u8, args: anytype) Io.Writer.Error!void { - const prev_mode = t.disableEscape(); - defer t.restoreEscape(prev_mode); - return t.interface.print(fmt, args); -} diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 3e7b6950d4..b07a9bb9a8 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -7178,7 +7178,7 @@ fn fileWriteFileStreaming( break :o .{ &off, @min(@intFromEnum(limit), size - file_reader.pos, max_count) }; }, .streaming => .{ null, limit.minInt(max_count) }, - .streaming_reading, .positional_reading => break :sf, + .streaming_simple, .positional_simple => break :sf, .failure => return error.ReadFailed, }; const current_thread = Thread.getCurrent(t); @@ -7251,7 +7251,7 @@ fn fileWriteFileStreaming( } var off_in: i64 = undefined; const off_in_ptr: ?*i64 = switch (file_reader.mode) { - .positional_reading, .streaming_reading => return error.Unimplemented, + .positional_simple, .streaming_simple => return error.Unimplemented, .positional => p: { off_in = @intCast(file_reader.pos); break :p &off_in; @@ -7427,7 +7427,7 @@ fn fileWriteFilePositional( } var off_in: i64 = undefined; const off_in_ptr: ?*i64 = switch (file_reader.mode) { - .positional_reading, .streaming_reading => return error.Unimplemented, + .positional_simple, .streaming_simple => return error.Unimplemented, .positional => p: { off_in = @intCast(file_reader.pos); break :p &off_in; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index fd3a456ff7..e33a2bd575 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -283,12 +283,12 @@ var static_single_threaded_io: Io.Threaded = .init_single_threaded; /// /// Alternatively, use the higher-level `Io.lockStderr` to integrate with the /// application's chosen `Io` implementation. -pub fn lockStderr(buffer: []u8) Io.Terminal { - return (static_single_threaded_io.ioBasic().lockStderr(buffer, null) catch |err| switch (err) { +pub fn lockStderr(buffer: []u8) Io.LockedStderr { + return static_single_threaded_io.ioBasic().lockStderr(buffer, null) catch |err| switch (err) { // Impossible to cancel because no calls to cancel using // `static_single_threaded_io` exist. error.Canceled => unreachable, - }).terminal(); + }; } pub fn unlockStderr() void { @@ -311,7 +311,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void { var buffer: [64]u8 = undefined; const stderr = lockStderr(&buffer); defer unlockStderr(); - stderr.writer.print(fmt, args) catch return; + stderr.file_writer.interface.print(fmt, args) catch return; } } @@ -327,7 +327,7 @@ pub inline fn getSelfDebugInfo() !*SelfInfo { /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. /// Obtains the stderr mutex while dumping. pub fn dumpHex(bytes: []const u8) void { - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); dumpHexFallible(stderr, bytes) catch {}; } @@ -551,7 +551,7 @@ pub fn defaultPanic( _ = panicking.fetchAdd(1, .seq_cst); trace: { - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); const writer = stderr.writer; @@ -581,7 +581,7 @@ pub fn defaultPanic( // A panic happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); stderr.writer.writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. @@ -751,7 +751,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin } /// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors. pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); writeCurrentStackTrace(.{ .first_address = a: { @@ -814,7 +814,7 @@ pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void } /// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors. pub fn dumpStackTrace(st: *const StackTrace) void { - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); writeStackTrace(st, stderr) catch |err| switch (err) { error.WriteFailed => {}, @@ -1550,7 +1550,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex _ = panicking.fetchAdd(1, .seq_cst); trace: { - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); if (addr) |a| { @@ -1571,7 +1571,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex // A segfault happened while trying to print a previous panic message. // We're still holding the mutex but that's fine as we're going to // call abort(). - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); stderr.writer.writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. @@ -1678,7 +1678,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize pub fn dump(t: @This()) void { if (!enabled) return; - const stderr = lockStderr(&.{}); + const stderr = lockStderr(&.{}).terminal(); defer unlockStderr(); const end = @min(t.index, size); for (t.addrs[0..end], 0..) |frames_array, i| { diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig index 2d0e5abf4e..34e8f7b43c 100644 --- a/lib/std/debug/simple_panic.zig +++ b/lib/std/debug/simple_panic.zig @@ -14,9 +14,9 @@ const std = @import("../std.zig"); pub fn call(msg: []const u8, ra: ?usize) noreturn { @branchHint(.cold); _ = ra; - const stderr = std.debug.lockStderrWriter(&.{}); - stderr.interface.writeAll(msg) catch {}; - stderr.interface.flush(msg) catch {}; + const stderr_writer = std.debug.lockStderr(&.{}, null).terminal().writer; + stderr_writer.writeAll(msg) catch {}; + stderr_writer.flush(msg) catch {}; @trap(); } diff --git a/lib/std/json/dynamic.zig b/lib/std/json/dynamic.zig index f85916670b..e38ea9cb17 100644 --- a/lib/std/json/dynamic.zig +++ b/lib/std/json/dynamic.zig @@ -47,9 +47,9 @@ pub const Value = union(enum) { } pub fn dump(v: Value) void { - const stderr = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - json.Stringify.value(v, .{}, &stderr.interface) catch return; + const stderr = std.debug.lockStderr(&.{}, null); + defer std.debug.unlockStderr(); + json.Stringify.value(v, .{}, &stderr.file_writer.interface) catch return; } pub fn jsonStringify(value: @This(), jws: anytype) !void { diff --git a/lib/std/log.zig b/lib/std/log.zig index 8579bb04e0..81bfc4ebb6 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -92,7 +92,7 @@ pub fn defaultLog( args: anytype, ) void { var buffer: [64]u8 = undefined; - const stderr = std.debug.lockStderr(&buffer); + const stderr = std.debug.lockStderr(&buffer).terminal(); defer std.debug.unlockStderr(); return defaultLogFileTerminal(level, scope, format, args, stderr) catch {}; } diff --git a/lib/std/process.zig b/lib/std/process.zig index 45cd575133..23a3d92e9b 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1856,7 +1856,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 { /// and does not return. pub fn cleanExit(io: Io) void { if (builtin.mode == .Debug) return; - _ = io.lockStderrWriter(&.{}) catch {}; + _ = io.lockStderr(&.{}, .no_color) catch {}; exit(0); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index be6f316804..98fca2f2d5 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -368,8 +368,8 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const break :diff_index if (expected.len == actual.len) return else shortest; }; if (!backend_can_print) return error.TestExpectedEqual; - if (io.lockStderrWriter(&.{})) |stderr| { - defer io.unlockStderrWriter(); + if (io.lockStderr(&.{}, null)) |stderr| { + defer io.unlockStderr(); failEqualSlices(T, expected, actual, diff_index, &stderr.interface, stderr.mode) catch {}; } else |_| {} return error.TestExpectedEqual; @@ -381,7 +381,7 @@ fn failEqualSlices( actual: []const T, diff_index: usize, w: *Io.Writer, - fwm: Io.File.Writer.Mode, + terminal_mode: Io.Terminal.Mode, ) !void { try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); @@ -404,12 +404,12 @@ fn failEqualSlices( var differ = if (T == u8) BytesDiffer{ .expected = expected_window, .actual = actual_window, - .file_writer_mode = fwm, + .terminal_mode = terminal_mode, } else SliceDiffer(T){ .start_index = window_start, .expected = expected_window, .actual = actual_window, - .file_writer_mode = fwm, + .terminal_mode = terminal_mode, }; // Print indexes as hex for slices of u8 since it's more likely to be binary data where @@ -466,21 +466,22 @@ fn SliceDiffer(comptime T: type) type { start_index: usize, expected: []const T, actual: []const T, - file_writer_mode: Io.File.Writer.Mode, + terminal_mode: Io.Terminal.Mode, const Self = @This(); pub fn write(self: Self, writer: *Io.Writer) !void { + const t: Io.Terminal = .{ .writer = writer, .mode = self.terminal_mode }; for (self.expected, 0..) |value, i| { const full_index = self.start_index + i; const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true; - if (diff) try self.file_writer_mode.setColor(writer, .red); + if (diff) try t.setColor(writer, .red); if (@typeInfo(T) == .pointer) { try writer.print("[{}]{*}: {any}\n", .{ full_index, value, value }); } else { try writer.print("[{}]: {any}\n", .{ full_index, value }); } - if (diff) try self.file_writer_mode.setColor(writer, .reset); + if (diff) try t.setColor(writer, .reset); } } }; @@ -489,7 +490,7 @@ fn SliceDiffer(comptime T: type) type { const BytesDiffer = struct { expected: []const u8, actual: []const u8, - file_writer_mode: Io.File.Writer.Mode, + terminal_mode: Io.Terminal.Mode, pub fn write(self: BytesDiffer, writer: *Io.Writer) !void { var expected_iterator = std.mem.window(u8, self.expected, 16, 16); @@ -516,7 +517,7 @@ const BytesDiffer = struct { try self.writeDiff(writer, "{c}", .{byte}, diff); } else { // TODO: remove this `if` when https://github.com/ziglang/zig/issues/7600 is fixed - if (self.file_writer_mode == .terminal_winapi) { + if (self.terminal_mode == .windows_api) { try self.writeDiff(writer, ".", .{}, diff); continue; } diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 6e89c75d91..6212264005 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -46,25 +46,18 @@ pub const SrcHasher = std.crypto.hash.Blake3; pub const SrcHash = [16]u8; pub const Color = enum { - /// Determine whether stderr is a terminal or not automatically. + /// Auto-detect whether stream supports terminal colors. auto, - /// Assume stderr is not a terminal. + /// Force-enable colors. off, - /// Assume stderr is a terminal. + /// Suppress colors. on, - pub fn getTtyConf(color: Color, detected: Io.File.Writer.Mode) Io.File.Writer.Mode { + pub fn terminalMode(color: Color) ?Io.Terminal.Mode { return switch (color) { - .auto => detected, - .on => .terminal_escaped, - .off => .streaming, - }; - } - pub fn detectTtyConf(color: Color, io: Io) Io.File.Writer.Mode { - return switch (color) { - .auto => .detect(io, .stderr()), - .on => .terminal_escaped, - .off => .streaming, + .auto => null, + .on => .escape_codes, + .off => .no_color, }; } }; diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index 556b1167a3..c5275729ae 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -166,51 +166,53 @@ pub const RenderToStderrError = Io.Cancelable || Io.File.Writer.Error; pub fn renderToStderr(eb: ErrorBundle, io: Io, options: RenderOptions, color: std.zig.Color) RenderToStderrError!void { var buffer: [256]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - renderToWriter(eb, options, &stderr.interface, color.getTtyConf(stderr.mode)) catch |err| switch (err) { - error.WriteFailed => return stderr.err.?, + const stderr = try io.lockStderr(&buffer, color.terminalMode()); + defer io.unlockStderr(); + renderToTerminal(eb, options, stderr.terminal()) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, else => |e| return e, }; } -pub fn renderToWriter( - eb: ErrorBundle, - options: RenderOptions, - w: *Writer, - fwm: Io.File.Writer.Mode, -) Io.File.Writer.Mode.SetColorError!void { +pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) Writer.Error!void { + return renderToTerminal(eb, options, .{ .writer = w, .mode = .no_color }) catch |err| switch (err) { + error.WriteFailed => |e| return e, + else => unreachable, + }; +} + +pub fn renderToTerminal(eb: ErrorBundle, options: RenderOptions, t: Io.Terminal) Io.Terminal.SetColorError!void { if (eb.extra.len == 0) return; for (eb.getMessages()) |err_msg| { - try renderErrorMessageToWriter(eb, options, err_msg, w, fwm, "error", .red, 0); + try renderErrorMessage(eb, options, err_msg, t, "error", .red, 0); } if (options.include_log_text) { const log_text = eb.getCompileLogOutput(); if (log_text.len != 0) { - try w.writeAll("\nCompile Log Output:\n"); - try w.writeAll(log_text); + try t.writer.writeAll("\nCompile Log Output:\n"); + try t.writer.writeAll(log_text); } } } -fn renderErrorMessageToWriter( +fn renderErrorMessage( eb: ErrorBundle, options: RenderOptions, err_msg_index: MessageIndex, - w: *Writer, - fwm: Io.File.Writer.Mode, + t: Io.Terminal, kind: []const u8, - color: Io.File.Writer.Color, + color: Io.Terminal.Color, indent: usize, -) Io.File.Writer.Mode.SetColorError!void { +) Io.Terminal.SetColorError!void { + const w = t.writer; const err_msg = eb.getErrorMessage(err_msg_index); if (err_msg.src_loc != .none) { const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); var prefix: Writer.Discarding = .init(&.{}); try w.splatByteAll(' ', indent); prefix.count += indent; - try fwm.setColor(w, .bold); + try t.setColor(.bold); try w.print("{s}:{d}:{d}: ", .{ eb.nullTerminatedString(src.data.src_path), src.data.line + 1, @@ -221,7 +223,7 @@ fn renderErrorMessageToWriter( src.data.line + 1, src.data.column + 1, }); - try fwm.setColor(w, color); + try t.setColor(color); try w.writeAll(kind); prefix.count += kind.len; try w.writeAll(": "); @@ -229,17 +231,17 @@ fn renderErrorMessageToWriter( // This is the length of the part before the error message: // e.g. "file.zig:4:5: error: " const prefix_len: usize = @intCast(prefix.count); - try fwm.setColor(w, .reset); - try fwm.setColor(w, .bold); + try t.setColor(.reset); + try t.setColor(.bold); if (err_msg.count == 1) { try writeMsg(eb, err_msg, w, prefix_len); try w.writeByte('\n'); } else { try writeMsg(eb, err_msg, w, prefix_len); - try fwm.setColor(w, .dim); + try t.setColor(.dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try fwm.setColor(w, .reset); + try t.setColor(.reset); if (src.data.source_line != 0 and options.include_source_line) { const line = eb.nullTerminatedString(src.data.source_line); for (line) |b| switch (b) { @@ -252,19 +254,19 @@ fn renderErrorMessageToWriter( // -1 since span.main includes the caret const after_caret = src.data.span_end -| src.data.span_main -| 1; try w.splatByteAll(' ', src.data.column - before_caret); - try fwm.setColor(w, .green); + try t.setColor(.green); try w.splatByteAll('~', before_caret); try w.writeByte('^'); try w.splatByteAll('~', after_caret); try w.writeByte('\n'); - try fwm.setColor(w, .reset); + try t.setColor(.reset); } for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent); + try renderErrorMessage(eb, options, note, t, "note", .cyan, indent); } if (src.data.reference_trace_len > 0 and options.include_reference_trace) { - try fwm.setColor(w, .reset); - try fwm.setColor(w, .dim); + try t.setColor(.reset); + try t.setColor(.dim); try w.print("referenced by:\n", .{}); var ref_index = src.end; for (0..src.data.reference_trace_len) |_| { @@ -291,25 +293,25 @@ fn renderErrorMessageToWriter( ); } } - try fwm.setColor(w, .reset); + try t.setColor(.reset); } } else { - try fwm.setColor(w, color); + try t.setColor(color); try w.splatByteAll(' ', indent); try w.writeAll(kind); try w.writeAll(": "); - try fwm.setColor(w, .reset); + try t.setColor(.reset); const msg = eb.nullTerminatedString(err_msg.msg); if (err_msg.count == 1) { try w.print("{s}\n", .{msg}); } else { try w.print("{s}", .{msg}); - try fwm.setColor(w, .dim); + try t.setColor(.dim); try w.print(" ({d} times)\n", .{err_msg.count}); } - try fwm.setColor(w, .reset); + try t.setColor(.reset); for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, fwm, "note", .cyan, indent + 4); + try renderErrorMessage(eb, options, note, t, "note", .cyan, indent + 4); } } } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 6c11c3021b..94d877b406 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -6333,25 +6333,25 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined; fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_changed: *bool) ![]u8 { var buffer: [64]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); var tree = try std.zig.Ast.parse(allocator, source, .zig); defer tree.deinit(allocator); for (tree.errors) |parse_error| { const loc = tree.tokenLocation(0, parse_error.token); - try stderr.printUnescaped("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 }); - try tree.renderError(parse_error, &stderr.interface); - try stderr.interface.print("\n{s}\n", .{source[loc.line_start..loc.line_end]}); + try stderr.writer.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 }); + try tree.renderError(parse_error, stderr.writer); + try stderr.writer.print("\n{s}\n", .{source[loc.line_start..loc.line_end]}); { var i: usize = 0; while (i < loc.column) : (i += 1) { - try stderr.writeAllUnescaped(" "); + try stderr.writer.writeAll(" "); } - try stderr.writeAllUnescaped("^"); + try stderr.writer.writeAll("^"); } - try stderr.writeAllUnescaped("\n"); + try stderr.writer.writeAll("\n"); } if (tree.errors.len != 0) { return error.ParseError; diff --git a/src/Air/print.zig b/src/Air/print.zig index 05614a0ed3..98b0a0b242 100644 --- a/src/Air/print.zig +++ b/src/Air/print.zig @@ -76,9 +76,9 @@ pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { const comp = pt.zcu.comp; const io = comp.io; var buffer: [512]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; air.write(w, pt, liveness); } @@ -86,9 +86,9 @@ pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Ai const comp = pt.zcu.comp; const io = comp.io; var buffer: [512]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; air.writeInst(w, inst, pt, liveness); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 37e15ab171..f3fcef40a0 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2092,14 +2092,16 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, } if (options.verbose_llvm_cpu_features) { - if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: { - const stderr = try io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - const w = &stderr.interface; - w.print("compilation: {s}\n", .{options.root_name}) catch break :print; - w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print; - w.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print; - w.print(" features: {s}\n", .{cf}) catch {}; + if (options.root_mod.resolved_target.llvm_cpu_features) |cf| { + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + printVerboseLlvmCpuFeatures(w, arena, options.root_name, target, cf) catch |err| switch (err) { + error.WriteFailed => switch (stderr.file_writer.err.?) { + error.Canceled => |e| return e, + else => {}, + }, + }; } } @@ -2700,6 +2702,19 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, return comp; } +fn printVerboseLlvmCpuFeatures( + w: *Writer, + arena: Allocator, + root_name: []const u8, + target: *const std.Target, + cf: [*:0]const u8, +) Writer.Error!void { + try w.print("compilation: {s}\n", .{root_name}); + try w.print(" target: {s}\n", .{try target.zigTriple(arena)}); + try w.print(" cpu: {s}\n", .{target.cpu.model.name}); + try w.print(" features: {s}\n", .{cf}); +} + pub fn destroy(comp: *Compilation) void { const gpa = comp.gpa; const io = comp.io; @@ -4259,9 +4274,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { // However, we haven't reported any such error. // This is a compiler bug. print_ctx: { - const stderr = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = std.debug.lockStderr(&.{}).terminal(); + defer std.debug.unlockStderr(); + const w = stderr.writer; w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx; w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx; while (ref) |r| { @@ -7772,11 +7787,11 @@ pub fn lockAndSetMiscFailure( pub fn dumpArgv(io: Io, argv: []const []const u8) Io.Cancelable!void { var buffer: [64]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; return dumpArgvWriter(w, argv) catch |err| switch (err) { - error.WriteFailed => switch (stderr.err.?) { + error.WriteFailed => switch (stderr.file_writer.err.?) { error.Canceled => return error.Canceled, else => return, }, diff --git a/src/InternPool.zig b/src/InternPool.zig index 539cb441c5..98bde244c5 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -11169,9 +11169,9 @@ pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) v pub fn dump(ip: *const InternPool, io: Io) Io.Cancelable!void { var buffer: [4096]u8 = undefined; - const stderr_writer = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr_writer.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; try dumpStatsFallible(ip, w, std.heap.page_allocator); try dumpAllFallible(ip, w); } @@ -11536,8 +11536,8 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { pub fn dumpGenericInstances(ip: *const InternPool, io: Io, allocator: Allocator) Io.Cancelable!void { var buffer: [4096]u8 = undefined; - const stderr_writer = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); + const stderr_writer = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); const w = &stderr_writer.interface; try ip.dumpGenericInstancesFallible(allocator, w); } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 76ab3e229c..103cbaaaae 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -4560,10 +4560,10 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e if (build_options.enable_debug_extensions and comp.verbose_air) p: { const io = comp.io; - const stderr = try io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - printVerboseAir(pt, liveness, fqn, air, &stderr.interface) catch |err| switch (err) { - error.WriteFailed => switch (stderr.err.?) { + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + printVerboseAir(pt, liveness, fqn, air, &stderr.file_writer.interface) catch |err| switch (err) { + error.WriteFailed => switch (stderr.file_writer.err.?) { error.Canceled => |e| return e, else => break :p, }, diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 138c70fecf..93a6e0a768 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -11274,16 +11274,15 @@ fn initValueAdvanced( } pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { const zcu = isel.pt.zcu; - const io = zcu.comp.io; const gpa = zcu.gpa; const ip = &zcu.intern_pool; const nav = ip.getNav(isel.nav_index); errdefer |err| @panic(@errorName(err)); - const stderr_writer = io.lockStderrWriter(&.{}) catch return; - defer io.unlockStderrWriter(); - const stderr = &stderr_writer.interface; + const locked_stderr = std.debug.lockStderr(&.{}, null); + defer std.debug.unlockStderr(); + const stderr = &locked_stderr.file_writer.interface; var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty; defer { diff --git a/src/crash_report.zig b/src/crash_report.zig index f23806b758..e56bc7cec5 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -95,9 +95,9 @@ fn dumpCrashContext() Io.Writer.Error!void { // TODO: this does mean that a different thread could grab the stderr mutex between the context // and the actual panic printing, which would be quite confusing. - const stderr = std.debug.lockStderrWriter(&.{}); - defer std.debug.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = std.debug.lockStderr(&.{}); + defer std.debug.unlockStderr(); + const w = &stderr.file_writer.interface; try w.writeAll("Compiler crash context:\n"); diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index a76fec9237..8cf1dfa303 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -314,14 +314,14 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { if (comp.verbose_cc) { var buffer: [256]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) { - error.WriteFailed => return stderr.err.?, + error.WriteFailed => return stderr.file_writer.err.?, }; w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) { - error.WriteFailed => return stderr.err.?, + error.WriteFailed => return stderr.file_writer.err.?, }; } @@ -339,12 +339,12 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) { var buffer: [64]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); for (aro_comp.diagnostics.output.to_list.messages.items) |msg| { if (msg.kind == .@"fatal error" or msg.kind == .@"error") { - msg.write(&stderr.interface, stderr.mode, true) catch |err| switch (err) { - error.WriteFailed => return stderr.err.?, + msg.write(stderr.terminal(), true) catch |err| switch (err) { + error.WriteFailed => return stderr.file_writer.err.?, }; return error.AroPreprocessorFailed; } @@ -365,9 +365,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { error.OutOfMemory => |e| return e, error.ParseError => { var buffer: [64]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; try w.writeAll("error: "); try def_diagnostics.writeMsg(w, input); try w.writeByte('\n'); diff --git a/src/libs/mingw/def.zig b/src/libs/mingw/def.zig index 9a105b6182..f1c112d16e 100644 --- a/src/libs/mingw/def.zig +++ b/src/libs/mingw/def.zig @@ -1039,9 +1039,9 @@ fn testParse( const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.ParseError => { - const stderr = try io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&.{}, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; try diagnostics.writeMsg(w, source); try w.writeByte('\n'); return err; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index d379669613..03b757f5b4 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -2382,9 +2382,9 @@ pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void { const comp = coff.base.comp; const io = comp.io; var buffer: [512]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; coff.printNode(tid, w, .root, 0) catch |err| switch (err) { error.WriteFailed => return stderr.err.?, }; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 3c511f1ee9..bbdb439385 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -3733,9 +3733,9 @@ pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void { const comp = elf.base.comp; const io = comp.io; var buffer: [512]u8 = undefined; - const stderr = try io.lockStderrWriter(&buffer); - defer io.unlockStderrWriter(); - const w = &stderr.interface; + const stderr = try io.lockStderr(&buffer, null); + defer io.lockStderr(); + const w = &stderr.file_writer.interface; elf.printNode(tid, w, .root, 0) catch |err| switch (err) { error.WriteFailed => return stderr.err.?, }; diff --git a/src/main.zig b/src/main.zig index c5ed278921..8e30febb81 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4429,9 +4429,9 @@ fn runOrTest( // the error message and invocation below. if (process.can_execv and arg_mode == .run) { // execv releases the locks; no need to destroy the Compilation here. - _ = try io.lockStderrWriter(&.{}); + _ = try io.lockStderr(&.{}, .no_color); const err = process.execve(gpa, argv.items, &env_map); - io.unlockStderrWriter(); + io.unlockStderr(); try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc); const cmd = try std.mem.join(arena, " ", argv.items); fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd }); @@ -4448,8 +4448,8 @@ fn runOrTest( comp_destroyed.* = true; const term_result = t: { - _ = try io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); + _ = try io.lockStderr(&.{}, .no_color); + defer io.unlockStderr(); break :t child.spawnAndWait(io); }; const term = term_result catch |err| { @@ -5418,8 +5418,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) child.stderr_behavior = .Inherit; const term = t: { - _ = try io.lockStderrWriter(&.{}); - defer io.unlockStderrWriter(); + _ = try io.lockStderr(&.{}, .no_color); + defer io.unlockStderr(); break :t child.spawnAndWait(io) catch |err| fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err }); }; -- cgit v1.2.3 From a8088306f6223b07ad9b7ae37486bcc9e0ac08c9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 19 Dec 2025 16:42:28 -0800 Subject: std: rename other Dir "make" functions to "create" --- lib/compiler/build_runner.zig | 6 +-- lib/compiler/translate-c/main.zig | 2 +- lib/std/Build.zig | 6 +-- lib/std/Build/Cache.zig | 8 ++-- lib/std/Build/Cache/Path.zig | 8 ++-- lib/std/Build/Step.zig | 6 +-- lib/std/Build/Step/Compile.zig | 4 +- lib/std/Build/Step/ConfigHeader.zig | 2 +- lib/std/Build/Step/ObjCopy.zig | 2 +- lib/std/Build/Step/Options.zig | 4 +- lib/std/Build/Step/Run.zig | 6 +-- lib/std/Build/Step/UpdateSourceFiles.zig | 2 +- lib/std/Build/Step/WriteFile.zig | 8 ++-- lib/std/Io.zig | 6 +-- lib/std/Io/Dir.zig | 40 +++++++++---------- lib/std/Io/Kqueue.zig | 12 +++--- lib/std/Io/Threaded.zig | 65 +++++++++++++++---------------- lib/std/fs/test.zig | 66 ++++++++++++++++---------------- lib/std/posix.zig | 2 +- lib/std/tar.zig | 6 +-- lib/std/testing.zig | 6 +-- lib/std/zip.zig | 4 +- src/Compilation.zig | 34 ++++++++-------- src/Package/Fetch.zig | 12 +++--- src/Package/Fetch/git.zig | 4 +- src/libs/freebsd.zig | 4 +- src/libs/glibc.zig | 4 +- src/libs/mingw.zig | 4 +- src/libs/netbsd.zig | 4 +- src/link/MachO.zig | 2 +- src/main.zig | 8 ++-- 31 files changed, 171 insertions(+), 176 deletions(-) (limited to 'lib/std/Build/Step.zig') diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 1c30ecaadc..cfe0fee78f 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -66,12 +66,12 @@ pub fn main() !void { const local_cache_directory: std.Build.Cache.Directory = .{ .path = cache_root, - .handle = try cwd.makeOpenPath(io, cache_root, .{}), + .handle = try cwd.createDirPathOpen(io, cache_root, .{}), }; const global_cache_directory: std.Build.Cache.Directory = .{ .path = global_cache_root, - .handle = try cwd.makeOpenPath(io, global_cache_root, .{}), + .handle = try cwd.createDirPathOpen(io, global_cache_root, .{}), }; var graph: std.Build.Graph = .{ @@ -80,7 +80,7 @@ pub fn main() !void { .cache = .{ .io = io, .gpa = arena, - .manifest_dir = try local_cache_directory.handle.makeOpenPath(io, "h", .{}), + .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}), }, .zig_exe = zig_exe, .env_map = try process.getEnvMap(arena), diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index d02f21a2a8..80dc67fbfe 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -253,7 +253,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration if (d.output_name) |path| blk: { if (std.mem.eql(u8, path, "-")) break :blk; if (std.fs.path.dirname(path)) |dirname| { - Io.Dir.cwd().makePath(io, dirname) catch |err| + Io.Dir.cwd().createDirPath(io, dirname) catch |err| return d.fatal("failed to create path to '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); } out_file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| { diff --git a/lib/std/Build.zig b/lib/std/Build.zig index cf0b9e5b0d..4b8909e689 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1701,14 +1701,14 @@ pub fn addCheckFile( return Step.CheckFile.create(b, file_source, options); } -pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Dir.StatFileError)!void { +pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.CreateDirError || Io.Dir.StatFileError)!void { const io = b.graph.io; if (b.verbose) log.info("truncate {s}", .{dest_path}); const cwd = Io.Dir.cwd(); var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { error.FileNotFound => blk: { if (fs.path.dirname(dest_path)) |dirname| { - try cwd.makePath(io, dirname); + try cwd.createDirPath(io, dirname); } break :blk try cwd.createFile(io, dest_path, .{}); }, @@ -2654,7 +2654,7 @@ pub fn makeTempPath(b: *Build) []const u8 { const rand_int = std.crypto.random.int(u64); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); - b.cache_root.handle.makePath(io, tmp_dir_sub_path) catch |err| { + b.cache_root.handle.createDirPath(io, tmp_dir_sub_path) catch |err| { std.debug.print("unable to make tmp path '{s}': {t}\n", .{ result_path, err }); }; return result_path; diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index 43f8691000..396f204350 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -1330,7 +1330,7 @@ test "cache file and then recall it" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(io, temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); defer cache.manifest_dir.close(io); @@ -1396,7 +1396,7 @@ test "check that changing a file makes cache fail" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(io, temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); defer cache.manifest_dir.close(io); @@ -1456,7 +1456,7 @@ test "no file inputs" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(io, temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); defer cache.manifest_dir.close(io); @@ -1515,7 +1515,7 @@ test "Manifest with files added after initial hash work" { var cache: Cache = .{ .io = io, .gpa = testing.allocator, - .manifest_dir = try tmp.dir.makeOpenPath(io, temp_manifest_dir, .{}), + .manifest_dir = try tmp.dir.createDirPathOpen(io, temp_manifest_dir, .{}), }; cache.addPrefix(.{ .path = null, .handle = tmp.dir }); defer cache.manifest_dir.close(io); diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig index 3ef4dec658..2b7814c544 100644 --- a/lib/std/Build/Cache/Path.zig +++ b/lib/std/Build/Cache/Path.zig @@ -84,14 +84,14 @@ pub fn openDir( return p.root_dir.handle.openDir(io, joined_path, args); } -pub fn makeOpenPath(p: Path, io: Io, sub_path: []const u8, opts: Io.Dir.OpenOptions) !Io.Dir { +pub fn createDirPathOpen(p: Path, io: Io, sub_path: []const u8, opts: Io.Dir.OpenOptions) !Io.Dir { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.makeOpenPath(io, joined_path, opts); + return p.root_dir.handle.createDirPathOpen(io, joined_path, opts); } pub fn statFile(p: Path, io: Io, sub_path: []const u8) !Io.Dir.Stat { @@ -129,14 +129,14 @@ pub fn access(p: Path, io: Io, sub_path: []const u8, flags: Io.Dir.AccessOptions return p.root_dir.handle.access(io, joined_path, flags); } -pub fn makePath(p: Path, io: Io, sub_path: []const u8) !void { +pub fn createDirPath(p: Path, io: Io, sub_path: []const u8) !void { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.makePath(io, joined_path); + return p.root_dir.handle.createDirPath(io, joined_path); } pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 74b41634a7..243dee8604 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -516,12 +516,12 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); } -/// Wrapper around `Io.Dir.makePathStatus` that handles verbose and error output. -pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.MakePathStatus { +/// Wrapper around `Io.Dir.createDirPathStatus` that handles verbose and error output. +pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.CreatePathStatus { const b = s.owner; const io = b.graph.io; try handleVerbose(b, null, &.{ "install", "-d", dest_path }); - return Io.Dir.cwd().makePathStatus(io, dest_path, .default_dir) catch |err| + return Io.Dir.cwd().createDirPathStatus(io, dest_path, .default_dir) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 4752046089..0454e5b79d 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -1669,7 +1669,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { args_length += arg.len + 1; // +1 to account for null terminator } if (args_length >= 30 * 1024) { - try b.cache_root.handle.makePath(io, "args"); + try b.cache_root.handle.createDirPath(io, "args"); const args_to_escape = zig_args.items[2..]; var escaped_args = try std.array_list.Managed([]const u8).initCapacity(arena, args_to_escape.len); @@ -1706,7 +1706,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { // The args file is already present from a previous run. } else |err| switch (err) { error.FileNotFound => { - try b.cache_root.handle.makePath(io, "tmp"); + try b.cache_root.handle.createDirPath(io, "tmp"); const rand_int = std.crypto.random.int(u64); const tmp_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); try b.cache_root.handle.writeFile(io, .{ .sub_path = tmp_path, .data = args }); diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 250bae5009..b55efc0da4 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const sub_path = b.pathJoin(&.{ "o", &digest, config_header.include_path }); const sub_path_dirname = std.fs.path.dirname(sub_path).?; - b.cache_root.handle.makePath(io, sub_path_dirname) catch |err| { + b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, sub_path_dirname, @errorName(err), }); diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig index b81f59b9a1..ea0714adf9 100644 --- a/lib/std/Build/Step/ObjCopy.zig +++ b/lib/std/Build/Step/ObjCopy.zig @@ -177,7 +177,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const cache_path = "o" ++ fs.path.sep_str ++ digest; const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename }); const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) }); - b.cache_root.handle.makePath(io, cache_path) catch |err| { + b.cache_root.handle.createDirPath(io, cache_path) catch |err| { return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); }; diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 676ea4d851..610d417aea 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -477,7 +477,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { } else |outer_err| switch (outer_err) { error.FileNotFound => { const sub_dirname = fs.path.dirname(sub_path).?; - b.cache_root.handle.makePath(io, sub_dirname) catch |e| + b.cache_root.handle.createDirPath(io, sub_dirname) catch |e| return step.fail("unable to make path '{f}{s}': {t}", .{ b.cache_root, sub_dirname, e }); const rand_int = std.crypto.random.int(u64); @@ -486,7 +486,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { basename; const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?; - b.cache_root.handle.makePath(io, tmp_sub_path_dirname) catch |err| { + b.cache_root.handle.createDirPath(io, tmp_sub_path_dirname) catch |err| { return step.fail("unable to make temporary directory '{f}{s}': {t}", .{ b.cache_root, tmp_sub_path_dirname, err, }); diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 157a0292e7..c0ba7f0cee 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -975,7 +975,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .output_directory => output_sub_path, else => unreachable, }; - b.cache_root.handle.makePath(io, output_sub_dir_path) catch |err| { + b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, output_sub_dir_path, @errorName(err), }); @@ -1007,7 +1007,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { .output_directory => output_sub_path, else => unreachable, }; - b.cache_root.handle.makePath(io, output_sub_dir_path) catch |err| { + b.cache_root.handle.createDirPath(io, output_sub_dir_path) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, output_sub_dir_path, @errorName(err), }); @@ -1439,7 +1439,7 @@ fn runCommand( const sub_path = b.pathJoin(&output_components); const sub_path_dirname = Dir.path.dirname(sub_path).?; - b.cache_root.handle.makePath(io, sub_path_dirname) catch |err| { + b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {s}", .{ b.cache_root, sub_path_dirname, @errorName(err), }); diff --git a/lib/std/Build/Step/UpdateSourceFiles.zig b/lib/std/Build/Step/UpdateSourceFiles.zig index eb8a6a85dd..1c4c94f9cf 100644 --- a/lib/std/Build/Step/UpdateSourceFiles.zig +++ b/lib/std/Build/Step/UpdateSourceFiles.zig @@ -78,7 +78,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { var any_miss = false; for (usf.output_source_files.items) |output_source_file| { if (fs.path.dirname(output_source_file.sub_path)) |dirname| { - b.build_root.handle.makePath(io, dirname) catch |err| { + b.build_root.handle.createDirPath(io, dirname) catch |err| { return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err }); }; } diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 53222289e6..145c7f9bb3 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -259,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); - var cache_dir = b.cache_root.handle.makeOpenPath(io, cache_path, .{}) catch |err| + var cache_dir = b.cache_root.handle.createDirPathOpen(io, cache_path, .{}) catch |err| return step.fail("unable to make path '{f}{s}': {t}", .{ b.cache_root, cache_path, err }); defer cache_dir.close(io); for (write_file.files.items) |file| { if (fs.path.dirname(file.sub_path)) |dirname| { - cache_dir.makePath(io, dirname) catch |err| { + cache_dir.createDirPath(io, dirname) catch |err| { return step.fail("unable to make path '{f}{s}{c}{s}': {t}", .{ b.cache_root, cache_path, fs.path.sep, dirname, err, }); @@ -300,7 +300,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const dest_dirname = dir.sub_path; if (dest_dirname.len != 0) { - cache_dir.makePath(io, dest_dirname) catch |err| { + cache_dir.createDirPath(io, dest_dirname) catch |err| { return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{ b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err), }); @@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const src_entry_path = try src_dir_path.join(arena, entry.path); const dest_path = b.pathJoin(&.{ dest_dirname, entry.path }); switch (entry.kind) { - .directory => try cache_dir.makePath(io, dest_path), + .directory => try cache_dir.createDirPath(io, dest_path), .file => { const prev_status = Io.Dir.updateFile( src_entry_path.root_dir.handle, diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 1d477d330e..ad26893651 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -659,9 +659,9 @@ pub const VTable = struct { futexWaitUncancelable: *const fn (?*anyopaque, ptr: *const u32, expected: u32) void, futexWake: *const fn (?*anyopaque, ptr: *const u32, max_waiters: u32) void, - dirMake: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.MakeError!void, - dirMakePath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.MakePathError!Dir.MakePathStatus, - dirMakeOpenPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions, Dir.OpenOptions) Dir.MakeOpenPathError!Dir, + dirCreateDir: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirError!void, + dirCreateDirPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions) Dir.CreateDirPathError!Dir.CreatePathStatus, + dirCreateDirPathOpen: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions, Dir.OpenOptions) Dir.CreateDirPathOpenError!Dir, dirOpenDir: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.OpenError!Dir, dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, dirStatFile: *const fn (?*anyopaque, Dir, []const u8, Dir.StatFileOptions) Dir.StatFileError!File.Stat, diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 78637015ba..54cce082da 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -590,7 +590,7 @@ pub fn updateFile( } if (path.dirname(dest_path)) |dirname| { - try dest_dir.makePath(io, dirname); + try dest_dir.createDirPath(io, dirname); } var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. @@ -637,7 +637,7 @@ pub fn readFile(dir: Dir, io: Io, file_path: []const u8, buffer: []u8) ReadFileE return buffer[0..n]; } -pub const MakeError = error{ +pub const CreateDirError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to create a new directory relative to it. AccessDenied, @@ -663,10 +663,10 @@ pub const MakeError = error{ /// * On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. /// /// Related: -/// * `makePath` +/// * `createDirPath` /// * `createDirAbsolute` -pub fn createDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) MakeError!void { - return io.vtable.dirMake(io.userdata, dir, sub_path, permissions); +pub fn createDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) CreateDirError!void { + return io.vtable.dirCreateDir(io.userdata, dir, sub_path, permissions); } /// Create a new directory, based on an absolute path. @@ -677,14 +677,14 @@ pub fn createDir(dir: Dir, io: Io, sub_path: []const u8, permissions: Permission /// 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 createDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissions) MakeError!void { +pub fn createDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissions) CreateDirError!void { assert(path.isAbsolute(absolute_path)); return createDir(.cwd(), io, absolute_path, permissions); } test createDirAbsolute {} -pub const MakePathError = MakeError || StatFileError; +pub const CreateDirPathError = CreateDirError || StatFileError; /// Creates parent directories with default permissions as necessary to ensure /// `sub_path` exists as a directory. @@ -710,27 +710,27 @@ pub const MakePathError = MakeError || StatFileError; /// and a `./second` directory. /// /// See also: -/// * `makePathStatus` -pub fn makePath(dir: Dir, io: Io, sub_path: []const u8) MakePathError!void { - _ = try io.vtable.dirMakePath(io.userdata, dir, sub_path, .default_dir); +/// * `createDirPathStatus` +pub fn createDirPath(dir: Dir, io: Io, sub_path: []const u8) CreateDirPathError!void { + _ = try io.vtable.dirCreateDirPath(io.userdata, dir, sub_path, .default_dir); } -pub const MakePathStatus = enum { existed, created }; +pub const CreatePathStatus = enum { existed, created }; -/// Same as `makePath` except returns whether the path already existed or was +/// Same as `createDirPath` except returns whether the path already existed or was /// successfully created. -pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) MakePathError!MakePathStatus { - return io.vtable.dirMakePath(io.userdata, dir, sub_path, permissions); +pub fn createDirPathStatus(dir: Dir, io: Io, sub_path: []const u8, permissions: Permissions) CreateDirPathError!CreatePathStatus { + return io.vtable.dirCreateDirPath(io.userdata, dir, sub_path, permissions); } -pub const MakeOpenPathError = MakeError || OpenError || StatFileError; +pub const CreateDirPathOpenError = CreateDirError || OpenError || StatFileError; -pub const MakeOpenPathOptions = struct { +pub const CreateDirPathOpenOptions = struct { open_options: OpenOptions = .{}, permissions: Permissions = .default_dir, }; -/// Performs the equivalent of `makePath` followed by `openDir`, atomically if possible. +/// Performs the equivalent of `createDirPath` followed by `openDir`, atomically if possible. /// /// When this operation is canceled, it may leave the file system in a /// partially modified state. @@ -738,8 +738,8 @@ pub const MakeOpenPathOptions = 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. /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn makeOpenPath(dir: Dir, io: Io, sub_path: []const u8, options: MakeOpenPathOptions) MakeOpenPathError!Dir { - return io.vtable.dirMakeOpenPath(io.userdata, dir, sub_path, options.permissions, options.open_options); +pub fn createDirPathOpen(dir: Dir, io: Io, sub_path: []const u8, options: CreateDirPathOpenOptions) CreateDirPathOpenError!Dir { + return io.vtable.dirCreateDirPathOpen(io.userdata, dir, sub_path, options.permissions, options.open_options); } pub const Stat = File.Stat; @@ -1729,7 +1729,7 @@ pub const AtomicFileOptions = struct { pub fn atomicFile(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFileOptions) !File.Atomic { if (path.dirname(dest_path)) |dirname| { const dir = if (options.make_path) - try parent.makeOpenPath(io, dirname, .{}) + try parent.createDirPathOpen(io, dirname, .{}) else try parent.openDir(io, dirname, .{}); diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig index 9f9403d5ad..26b8298cab 100644 --- a/lib/std/Io/Kqueue.zig +++ b/lib/std/Io/Kqueue.zig @@ -869,9 +869,9 @@ pub fn io(k: *Kqueue) Io { .conditionWaitUncancelable = conditionWaitUncancelable, .conditionWake = conditionWake, - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, .dirStat = dirStat, .dirStatFile = dirStatFile, @@ -1114,7 +1114,7 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. k.yield(waiting_fiber, .reschedule); } -fn dirMake(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { +fn dirCreateDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.CreateDirError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; @@ -1122,7 +1122,7 @@ fn dirMake(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode _ = mode; @panic("TODO"); } -fn dirMakePath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void { +fn dirCreateDirPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.CreateDirError!void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; @@ -1130,7 +1130,7 @@ fn dirMakePath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir. _ = mode; @panic("TODO"); } -fn dirMakeOpenPath(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.MakeOpenPathError!Dir { +fn dirCreateDirPathOpen(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Dir.OpenOptions) Dir.CreateDirPathOpenError!Dir { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; _ = dir; diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index f4d60b3934..4afd8d75d1 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -711,9 +711,9 @@ pub fn io(t: *Threaded) Io { .futexWaitUncancelable = futexWaitUncancelable, .futexWake = futexWake, - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, .dirStat = dirStat, .dirStatFile = dirStatFile, .dirAccess = dirAccess, @@ -846,9 +846,9 @@ pub fn ioBasic(t: *Threaded) Io { .futexWaitUncancelable = futexWaitUncancelable, .futexWake = futexWake, - .dirMake = dirMake, - .dirMakePath = dirMakePath, - .dirMakeOpenPath = dirMakeOpenPath, + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, .dirStat = dirStat, .dirStatFile = dirStatFile, .dirAccess = dirAccess, @@ -1507,13 +1507,13 @@ fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void { } } -const dirMake = switch (native_os) { - .windows => dirMakeWindows, - .wasi => dirMakeWasi, - else => dirMakePosix, +const dirCreateDir = switch (native_os) { + .windows => dirCreateDirWindows, + .wasi => dirCreateDirWasi, + else => dirCreateDirPosix, }; -fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void { +fn dirCreateDirPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); @@ -1559,8 +1559,8 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissio } } -fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void { - if (builtin.link_libc) return dirMakePosix(userdata, dir, sub_path, permissions); +fn dirCreateDirWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { + if (builtin.link_libc) return dirCreateDirPosix(userdata, dir, sub_path, permissions); const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); try current_thread.beginSyscall(); @@ -1601,7 +1601,7 @@ fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permission } } -fn dirMakeWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void { +fn dirCreateDirWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.CreateDirError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); try current_thread.checkCancel(); @@ -1627,19 +1627,19 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permiss windows.CloseHandle(sub_dir_handle); } -fn dirMakePath( +fn dirCreateDirPath( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions, -) Dir.MakePathError!Dir.MakePathStatus { +) Dir.CreateDirPathError!Dir.CreatePathStatus { const t: *Threaded = @ptrCast(@alignCast(userdata)); var it = std.fs.path.componentIterator(sub_path); - var status: Dir.MakePathStatus = .existed; + var status: Dir.CreatePathStatus = .existed; var component = it.last() orelse return error.BadPathName; while (true) { - if (dirMake(t, dir, component.path, permissions)) |_| { + if (dirCreateDir(t, dir, component.path, permissions)) |_| { status = .created; } else |err| switch (err) { error.PathAlreadyExists => { @@ -1659,37 +1659,37 @@ fn dirMakePath( } } -const dirMakeOpenPath = switch (native_os) { - .windows => dirMakeOpenPathWindows, - .wasi => dirMakeOpenPathWasi, - else => dirMakeOpenPathPosix, +const dirCreateDirPathOpen = switch (native_os) { + .windows => dirCreateDirPathOpenWindows, + .wasi => dirCreateDirPathOpenWasi, + else => dirCreateDirPathOpenPosix, }; -fn dirMakeOpenPathPosix( +fn dirCreateDirPathOpenPosix( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions, options: Dir.OpenOptions, -) Dir.MakeOpenPathError!Dir { +) Dir.CreateDirPathOpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const t_io = ioBasic(t); return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { error.FileNotFound => { - _ = try dir.makePathStatus(t_io, sub_path, permissions); + _ = try dir.createDirPathStatus(t_io, sub_path, permissions); return dirOpenDirPosix(t, dir, sub_path, options); }, else => |e| return e, }; } -fn dirMakeOpenPathWindows( +fn dirCreateDirPathOpenWindows( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions, options: Dir.OpenOptions, -) Dir.MakeOpenPathError!Dir { +) Dir.CreateDirPathOpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); const w = windows; @@ -1795,18 +1795,18 @@ fn dirMakeOpenPathWindows( } } -fn dirMakeOpenPathWasi( +fn dirCreateDirPathOpenWasi( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions, options: Dir.OpenOptions, -) Dir.MakeOpenPathError!Dir { +) Dir.CreateDirPathOpenError!Dir { const t: *Threaded = @ptrCast(@alignCast(userdata)); const t_io = ioBasic(t); return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { error.FileNotFound => { - _ = try dir.makePathStatus(t_io, sub_path, permissions); + _ = try dir.createDirPathStatus(t_io, sub_path, permissions); return dirOpenDirWasi(t, dir, sub_path, options); }, else => |e| return e, @@ -3352,11 +3352,6 @@ pub fn dirOpenDirWindows( } } -const MakeOpenDirAccessMaskWOptions = struct { - no_follow: bool, - create_disposition: u32, -}; - fn dirClose(userdata: ?*anyopaque, dirs: []const Dir) void { const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 644a6fc52d..bcb9048e0e 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -226,7 +226,7 @@ test "Dir.readLink" { // test 3: relative path symlink const parent_file = ".." ++ Dir.path.sep_str ++ "target.txt"; const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); - var subdir = try ctx.dir.makeOpenPath(io, "subdir", .{}); + var subdir = try ctx.dir.createDirPathOpen(io, "subdir", .{}); defer subdir.close(io); try setupSymlink(io, subdir, canonical_parent_file, "relative-link.txt", .{}); try testReadLink(io, subdir, canonical_parent_file, "relative-link.txt"); @@ -411,7 +411,7 @@ test "openDir non-cwd parent '..'" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - var subdir = try tmp.dir.makeOpenPath(io, "subdir", .{}); + var subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{}); defer subdir.close(io); var dir = try subdir.openDir(io, "..", .{}); @@ -613,13 +613,13 @@ test "Dir.Iterator but dir is deleted during iteration" { defer tmp.cleanup(); // Create directory and setup an iterator for it - var subdir = try tmp.dir.makeOpenPath(io, "subdir", .{ .open_options = .{ .iterate = true } }); + var subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{ .open_options = .{ .iterate = true } }); defer subdir.close(io); var iterator = subdir.iterate(); // Create something to iterate over within the subdir - try tmp.dir.makePath(io, "subdir" ++ Dir.path.sep_str ++ "b"); + try tmp.dir.createDirPath(io, "subdir" ++ Dir.path.sep_str ++ "b"); // Then, before iterating, delete the directory that we're iterating. // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. @@ -862,13 +862,13 @@ test "file operations on directories" { }.impl); } -test "makeOpenPath parent dirs do not exist" { +test "createDirPathOpen parent dirs do not exist" { const io = testing.io; var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); - var dir = try tmp_dir.dir.makeOpenPath(io, "root_dir/parent_dir/some_dir", .{}); + var dir = try tmp_dir.dir.createDirPathOpen(io, "root_dir/parent_dir/some_dir", .{}); dir.close(io); // double check that the full directory structure was created @@ -1016,7 +1016,7 @@ test "Dir.rename directory onto non-empty dir" { try ctx.dir.createDir(io, test_dir_path, .default_dir); - var target_dir = try ctx.dir.makeOpenPath(io, target_dir_path, .{}); + var target_dir = try ctx.dir.createDirPathOpen(io, target_dir_path, .{}); var file = try target_dir.createFile(io, "test_file", .{ .read = true }); file.close(io); target_dir.close(io); @@ -1155,9 +1155,9 @@ test "deleteTree does not follow symlinks" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath(io, "b"); + try tmp.dir.createDirPath(io, "b"); { - var a = try tmp.dir.makeOpenPath(io, "a", .{}); + var a = try tmp.dir.createDirPathOpen(io, "a", .{}); defer a.close(io); try setupSymlink(io, a, "../b", "b", .{ .is_directory = true }); @@ -1184,7 +1184,7 @@ test "deleteTree on a symlink" { try tmp.dir.access(io, "file", .{}); // Symlink to a directory - try tmp.dir.makePath(io, "dir"); + try tmp.dir.createDirPath(io, "dir"); try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); try tmp.dir.deleteTree(io, "dirlink"); @@ -1192,14 +1192,14 @@ test "deleteTree on a symlink" { try tmp.dir.access(io, "dir", .{}); } -test "makePath, put some files in it, deleteTree" { +test "createDirPath, put some files in it, deleteTree" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const io = ctx.io; const allocator = ctx.arena.allocator(); const dir_path = try ctx.transformPath("os_test_tmp"); - try ctx.dir.makePath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); + try ctx.dir.createDirPath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); try ctx.dir.writeFile(io, .{ .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), .data = "nonsense", @@ -1215,14 +1215,14 @@ test "makePath, put some files in it, deleteTree" { }.impl); } -test "makePath, put some files in it, deleteTreeMinStackSize" { +test "createDirPath, put some files in it, deleteTreeMinStackSize" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const io = ctx.io; const allocator = ctx.arena.allocator(); const dir_path = try ctx.transformPath("os_test_tmp"); - try ctx.dir.makePath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); + try ctx.dir.createDirPath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); try ctx.dir.writeFile(io, .{ .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), .data = "nonsense", @@ -1238,7 +1238,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { }.impl); } -test "makePath in a directory that no longer exists" { +test "createDirPath in a directory that no longer exists" { if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir const io = testing.io; @@ -1247,10 +1247,10 @@ test "makePath in a directory that no longer exists" { defer tmp.cleanup(); try tmp.parent_dir.deleteTree(io, &tmp.sub_path); - try expectError(error.FileNotFound, tmp.dir.makePath(io, "sub-path")); + try expectError(error.FileNotFound, tmp.dir.createDirPath(io, "sub-path")); } -test "makePath but sub_path contains pre-existing file" { +test "createDirPath but sub_path contains pre-existing file" { const io = testing.io; var tmp = tmpDir(.{}); @@ -1259,7 +1259,7 @@ test "makePath but sub_path contains pre-existing file" { try tmp.dir.createDir(io, "foo", .default_dir); try tmp.dir.writeFile(io, .{ .sub_path = "foo/bar", .data = "" }); - try expectError(error.NotDir, tmp.dir.makePath(io, "foo/bar/baz")); + try expectError(error.NotDir, tmp.dir.createDirPath(io, "foo/bar/baz")); } fn expectDir(io: Io, dir: Dir, path: []const u8) !void { @@ -1279,7 +1279,7 @@ test "makepath existing directories" { try tmpA.createDir(io, "B", .default_dir); const testPath = "A" ++ Dir.path.sep_str ++ "B" ++ Dir.path.sep_str ++ "C"; - try tmp.dir.makePath(io, testPath); + try tmp.dir.createDirPath(io, testPath); try expectDir(io, tmp.dir, testPath); } @@ -1293,7 +1293,7 @@ test "makepath through existing valid symlink" { try tmp.dir.createDir(io, "realfolder", .default_dir); try setupSymlink(io, tmp.dir, "." ++ Dir.path.sep_str ++ "realfolder", "working-symlink", .{}); - try tmp.dir.makePath(io, "working-symlink" ++ Dir.path.sep_str ++ "in-realfolder"); + try tmp.dir.createDirPath(io, "working-symlink" ++ Dir.path.sep_str ++ "in-realfolder"); try expectDir(io, tmp.dir, "realfolder" ++ Dir.path.sep_str ++ "in-realfolder"); } @@ -1309,7 +1309,7 @@ test "makepath relative walks" { }); defer testing.allocator.free(relPath); - try tmp.dir.makePath(io, relPath); + try tmp.dir.createDirPath(io, relPath); // How .. is handled is different on Windows than non-Windows switch (native_os) { @@ -1348,7 +1348,7 @@ test "makepath ignores '.'" { }); defer testing.allocator.free(expectedPath); - try tmp.dir.makePath(io, dotPath); + try tmp.dir.createDirPath(io, dotPath); try expectDir(io, tmp.dir, expectedPath); } @@ -1358,7 +1358,7 @@ fn testFilenameLimits(io: Io, iterable_dir: Dir, maxed_filename: []const u8, max { try iterable_dir.writeFile(io, .{ .sub_path = maxed_filename, .data = "" }); - var maxed_dir = try iterable_dir.makeOpenPath(io, maxed_dirname, .{}); + var maxed_dir = try iterable_dir.createDirPathOpen(io, maxed_dirname, .{}); defer maxed_dir.close(io); try maxed_dir.writeFile(io, .{ .sub_path = maxed_filename, .data = "" }); @@ -1511,7 +1511,7 @@ test "access file" { const dir_path = try ctx.transformPath("os_test_tmp"); const file_path = try ctx.transformPath("os_test_tmp" ++ Dir.path.sep_str ++ "file.txt"); - try ctx.dir.makePath(io, dir_path); + try ctx.dir.createDirPath(io, dir_path); try expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "" }); @@ -1527,7 +1527,7 @@ test "sendfile" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath(io, "os_test_tmp"); + try tmp.dir.createDirPath(io, "os_test_tmp"); var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); defer dir.close(io); @@ -1574,7 +1574,7 @@ test "sendfile with buffered data" { var tmp = tmpDir(.{}); defer tmp.cleanup(); - try tmp.dir.makePath(io, "os_test_tmp"); + try tmp.dir.createDirPath(io, "os_test_tmp"); var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); defer dir.close(io); @@ -1851,7 +1851,7 @@ test "walker" { }); for (expected_paths.keys()) |key| { - try tmp.dir.makePath(io, key); + try tmp.dir.createDirPath(io, key); } var walker = try tmp.dir.walk(testing.allocator); @@ -1913,7 +1913,7 @@ test "selective walker, skip entries that start with ." { }); for (paths_to_create) |path| { - try tmp.dir.makePath(io, path); + try tmp.dir.createDirPath(io, path); } var walker = try tmp.dir.walkSelectively(testing.allocator); @@ -1959,8 +1959,8 @@ test "walker without fully iterating" { // Create 2 directories inside the tmp directory, but then only iterate once before breaking. // This ensures that walker doesn't try to close the initial directory when not fully iterating. - try tmp.dir.makePath(io, "a"); - try tmp.dir.makePath(io, "b"); + try tmp.dir.createDirPath(io, "a"); + try tmp.dir.createDirPath(io, "b"); var num_walked: usize = 0; while (try walker.next(io)) |_| { @@ -2109,8 +2109,8 @@ test "invalid UTF-8/WTF-8 paths" { try expectError(expected_err, ctx.dir.createDir(io, invalid_path, .default_dir)); - try expectError(expected_err, ctx.dir.makePath(io, invalid_path)); - try expectError(expected_err, ctx.dir.makeOpenPath(io, invalid_path, .{})); + try expectError(expected_err, ctx.dir.createDirPath(io, invalid_path)); + try expectError(expected_err, ctx.dir.createDirPathOpen(io, invalid_path, .{})); try expectError(expected_err, ctx.dir.openDir(io, invalid_path, .{})); @@ -2574,7 +2574,7 @@ test "hard link with different directories" { const target_name = "link-target"; const link_name = "newlink"; - const subdir = try tmp.dir.makeOpenPath(io, "subdir", .{}); + const subdir = try tmp.dir.createDirPathOpen(io, "subdir", .{}); defer tmp.dir.deleteFile(io, target_name) catch {}; try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 3997bc70cd..133dfc0293 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -1079,7 +1079,7 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDir } } -pub const MakeDirError = std.Io.Dir.MakeError; +pub const MakeDirError = std.Io.Dir.CreateDirError; /// Create a directory. /// `mode` is ignored on Windows and WASI. diff --git a/lib/std/tar.zig b/lib/std/tar.zig index d45aa99443..024a425919 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -606,7 +606,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp switch (file.kind) { .directory => { if (file_name.len > 0 and !options.exclude_empty_directories) { - try dir.makePath(io, file_name); + try dir.createDirPath(io, file_name); } }, .file => { @@ -642,7 +642,7 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, permissions: Io. const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { - try dir.makePath(io, dir_name); + try dir.createDirPath(io, dir_name); return try dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }); } } @@ -656,7 +656,7 @@ fn createDirAndSymlink(io: Io, dir: Io.Dir, link_name: []const u8, file_name: [] dir.symLink(io, link_name, file_name, .{}) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { - try dir.makePath(io, dir_name); + try dir.createDirPath(io, dir_name); return try dir.symLink(io, link_name, file_name, .{}); } } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index f3dd114af3..5b5ec852e9 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -635,12 +635,12 @@ pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); const cwd = Io.Dir.cwd(); - var cache_dir = cwd.makeOpenPath(io, ".zig-cache", .{}) catch + var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); defer cache_dir.close(io); - const parent_dir = cache_dir.makeOpenPath(io, "tmp", .{}) catch + const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.makeOpenPath(io, &sub_path, .{ .open_options = opts }) catch + const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); return .{ diff --git a/lib/std/zip.zig b/lib/std/zip.zig index 770bfd8ae7..ff95587e7a 100644 --- a/lib/std/zip.zig +++ b/lib/std/zip.zig @@ -554,13 +554,13 @@ pub const Iterator = struct { if (filename[filename.len - 1] == '/') { if (self.uncompressed_size != 0) return error.ZipBadDirectorySize; - try dest.makePath(io, filename[0 .. filename.len - 1]); + try dest.createDirPath(io, filename[0 .. filename.len - 1]); return; } const out_file = blk: { if (std.fs.path.dirname(filename)) |dirname| { - var parent_dir = try dest.makeOpenPath(io, dirname, .{}); + var parent_dir = try dest.createDirPathOpen(io, dirname, .{}); defer parent_dir.close(io); const basename = std.fs.path.basename(filename); diff --git a/src/Compilation.zig b/src/Compilation.zig index dc254a36c5..8b840b8d45 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -832,7 +832,7 @@ pub const Directories = struct { const nonempty_path = if (path.len == 0) "." else path; const handle_or_err = switch (thing) { .@"zig lib" => Io.Dir.cwd().openDir(io, nonempty_path, .{}), - .@"global cache", .@"local cache" => Io.Dir.cwd().makeOpenPath(io, nonempty_path, .{}), + .@"global cache", .@"local cache" => Io.Dir.cwd().createDirPathOpen(io, nonempty_path, .{}), }; return .{ .path = if (path.len == 0) null else path, @@ -1879,7 +1879,7 @@ pub const CreateDiagnostic = union(enum) { pub const CreateCachePath = struct { which: enum { local, global }, sub: []const u8, - err: (Io.Dir.MakeError || Io.Dir.OpenError || Io.Dir.StatFileError), + err: (Io.Dir.CreateDirError || Io.Dir.OpenError || Io.Dir.StatFileError), }; pub fn format(diag: CreateDiagnostic, w: *Writer) Writer.Error!void { switch (diag) { @@ -2120,7 +2120,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, cache.* = .{ .gpa = gpa, .io = io, - .manifest_dir = options.dirs.local_cache.handle.makeOpenPath(io, "h", .{}) catch |err| { + .manifest_dir = options.dirs.local_cache.handle.createDirPathOpen(io, "h", .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = "h", .err = err } }); }, }; @@ -2170,7 +2170,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, // to redundantly happen for each AstGen operation. const zir_sub_dir = "z"; - var local_zir_dir = options.dirs.local_cache.handle.makeOpenPath(io, zir_sub_dir, .{}) catch |err| { + var local_zir_dir = options.dirs.local_cache.handle.createDirPathOpen(io, zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = zir_sub_dir, .err = err } }); }; errdefer local_zir_dir.close(io); @@ -2178,7 +2178,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .handle = local_zir_dir, .path = try options.dirs.local_cache.join(arena, &.{zir_sub_dir}), }; - var global_zir_dir = options.dirs.global_cache.handle.makeOpenPath(io, zir_sub_dir, .{}) catch |err| { + var global_zir_dir = options.dirs.global_cache.handle.createDirPathOpen(io, zir_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .global, .sub = zir_sub_dir, .err = err } }); }; errdefer global_zir_dir.close(io); @@ -2449,7 +2449,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, const digest = hash.final(); const artifact_sub_dir = "o" ++ fs.path.sep_str ++ digest; - var artifact_dir = options.dirs.local_cache.handle.makeOpenPath(io, artifact_sub_dir, .{}) catch |err| { + var artifact_dir = options.dirs.local_cache.handle.createDirPathOpen(io, artifact_sub_dir, .{}) catch |err| { return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = artifact_sub_dir, .err = err } }); }; errdefer artifact_dir.close(io); @@ -2917,7 +2917,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE tmp_dir_rand_int = std.crypto.random.int(u64); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); - const handle = comp.dirs.local_cache.handle.makeOpenPath(io, tmp_dir_sub_path, .{}) catch |err| { + const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err }); }; break :d .{ .path = path, .handle = handle }; @@ -2998,7 +2998,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE tmp_dir_rand_int = std.crypto.random.int(u64); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); - const handle = comp.dirs.local_cache.handle.makeOpenPath(io, tmp_dir_sub_path, .{}) catch |err| { + const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err }); }; break :d .{ .path = path, .handle = handle }; @@ -3437,7 +3437,7 @@ fn renameTmpIntoCache( continue; }, error.FileNotFound => { - try cache_directory.handle.makePath(io, "o"); + try cache_directory.handle.createDirPath(io, "o"); continue; }, else => |e| return e, @@ -5276,7 +5276,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { const io = comp.io; const docs_path = comp.resolveEmitPath(comp.emit_docs.?); - var out_dir = docs_path.root_dir.handle.makeOpenPath(io, docs_path.sub_path, .{}) catch |err| { + var out_dir = docs_path.root_dir.handle.createDirPathOpen(io, docs_path.sub_path, .{}) catch |err| { return comp.lockAndSetMiscFailure( .docs_copy, "unable to create output directory '{f}': {s}", @@ -5513,7 +5513,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU assert(docs_bin_file.sub_path.len > 0); // emitted binary is not a directory const docs_path = comp.resolveEmitPath(comp.emit_docs.?); - var out_dir = docs_path.root_dir.handle.makeOpenPath(io, docs_path.sub_path, .{}) catch |err| { + var out_dir = docs_path.root_dir.handle.createDirPathOpen(io, docs_path.sub_path, .{}) catch |err| { comp.lockAndSetMiscFailure( .docs_copy, "unable to create output directory '{f}': {t}", @@ -5705,7 +5705,7 @@ pub fn translateC( const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; const cache_dir = comp.dirs.local_cache.handle; - var cache_tmp_dir = try cache_dir.makeOpenPath(io, tmp_sub_path, .{}); + var cache_tmp_dir = try cache_dir.createDirPathOpen(io, tmp_sub_path, .{}); defer cache_tmp_dir.close(io); const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); @@ -6280,7 +6280,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr // We can't know the digest until we do the C compiler invocation, // so we need a temporary filename. const out_obj_path = try comp.tmpFilePath(arena, o_basename); - var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(io, "tmp", .{}); + var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{}); defer zig_cache_tmp_dir.close(io); const out_diag_path = if (comp.clang_passthrough_mode or !ext.clangSupportsDiagnostics()) @@ -6445,7 +6445,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr // Rename into place. const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(io, o_sub_path, .{}); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); defer o_dir.close(io); const tmp_basename = fs.path.basename(out_obj_path); try Io.Dir.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename, io); @@ -6534,7 +6534,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const digest = man.final(); const o_sub_path = try fs.path.join(arena, &.{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(io, o_sub_path, .{}); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); defer o_dir.close(io); const in_rc_path = try comp.dirs.local_cache.join(comp.gpa, &.{ @@ -6622,7 +6622,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len]; const digest = if (try man.hit()) man.final() else blk: { - var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(io, "tmp", .{}); + var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, "tmp", .{}); defer zig_cache_tmp_dir.close(io); const res_filename = try std.fmt.allocPrint(arena, "{s}.res", .{rc_basename_noext}); @@ -6693,7 +6693,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // Rename into place. const digest = man.final(); const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(io, o_sub_path, .{}); + var o_dir = try comp.dirs.local_cache.handle.createDirPathOpen(io, o_sub_path, .{}); defer o_dir.close(io); const tmp_basename = fs.path.basename(out_res_path); try Io.Dir.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename, io); diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 45fcd66b8c..8a11736e42 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -500,7 +500,7 @@ fn runResource( var tmp_directory: Cache.Directory = .{ .path = tmp_directory_path, .handle = handle: { - const dir = cache_root.handle.makeOpenPath(io, tmp_dir_sub_path, .{ + const dir = cache_root.handle.createDirPathOpen(io, tmp_dir_sub_path, .{ .open_options = .{ .iterate = true }, }) catch |err| { try eb.addRootErrorMessage(.{ @@ -524,7 +524,7 @@ fn runResource( if (native_os == .linux and f.job_queue.work_around_btrfs_bug) { // https://github.com/ziglang/zig/issues/17095 pkg_path.root_dir.handle.close(io); - pkg_path.root_dir.handle = cache_root.handle.makeOpenPath(io, tmp_dir_sub_path, .{ + pkg_path.root_dir.handle = cache_root.handle.createDirPathOpen(io, tmp_dir_sub_path, .{ .open_options = .{ .iterate = true }, }) catch @panic("btrfs workaround failed"); } @@ -1366,7 +1366,7 @@ fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!U // we do not attempt to replicate the exact structure of a real .git // directory, since that isn't relevant for fetching a package. { - var pack_dir = try out_dir.makeOpenPath(io, ".git", .{}); + var pack_dir = try out_dir.createDirPathOpen(io, ".git", .{}); defer pack_dir.close(io); var pack_file = try pack_dir.createFile(io, "pkg.pack", .{ .read = true }); defer pack_file.close(io); @@ -1427,7 +1427,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void .file => { dir.copyFile(entry.path, tmp_dir, entry.path, io, .{}) catch |err| switch (err) { error.FileNotFound => { - if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(io, dirname); + if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.createDirPath(io, dirname); try dir.copyFile(entry.path, tmp_dir, entry.path, io, .{}); }, else => |e| return e, @@ -1440,7 +1440,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void // the destination directory, fail with an error instead. tmp_dir.symLink(io, link_name, entry.path, .{}) catch |err| switch (err) { error.FileNotFound => { - if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(io, dirname); + if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.createDirPath(io, dirname); try tmp_dir.symLink(io, link_name, entry.path, .{}); }, else => |e| return e, @@ -2250,7 +2250,7 @@ const TestFetchBuilder = struct { cache_parent_dir: std.Io.Dir, path_or_url: []const u8, ) !*Fetch { - const cache_dir = try cache_parent_dir.makeOpenPath(io, "zig-global-cache", .{}); + const cache_dir = try cache_parent_dir.createDirPathOpen(io, "zig-global-cache", .{}); self.http_client = .{ .allocator = allocator, .io = io }; self.global_cache_directory = .{ .handle = cache_dir, .path = null }; diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index eb3d2a447e..f241f768f6 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -1720,10 +1720,10 @@ pub fn main() !void { var pack_file_reader = pack_file.reader(io, &pack_file_buffer); const commit = try Oid.parse(format, args[3]); - var worktree = try Io.Dir.cwd().makeOpenPath(io, args[4], .{}); + var worktree = try Io.Dir.cwd().createDirPathOpen(io, args[4], .{}); defer worktree.close(io); - var git_dir = try worktree.makeOpenPath(io, ".git", .{}); + var git_dir = try worktree.createDirPathOpen(io, ".git", .{}); defer git_dir.close(io); std.debug.print("Starting index...\n", .{}); diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index 44676007e2..ba85f45830 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -444,7 +444,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath(io, "h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), }; cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); @@ -477,7 +477,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(io, o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; defer o_directory.handle.close(io); diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index 8371b3288d..e9b6ce1882 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -679,7 +679,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath(io, "h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), }; cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); @@ -712,7 +712,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(io, o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; defer o_directory.handle.close(io); diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index c4b002f983..03ed917c4f 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -258,7 +258,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath(io, "h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), }; cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); @@ -297,7 +297,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { const digest = man.final(); const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var o_dir = try comp.dirs.global_cache.handle.makeOpenPath(io, o_sub_path, .{}); + var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}); defer o_dir.close(io); const aro = @import("aro"); diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index 9c09c35b0a..9e4213d237 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -385,7 +385,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye var cache: Cache = .{ .gpa = gpa, .io = io, - .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath(io, "h", .{}), + .manifest_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, "h", .{}), }; cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); cache.addPrefix(comp.dirs.zig_lib); @@ -418,7 +418,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); var o_directory: Cache.Directory = .{ - .handle = try comp.dirs.global_cache.handle.makeOpenPath(io, o_sub_path, .{}), + .handle = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{}), .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}), }; defer o_directory.handle.close(io); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 513c857dbf..97493ada32 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3319,7 +3319,7 @@ pub fn reopenDebugInfo(self: *MachO) !void { ); defer gpa.free(d_sym_path); - var d_sym_bundle = try self.base.emit.root_dir.handle.makeOpenPath(io, d_sym_path, .{}); + var d_sym_bundle = try self.base.emit.root_dir.handle.createDirPathOpen(io, d_sym_path, .{}); defer d_sym_bundle.close(io); self.d_sym.?.file = try d_sym_bundle.createFile(io, fs.path.basename(self.base.emit.sub_path), .{ diff --git a/src/main.zig b/src/main.zig index fb2a8cfe0f..507b01ab0e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3381,7 +3381,7 @@ fn buildOutputType( const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ std.crypto.random.int(u64), ext.canonicalName(target), }); - try dirs.local_cache.handle.makePath(io, "tmp"); + try dirs.local_cache.handle.createDirPath(io, "tmp"); // Note that in one of the happy paths, execve() is used to switch to // clang in which case any cleanup logic that exists for this temporary @@ -6955,7 +6955,7 @@ fn cmdFetch( var global_cache_directory: Directory = l: { const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); break :l .{ - .handle = try Io.Dir.cwd().makeOpenPath(io, p, .{}), + .handle = try Io.Dir.cwd().createDirPathOpen(io, p, .{}), .path = p, }; }; @@ -7201,7 +7201,7 @@ fn createDependenciesModule( const rand_int = std.crypto.random.int(u64); const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); { - var tmp_dir = try dirs.local_cache.handle.makeOpenPath(io, tmp_dir_sub_path, .{}); + var tmp_dir = try dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}); defer tmp_dir.close(io); try tmp_dir.writeFile(io, .{ .sub_path = basename, .data = source }); } @@ -7396,7 +7396,7 @@ const Templates = struct { fingerprint: Package.Fingerprint, ) !void { if (fs.path.dirname(template_path)) |dirname| { - out_dir.makePath(io, dirname) catch |err| { + out_dir.createDirPath(io, dirname) catch |err| { fatal("unable to make path '{s}': {t}", .{ dirname, err }); }; } -- cgit v1.2.3