authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-20 12:49:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-21 12:32:37-07:00
logf2a3ac7c0534a74ee544fdf6ef9d2176a8d62389
tree548115489df6c29b38049d8727b5be74806b488f
parent5df52ca0a28d204da0557e88c6c9fe1818bcd6af

std.fs.File: delete writeFileAll and friends

please use File.Writer for these use cases also breaking API changes to std.fs.AtomicFile

10 files changed, 274 insertions(+), 416 deletions(-)

lib/std/Build/Step/Run.zig+14-5
...@@ -169,7 +169,7 @@ pub const Output = struct {...@@ -169,7 +169,7 @@ pub const Output = struct {
169pub fn create(owner: *std.Build, name: []const u8) *Run {169pub fn create(owner: *std.Build, name: []const u8) *Run {
170 const run = owner.allocator.create(Run) catch @panic("OOM");170 const run = owner.allocator.create(Run) catch @panic("OOM");
171 run.* = .{171 run.* = .{
172 .step = Step.init(.{172 .step = .init(.{
173 .id = base_id,173 .id = base_id,
174 .name = name,174 .name = name,
175 .owner = owner,175 .owner = owner,
...@@ -1769,13 +1769,22 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {...@@ -1769,13 +1769,22 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
1769 child.stdin = null;1769 child.stdin = null;
1770 },1770 },
1771 .lazy_path => |lazy_path| {1771 .lazy_path => |lazy_path| {
1772 const path = lazy_path.getPath2(b, &run.step);1772 const path = lazy_path.getPath3(b, &run.step);
1773 const file = b.build_root.handle.openFile(path, .{}) catch |err| {1773 const file = path.root_dir.handle.openFile(path.subPathOrDot(), .{}) catch |err| {
1774 return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)});1774 return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)});
1775 };1775 };
1776 defer file.close();1776 defer file.close();
1777 child.stdin.?.writeFileAll(file, .{}) catch |err| {1777 // TODO https://github.com/ziglang/zig/issues/23955
1778 return run.step.fail("unable to write file to stdin: {s}", .{@errorName(err)});1778 var buffer: [1024]u8 = undefined;
1779 var file_reader = file.reader(&buffer);
1780 var stdin_writer = child.stdin.?.writer(&.{});
1781 _ = stdin_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) {
1782 error.ReadFailed => return run.step.fail("failed to read from {f}: {t}", .{
1783 path, file_reader.err.?,
1784 }),
1785 error.WriteFailed => return run.step.fail("failed to write to stdin: {t}", .{
1786 stdin_writer.err.?,
1787 }),
1779 };1788 };
1780 child.stdin.?.close();1789 child.stdin.?.close();
1781 child.stdin = null;1790 child.stdin = null;
lib/std/fs/AtomicFile.zig+52-46
...@@ -1,6 +1,13 @@...@@ -1,6 +1,13 @@
1file: File,1const AtomicFile = @This();
2// TODO either replace this with rand_buf or use []u16 on Windows2const std = @import("../std.zig");
3tmp_path_buf: [tmp_path_len:0]u8,3const File = std.fs.File;
4const Dir = std.fs.Dir;
5const fs = std.fs;
6const assert = std.debug.assert;
7const posix = std.posix;
8
9file_writer: File.Writer,
10random_integer: u64,
4dest_basename: []const u8,11dest_basename: []const u8,
5file_open: bool,12file_open: bool,
6file_exists: bool,13file_exists: bool,
...@@ -9,35 +16,24 @@ dir: Dir,...@@ -9,35 +16,24 @@ dir: Dir,
916
10pub const InitError = File.OpenError;17pub const InitError = File.OpenError;
1118
12pub const random_bytes_len = 12;
13const tmp_path_len = fs.base64_encoder.calcSize(random_bytes_len);
14
15/// Note that the `Dir.atomicFile` API may be more handy than this lower-level function.19/// Note that the `Dir.atomicFile` API may be more handy than this lower-level function.
16pub fn init(20pub fn init(
17 dest_basename: []const u8,21 dest_basename: []const u8,
18 mode: File.Mode,22 mode: File.Mode,
19 dir: Dir,23 dir: Dir,
20 close_dir_on_deinit: bool,24 close_dir_on_deinit: bool,
25 write_buffer: []u8,
21) InitError!AtomicFile {26) InitError!AtomicFile {
22 var rand_buf: [random_bytes_len]u8 = undefined;
23 var tmp_path_buf: [tmp_path_len:0]u8 = undefined;
24
25 while (true) {27 while (true) {
26 std.crypto.random.bytes(rand_buf[0..]);28 const random_integer = std.crypto.random.int(u64);
27 const tmp_path = fs.base64_encoder.encode(&tmp_path_buf, &rand_buf);29 const tmp_sub_path = std.fmt.hex(random_integer);
28 tmp_path_buf[tmp_path.len] = 0;30 const file = dir.createFile(&tmp_sub_path, .{ .mode = mode, .exclusive = true }) catch |err| switch (err) {
29
30 const file = dir.createFile(
31 tmp_path,
32 .{ .mode = mode, .exclusive = true },
33 ) catch |err| switch (err) {
34 error.PathAlreadyExists => continue,31 error.PathAlreadyExists => continue,
35 else => |e| return e,32 else => |e| return e,
36 };33 };
3734 return .{
38 return AtomicFile{35 .file_writer = file.writer(write_buffer),
39 .file = file,36 .random_integer = random_integer,
40 .tmp_path_buf = tmp_path_buf,
41 .dest_basename = dest_basename,37 .dest_basename = dest_basename,
42 .file_open = true,38 .file_open = true,
43 .file_exists = true,39 .file_exists = true,
...@@ -48,41 +44,51 @@ pub fn init(...@@ -48,41 +44,51 @@ pub fn init(
48}44}
4945
50/// Always call deinit, even after a successful finish().46/// Always call deinit, even after a successful finish().
51pub fn deinit(self: *AtomicFile) void {47pub fn deinit(af: *AtomicFile) void {
52 if (self.file_open) {48 if (af.file_open) {
53 self.file.close();49 af.file_writer.file.close();
54 self.file_open = false;50 af.file_open = false;
55 }51 }
56 if (self.file_exists) {52 if (af.file_exists) {
57 self.dir.deleteFile(&self.tmp_path_buf) catch {};53 const tmp_sub_path = std.fmt.hex(af.random_integer);
58 self.file_exists = false;54 af.dir.deleteFile(&tmp_sub_path) catch {};
55 af.file_exists = false;
59 }56 }
60 if (self.close_dir_on_deinit) {57 if (af.close_dir_on_deinit) {
61 self.dir.close();58 af.dir.close();
62 }59 }
63 self.* = undefined;60 af.* = undefined;
64}61}
6562
66pub const FinishError = posix.RenameError;63pub const FlushError = File.WriteError;
64
65pub fn flush(af: *AtomicFile) FlushError!void {
66 af.file_writer.interface.flush() catch |err| switch (err) {
67 error.WriteFailed => return af.file_writer.err.?,
68 };
69}
70
71pub const RenameIntoPlaceError = posix.RenameError;
6772
68/// On Windows, this function introduces a period of time where some file73/// On Windows, this function introduces a period of time where some file
69/// system operations on the destination file will result in74/// system operations on the destination file will result in
70/// `error.AccessDenied`, including rename operations (such as the one used in75/// `error.AccessDenied`, including rename operations (such as the one used in
71/// this function).76/// this function).
72pub fn finish(self: *AtomicFile) FinishError!void {77pub fn renameIntoPlace(af: *AtomicFile) RenameIntoPlaceError!void {
73 assert(self.file_exists);78 assert(af.file_exists);
74 if (self.file_open) {79 if (af.file_open) {
75 self.file.close();80 af.file_writer.file.close();
76 self.file_open = false;81 af.file_open = false;
77 }82 }
78 try posix.renameat(self.dir.fd, self.tmp_path_buf[0..], self.dir.fd, self.dest_basename);83 const tmp_sub_path = std.fmt.hex(af.random_integer);
79 self.file_exists = false;84 try posix.renameat(af.dir.fd, &tmp_sub_path, af.dir.fd, af.dest_basename);
85 af.file_exists = false;
80}86}
8187
82const AtomicFile = @This();88pub const FinishError = FlushError || RenameIntoPlaceError;
83const std = @import("../std.zig");89
84const File = std.fs.File;90/// Combination of `flush` followed by `renameIntoPlace`.
85const Dir = std.fs.Dir;91pub fn finish(af: *AtomicFile) FinishError!void {
86const fs = std.fs;92 try af.flush();
87const assert = std.debug.assert;93 try af.renameIntoPlace();
88const posix = std.posix;94}
lib/std/fs/Dir.zig+71-109
...@@ -1,3 +1,20 @@...@@ -1,3 +1,20 @@
1const Dir = @This();
2const builtin = @import("builtin");
3const std = @import("../std.zig");
4const File = std.fs.File;
5const AtomicFile = std.fs.AtomicFile;
6const base64_encoder = fs.base64_encoder;
7const posix = std.posix;
8const mem = std.mem;
9const path = fs.path;
10const fs = std.fs;
11const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;
13const linux = std.os.linux;
14const windows = std.os.windows;
15const native_os = builtin.os.tag;
16const have_flock = @TypeOf(posix.system.flock) != void;
17
1fd: Handle,18fd: Handle,
219
3pub const Handle = posix.fd_t;20pub const Handle = posix.fd_t;
...@@ -1862,9 +1879,10 @@ pub fn symLinkW(...@@ -1862,9 +1879,10 @@ pub fn symLinkW(
18621879
1863/// Same as `symLink`, except tries to create the symbolic link until it1880/// Same as `symLink`, except tries to create the symbolic link until it
1864/// succeeds or encounters an error other than `error.PathAlreadyExists`.1881/// succeeds or encounters an error other than `error.PathAlreadyExists`.
1865/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).1882///
1866/// On WASI, both paths should be encoded as valid UTF-8.1883/// * On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
1867/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.1884/// * On WASI, both paths should be encoded as valid UTF-8.
1885/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
1868pub fn atomicSymLink(1886pub fn atomicSymLink(
1869 dir: Dir,1887 dir: Dir,
1870 target_path: []const u8,1888 target_path: []const u8,
...@@ -1880,9 +1898,8 @@ pub fn atomicSymLink(...@@ -1880,9 +1898,8 @@ pub fn atomicSymLink(
18801898
1881 const dirname = path.dirname(sym_link_path) orelse ".";1899 const dirname = path.dirname(sym_link_path) orelse ".";
18821900
1883 var rand_buf: [AtomicFile.random_bytes_len]u8 = undefined;1901 const rand_len = @sizeOf(u64) * 2;
18841902 const temp_path_len = dirname.len + 1 + rand_len;
1885 const temp_path_len = dirname.len + 1 + base64_encoder.calcSize(rand_buf.len);
1886 var temp_path_buf: [fs.max_path_bytes]u8 = undefined;1903 var temp_path_buf: [fs.max_path_bytes]u8 = undefined;
18871904
1888 if (temp_path_len > temp_path_buf.len) return error.NameTooLong;1905 if (temp_path_len > temp_path_buf.len) return error.NameTooLong;
...@@ -1892,8 +1909,8 @@ pub fn atomicSymLink(...@@ -1892,8 +1909,8 @@ pub fn atomicSymLink(
1892 const temp_path = temp_path_buf[0..temp_path_len];1909 const temp_path = temp_path_buf[0..temp_path_len];
18931910
1894 while (true) {1911 while (true) {
1895 crypto.random.bytes(rand_buf[0..]);1912 const random_integer = std.crypto.random.int(u64);
1896 _ = base64_encoder.encode(temp_path[dirname.len + 1 ..], rand_buf[0..]);1913 temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer);
18971914
1898 if (dir.symLink(target_path, temp_path, flags)) {1915 if (dir.symLink(target_path, temp_path, flags)) {
1899 return dir.rename(temp_path, sym_link_path);1916 return dir.rename(temp_path, sym_link_path);
...@@ -2552,25 +2569,42 @@ pub fn updateFile(...@@ -2552,25 +2569,42 @@ pub fn updateFile(
2552 try dest_dir.makePath(dirname);2569 try dest_dir.makePath(dirname);
2553 }2570 }
25542571
2555 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = actual_mode });2572 var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available.
2573 var atomic_file = try dest_dir.atomicFile(dest_path, .{
2574 .mode = actual_mode,
2575 .write_buffer = &buffer,
2576 });
2556 defer atomic_file.deinit();2577 defer atomic_file.deinit();
25572578
2558 try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size });2579 var src_reader: File.Reader = .initSize(src_file, &.{}, src_stat.size);
2559 try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime);2580 const dest_writer = &atomic_file.file_writer.interface;
2581
2582 _ = dest_writer.sendFileAll(&src_reader, .unlimited) catch |err| switch (err) {
2583 error.ReadFailed => return src_reader.err.?,
2584 error.WriteFailed => return atomic_file.file_writer.err.?,
2585 };
2586 try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime);
2560 try atomic_file.finish();2587 try atomic_file.finish();
2561 return PrevStatus.stale;2588 return .stale;
2562}2589}
25632590
2564pub const CopyFileError = File.OpenError || File.StatError ||2591pub const CopyFileError = File.OpenError || File.StatError ||
2565 AtomicFile.InitError || CopyFileRawError || AtomicFile.FinishError;2592 AtomicFile.InitError || AtomicFile.FinishError ||
2593 File.ReadError || File.WriteError;
25662594
2567/// Guaranteed to be atomic.2595/// Atomically creates a new file at `dest_path` within `dest_dir` with the
2568/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,2596/// same contents as `source_path` within `source_dir`, overwriting any already
2569/// there is a possibility of power loss or application termination leaving temporary files present2597/// existing file.
2570/// in the same directory as dest_path.2598///
2571/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).2599/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and
2572/// On WASI, both paths should be encoded as valid UTF-8.2600/// readily available, there is a possibility of power loss or application
2573/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.2601/// termination leaving temporary files present in the same directory as
2602/// dest_path.
2603///
2604/// On Windows, both paths should be encoded as
2605/// [WTF-8](https://simonsapin.github.io/wtf-8/). On WASI, both paths should be
2606/// encoded as valid UTF-8. On other platforms, both paths are an opaque
2607/// sequence of bytes with no particular encoding.
2574pub fn copyFile(2608pub fn copyFile(
2575 source_dir: Dir,2609 source_dir: Dir,
2576 source_path: []const u8,2610 source_path: []const u8,
...@@ -2578,79 +2612,34 @@ pub fn copyFile(...@@ -2578,79 +2612,34 @@ pub fn copyFile(
2578 dest_path: []const u8,2612 dest_path: []const u8,
2579 options: CopyFileOptions,2613 options: CopyFileOptions,
2580) CopyFileError!void {2614) CopyFileError!void {
2581 var in_file = try source_dir.openFile(source_path, .{});2615 var file_reader: File.Reader = .init(try source_dir.openFile(source_path, .{}), &.{});
2582 defer in_file.close();2616 defer file_reader.file.close();
25832617
2584 var size: ?u64 = null;
2585 const mode = options.override_mode orelse blk: {2618 const mode = options.override_mode orelse blk: {
2586 const st = try in_file.stat();2619 const st = try file_reader.file.stat();
2587 size = st.size;2620 file_reader.size = st.size;
2588 break :blk st.mode;2621 break :blk st.mode;
2589 };2622 };
25902623
2591 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = mode });2624 var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available.
2625 var atomic_file = try dest_dir.atomicFile(dest_path, .{
2626 .mode = mode,
2627 .write_buffer = &buffer,
2628 });
2592 defer atomic_file.deinit();2629 defer atomic_file.deinit();
25932630
2594 try copy_file(in_file.handle, atomic_file.file.handle, size);2631 _ = atomic_file.file_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) {
2595 try atomic_file.finish();2632 error.ReadFailed => return file_reader.err.?,
2596}2633 error.WriteFailed => return atomic_file.file_writer.err.?,
25972634 };
2598const CopyFileRawError = error{SystemResources} || posix.CopyFileRangeError || posix.SendFileError;
2599
2600// Transfer all the data between two file descriptors in the most efficient way.
2601// The copy starts at offset 0, the initial offsets are preserved.
2602// No metadata is transferred over.
2603fn copy_file(fd_in: posix.fd_t, fd_out: posix.fd_t, maybe_size: ?u64) CopyFileRawError!void {
2604 if (builtin.target.os.tag.isDarwin()) {
2605 const rc = posix.system.fcopyfile(fd_in, fd_out, null, .{ .DATA = true });
2606 switch (posix.errno(rc)) {
2607 .SUCCESS => return,
2608 .INVAL => unreachable,
2609 .NOMEM => return error.SystemResources,
2610 // The source file is not a directory, symbolic link, or regular file.
2611 // Try with the fallback path before giving up.
2612 .OPNOTSUPP => {},
2613 else => |err| return posix.unexpectedErrno(err),
2614 }
2615 }
2616
2617 if (native_os == .linux) {
2618 // Try copy_file_range first as that works at the FS level and is the
2619 // most efficient method (if available).
2620 var offset: u64 = 0;
2621 cfr_loop: while (true) {
2622 // The kernel checks the u64 value `offset+count` for overflow, use
2623 // a 32 bit value so that the syscall won't return EINVAL except for
2624 // impossibly large files (> 2^64-1 - 2^32-1).
2625 const amt = try posix.copy_file_range(fd_in, offset, fd_out, offset, std.math.maxInt(u32), 0);
2626 // Terminate as soon as we have copied size bytes or no bytes
2627 if (maybe_size) |s| {
2628 if (s == amt) break :cfr_loop;
2629 }
2630 if (amt == 0) break :cfr_loop;
2631 offset += amt;
2632 }
2633 return;
2634 }
26352635
2636 // Sendfile is a zero-copy mechanism iff the OS supports it, otherwise the2636 try atomic_file.finish();
2637 // fallback code will copy the contents chunk by chunk.
2638 const empty_iovec = [0]posix.iovec_const{};
2639 var offset: u64 = 0;
2640 sendfile_loop: while (true) {
2641 const amt = try posix.sendfile(fd_out, fd_in, offset, 0, &empty_iovec, &empty_iovec, 0);
2642 // Terminate as soon as we have copied size bytes or no bytes
2643 if (maybe_size) |s| {
2644 if (s == amt) break :sendfile_loop;
2645 }
2646 if (amt == 0) break :sendfile_loop;
2647 offset += amt;
2648 }
2649}2637}
26502638
2651pub const AtomicFileOptions = struct {2639pub const AtomicFileOptions = struct {
2652 mode: File.Mode = File.default_mode,2640 mode: File.Mode = File.default_mode,
2653 make_path: bool = false,2641 make_path: bool = false,
2642 write_buffer: []u8,
2654};2643};
26552644
2656/// Directly access the `.file` field, and then call `AtomicFile.finish` to2645/// Directly access the `.file` field, and then call `AtomicFile.finish` to
...@@ -2668,9 +2657,9 @@ pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions)...@@ -2668,9 +2657,9 @@ pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions)
2668 else2657 else
2669 try self.openDir(dirname, .{});2658 try self.openDir(dirname, .{});
26702659
2671 return AtomicFile.init(fs.path.basename(dest_path), options.mode, dir, true);2660 return .init(fs.path.basename(dest_path), options.mode, dir, true, options.write_buffer);
2672 } else {2661 } else {
2673 return AtomicFile.init(dest_path, options.mode, self, false);2662 return .init(dest_path, options.mode, self, false, options.write_buffer);
2674 }2663 }
2675}2664}
26762665
...@@ -2768,30 +2757,3 @@ pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!v...@@ -2768,30 +2757,3 @@ pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!v
2768 const file: File = .{ .handle = self.fd };2757 const file: File = .{ .handle = self.fd };
2769 try file.setPermissions(permissions);2758 try file.setPermissions(permissions);
2770}2759}
2771
2772const Metadata = File.Metadata;
2773pub const MetadataError = File.MetadataError;
2774
2775/// Returns a `Metadata` struct, representing the permissions on the directory
2776pub fn metadata(self: Dir) MetadataError!Metadata {
2777 const file: File = .{ .handle = self.fd };
2778 return try file.metadata();
2779}
2780
2781const Dir = @This();
2782const builtin = @import("builtin");
2783const std = @import("../std.zig");
2784const File = std.fs.File;
2785const AtomicFile = std.fs.AtomicFile;
2786const base64_encoder = fs.base64_encoder;
2787const crypto = std.crypto;
2788const posix = std.posix;
2789const mem = std.mem;
2790const path = fs.path;
2791const fs = std.fs;
2792const Allocator = std.mem.Allocator;
2793const assert = std.debug.assert;
2794const linux = std.os.linux;
2795const windows = std.os.windows;
2796const native_os = builtin.os.tag;
2797const have_flock = @TypeOf(posix.system.flock) != void;
lib/std/fs/File.zig-107
...@@ -1089,113 +1089,6 @@ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u...@@ -1089,113 +1089,6 @@ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u
1089 return total_bytes_copied;1089 return total_bytes_copied;
1090}1090}
10911091
1092/// Deprecated in favor of `Writer`.
1093pub const WriteFileOptions = struct {
1094 in_offset: u64 = 0,
1095 in_len: ?u64 = null,
1096 headers_and_trailers: []posix.iovec_const = &[0]posix.iovec_const{},
1097 header_count: usize = 0,
1098};
1099
1100/// Deprecated in favor of `Writer`.
1101pub const WriteFileError = ReadError || error{EndOfStream} || WriteError;
1102
1103/// Deprecated in favor of `Writer`.
1104pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
1105 return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {
1106 error.Unseekable,
1107 error.FastOpenAlreadyInProgress,
1108 error.MessageTooBig,
1109 error.FileDescriptorNotASocket,
1110 error.NetworkUnreachable,
1111 error.NetworkSubsystemFailed,
1112 error.ConnectionRefused,
1113 => return self.writeFileAllUnseekable(in_file, args),
1114 else => |e| return e,
1115 };
1116}
1117
1118/// Deprecated in favor of `Writer`.
1119pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
1120 const headers = args.headers_and_trailers[0..args.header_count];
1121 const trailers = args.headers_and_trailers[args.header_count..];
1122 try self.writevAll(headers);
1123 try in_file.deprecatedReader().skipBytes(args.in_offset, .{ .buf_size = 4096 });
1124 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
1125 if (args.in_len) |len| {
1126 var stream = std.io.limitedReader(in_file.deprecatedReader(), len);
1127 try fifo.pump(stream.reader(), self.deprecatedWriter());
1128 } else {
1129 try fifo.pump(in_file.deprecatedReader(), self.deprecatedWriter());
1130 }
1131 try self.writevAll(trailers);
1132}
1133
1134/// Deprecated in favor of `Writer`.
1135fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix.SendFileError!void {
1136 const count = blk: {
1137 if (args.in_len) |l| {
1138 if (l == 0) {
1139 return self.writevAll(args.headers_and_trailers);
1140 } else {
1141 break :blk l;
1142 }
1143 } else {
1144 break :blk 0;
1145 }
1146 };
1147 const headers = args.headers_and_trailers[0..args.header_count];
1148 const trailers = args.headers_and_trailers[args.header_count..];
1149 const zero_iovec = &[0]posix.iovec_const{};
1150 // When reading the whole file, we cannot put the trailers in the sendfile() syscall,
1151 // because we have no way to determine whether a partial write is past the end of the file or not.
1152 const trls = if (count == 0) zero_iovec else trailers;
1153 const offset = args.in_offset;
1154 const out_fd = self.handle;
1155 const in_fd = in_file.handle;
1156 const flags = 0;
1157 var amt: usize = 0;
1158 hdrs: {
1159 var i: usize = 0;
1160 while (i < headers.len) {
1161 amt = try posix.sendfile(out_fd, in_fd, offset, count, headers[i..], trls, flags);
1162 while (amt >= headers[i].len) {
1163 amt -= headers[i].len;
1164 i += 1;
1165 if (i >= headers.len) break :hdrs;
1166 }
1167 headers[i].base += amt;
1168 headers[i].len -= amt;
1169 }
1170 }
1171 if (count == 0) {
1172 var off: u64 = amt;
1173 while (true) {
1174 amt = try posix.sendfile(out_fd, in_fd, offset + off, 0, zero_iovec, zero_iovec, flags);
1175 if (amt == 0) break;
1176 off += amt;
1177 }
1178 } else {
1179 var off: u64 = amt;
1180 while (off < count) {
1181 amt = try posix.sendfile(out_fd, in_fd, offset + off, count - off, zero_iovec, trailers, flags);
1182 off += amt;
1183 }
1184 amt = @as(usize, @intCast(off - count));
1185 }
1186 var i: usize = 0;
1187 while (i < trailers.len) {
1188 while (amt >= trailers[i].len) {
1189 amt -= trailers[i].len;
1190 i += 1;
1191 if (i >= trailers.len) return;
1192 }
1193 trailers[i].base += amt;
1194 trailers[i].len -= amt;
1195 amt = try posix.writev(self.handle, trailers[i..]);
1196 }
1197}
1198
1199/// Deprecated in favor of `Reader`.1092/// Deprecated in favor of `Reader`.
1200pub const DeprecatedReader = io.GenericReader(File, ReadError, read);1093pub const DeprecatedReader = io.GenericReader(File, ReadError, read);
12011094
lib/std/fs/test.zig+13-26
...@@ -1499,32 +1499,18 @@ test "sendfile" {...@@ -1499,32 +1499,18 @@ test "sendfile" {
1499 const header2 = "second header\n";1499 const header2 = "second header\n";
1500 const trailer1 = "trailer1\n";1500 const trailer1 = "trailer1\n";
1501 const trailer2 = "second trailer\n";1501 const trailer2 = "second trailer\n";
1502 var hdtr = [_]posix.iovec_const{1502 var headers: [2][]const u8 = .{ header1, header2 };
1503 .{1503 var trailers: [2][]const u8 = .{ trailer1, trailer2 };
1504 .base = header1,
1505 .len = header1.len,
1506 },
1507 .{
1508 .base = header2,
1509 .len = header2.len,
1510 },
1511 .{
1512 .base = trailer1,
1513 .len = trailer1.len,
1514 },
1515 .{
1516 .base = trailer2,
1517 .len = trailer2.len,
1518 },
1519 };
15201504
1521 var written_buf: [100]u8 = undefined;1505 var written_buf: [100]u8 = undefined;
1522 try dest_file.writeFileAll(src_file, .{1506 var file_reader = src_file.reader(&.{});
1523 .in_offset = 1,1507 var fallback_buffer: [50]u8 = undefined;
1524 .in_len = 10,1508 var file_writer = dest_file.writer(&fallback_buffer);
1525 .headers_and_trailers = &hdtr,1509 try file_writer.interface.writeVecAll(&headers);
1526 .header_count = 2,1510 try file_reader.seekTo(1);
1527 });1511 try testing.expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10)));
1512 try file_writer.interface.writeVecAll(&trailers);
1513 try file_writer.interface.flush();
1528 const amt = try dest_file.preadAll(&written_buf, 0);1514 const amt = try dest_file.preadAll(&written_buf, 0);
1529 try testing.expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]);1515 try testing.expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]);
1530}1516}
...@@ -1595,9 +1581,10 @@ test "AtomicFile" {...@@ -1595,9 +1581,10 @@ test "AtomicFile" {
1595 ;1581 ;
15961582
1597 {1583 {
1598 var af = try ctx.dir.atomicFile(test_out_file, .{});1584 var buffer: [100]u8 = undefined;
1585 var af = try ctx.dir.atomicFile(test_out_file, .{ .write_buffer = &buffer });
1599 defer af.deinit();1586 defer af.deinit();
1600 try af.file.writeAll(test_content);1587 try af.file_writer.interface.writeAll(test_content);
1601 try af.finish();1588 try af.finish();
1602 }1589 }
1603 const content = try ctx.dir.readFileAlloc(allocator, test_out_file, 9999);1590 const content = try ctx.dir.readFileAlloc(allocator, test_out_file, 9999);
src/Builtin.zig+2-2
...@@ -342,9 +342,9 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {...@@ -342,9 +342,9 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
342 }342 }
343343
344 // `make_path` matters because the dir hasn't actually been created yet.344 // `make_path` matters because the dir hasn't actually been created yet.
345 var af = try root_dir.atomicFile(sub_path, .{ .make_path = true });345 var af = try root_dir.atomicFile(sub_path, .{ .make_path = true, .write_buffer = &.{} });
346 defer af.deinit();346 defer af.deinit();
347 try af.file.writeAll(file.source.?);347 try af.file_writer.interface.writeAll(file.source.?);
348 af.finish() catch |err| switch (err) {348 af.finish() catch |err| switch (err) {
349 error.AccessDenied => switch (builtin.os.tag) {349 error.AccessDenied => switch (builtin.os.tag) {
350 .windows => {350 .windows => {
src/Compilation.zig+117-117
...@@ -3382,7 +3382,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3382,7 +3382,7 @@ pub fn saveState(comp: *Compilation) !void {
33823382
3383 const gpa = comp.gpa;3383 const gpa = comp.gpa;
33843384
3385 var bufs = std.ArrayList(std.posix.iovec_const).init(gpa);3385 var bufs = std.ArrayList([]const u8).init(gpa);
3386 defer bufs.deinit();3386 defer bufs.deinit();
33873387
3388 var pt_headers = std.ArrayList(Header.PerThread).init(gpa);3388 var pt_headers = std.ArrayList(Header.PerThread).init(gpa);
...@@ -3421,50 +3421,50 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3421,50 +3421,50 @@ pub fn saveState(comp: *Compilation) !void {
34213421
3422 try bufs.ensureTotalCapacityPrecise(14 + 8 * pt_headers.items.len);3422 try bufs.ensureTotalCapacityPrecise(14 + 8 * pt_headers.items.len);
3423 addBuf(&bufs, mem.asBytes(&header));3423 addBuf(&bufs, mem.asBytes(&header));
3424 addBuf(&bufs, mem.sliceAsBytes(pt_headers.items));3424 addBuf(&bufs, @ptrCast(pt_headers.items));
34253425
3426 addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys()));3426 addBuf(&bufs, @ptrCast(ip.src_hash_deps.keys()));
3427 addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values()));3427 addBuf(&bufs, @ptrCast(ip.src_hash_deps.values()));
3428 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys()));3428 addBuf(&bufs, @ptrCast(ip.nav_val_deps.keys()));
3429 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values()));3429 addBuf(&bufs, @ptrCast(ip.nav_val_deps.values()));
3430 addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys()));3430 addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys()));
3431 addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values()));3431 addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values()));
3432 addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.keys()));3432 addBuf(&bufs, @ptrCast(ip.interned_deps.keys()));
3433 addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.values()));3433 addBuf(&bufs, @ptrCast(ip.interned_deps.values()));
3434 addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.keys()));3434 addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys()));
3435 addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.values()));3435 addBuf(&bufs, @ptrCast(ip.zon_file_deps.values()));
3436 addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.keys()));3436 addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys()));
3437 addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.values()));3437 addBuf(&bufs, @ptrCast(ip.embed_file_deps.values()));
3438 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys()));3438 addBuf(&bufs, @ptrCast(ip.namespace_deps.keys()));
3439 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values()));3439 addBuf(&bufs, @ptrCast(ip.namespace_deps.values()));
3440 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys()));3440 addBuf(&bufs, @ptrCast(ip.namespace_name_deps.keys()));
3441 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.values()));3441 addBuf(&bufs, @ptrCast(ip.namespace_name_deps.values()));
34423442
3443 addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.keys()));3443 addBuf(&bufs, @ptrCast(ip.first_dependency.keys()));
3444 addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.values()));3444 addBuf(&bufs, @ptrCast(ip.first_dependency.values()));
3445 addBuf(&bufs, mem.sliceAsBytes(ip.dep_entries.items));3445 addBuf(&bufs, @ptrCast(ip.dep_entries.items));
3446 addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));3446 addBuf(&bufs, @ptrCast(ip.free_dep_entries.items));
34473447
3448 for (ip.locals, pt_headers.items) |*local, pt_header| {3448 for (ip.locals, pt_headers.items) |*local, pt_header| {
3449 if (pt_header.intern_pool.limbs_len > 0) {3449 if (pt_header.intern_pool.limbs_len > 0) {
3450 addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));3450 addBuf(&bufs, @ptrCast(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
3451 }3451 }
3452 if (pt_header.intern_pool.extra_len > 0) {3452 if (pt_header.intern_pool.extra_len > 0) {
3453 addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));3453 addBuf(&bufs, @ptrCast(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
3454 }3454 }
3455 if (pt_header.intern_pool.items_len > 0) {3455 if (pt_header.intern_pool.items_len > 0) {
3456 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));3456 addBuf(&bufs, @ptrCast(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
3457 addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));3457 addBuf(&bufs, @ptrCast(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
3458 }3458 }
3459 if (pt_header.intern_pool.string_bytes_len > 0) {3459 if (pt_header.intern_pool.string_bytes_len > 0) {
3460 addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);3460 addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);
3461 }3461 }
3462 if (pt_header.intern_pool.tracked_insts_len > 0) {3462 if (pt_header.intern_pool.tracked_insts_len > 0) {
3463 addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));3463 addBuf(&bufs, @ptrCast(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
3464 }3464 }
3465 if (pt_header.intern_pool.files_len > 0) {3465 if (pt_header.intern_pool.files_len > 0) {
3466 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));3466 addBuf(&bufs, @ptrCast(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
3467 addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));3467 addBuf(&bufs, @ptrCast(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
3468 }3468 }
3469 }3469 }
34703470
...@@ -3482,95 +3482,95 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3482,95 +3482,95 @@ pub fn saveState(comp: *Compilation) !void {
3482 try bufs.ensureUnusedCapacity(85);3482 try bufs.ensureUnusedCapacity(85);
3483 addBuf(&bufs, wasm.string_bytes.items);3483 addBuf(&bufs, wasm.string_bytes.items);
3484 // TODO make it well-defined memory layout3484 // TODO make it well-defined memory layout
3485 //addBuf(&bufs, mem.sliceAsBytes(wasm.objects.items));3485 //addBuf(&bufs, @ptrCast(wasm.objects.items));
3486 addBuf(&bufs, mem.sliceAsBytes(wasm.func_types.keys()));3486 addBuf(&bufs, @ptrCast(wasm.func_types.keys()));
3487 addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.keys()));3487 addBuf(&bufs, @ptrCast(wasm.object_function_imports.keys()));
3488 addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.values()));3488 addBuf(&bufs, @ptrCast(wasm.object_function_imports.values()));
3489 addBuf(&bufs, mem.sliceAsBytes(wasm.object_functions.items));3489 addBuf(&bufs, @ptrCast(wasm.object_functions.items));
3490 addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.keys()));3490 addBuf(&bufs, @ptrCast(wasm.object_global_imports.keys()));
3491 addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.values()));3491 addBuf(&bufs, @ptrCast(wasm.object_global_imports.values()));
3492 addBuf(&bufs, mem.sliceAsBytes(wasm.object_globals.items));3492 addBuf(&bufs, @ptrCast(wasm.object_globals.items));
3493 addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.keys()));3493 addBuf(&bufs, @ptrCast(wasm.object_table_imports.keys()));
3494 addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.values()));3494 addBuf(&bufs, @ptrCast(wasm.object_table_imports.values()));
3495 addBuf(&bufs, mem.sliceAsBytes(wasm.object_tables.items));3495 addBuf(&bufs, @ptrCast(wasm.object_tables.items));
3496 addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.keys()));3496 addBuf(&bufs, @ptrCast(wasm.object_memory_imports.keys()));
3497 addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.values()));3497 addBuf(&bufs, @ptrCast(wasm.object_memory_imports.values()));
3498 addBuf(&bufs, mem.sliceAsBytes(wasm.object_memories.items));3498 addBuf(&bufs, @ptrCast(wasm.object_memories.items));
3499 addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.tag)));3499 addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.tag)));
3500 addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.offset)));3500 addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.offset)));
3501 // TODO handle the union safety field3501 // TODO handle the union safety field
3502 //addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.pointee)));3502 //addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.pointee)));
3503 addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.addend)));3503 addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.addend)));
3504 addBuf(&bufs, mem.sliceAsBytes(wasm.object_init_funcs.items));3504 addBuf(&bufs, @ptrCast(wasm.object_init_funcs.items));
3505 addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_segments.items));3505 addBuf(&bufs, @ptrCast(wasm.object_data_segments.items));
3506 addBuf(&bufs, mem.sliceAsBytes(wasm.object_datas.items));3506 addBuf(&bufs, @ptrCast(wasm.object_datas.items));
3507 addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.keys()));3507 addBuf(&bufs, @ptrCast(wasm.object_data_imports.keys()));
3508 addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.values()));3508 addBuf(&bufs, @ptrCast(wasm.object_data_imports.values()));
3509 addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.keys()));3509 addBuf(&bufs, @ptrCast(wasm.object_custom_segments.keys()));
3510 addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.values()));3510 addBuf(&bufs, @ptrCast(wasm.object_custom_segments.values()));
3511 // TODO make it well-defined memory layout3511 // TODO make it well-defined memory layout
3512 // addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdats.items));3512 // addBuf(&bufs, @ptrCast(wasm.object_comdats.items));
3513 addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.keys()));3513 addBuf(&bufs, @ptrCast(wasm.object_relocations_table.keys()));
3514 addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.values()));3514 addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values()));
3515 addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.kind)));3515 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind)));
3516 addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.index)));3516 addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index)));
3517 addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.tag)));3517 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag)));
3518 addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.offset)));3518 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset)));
3519 // TODO handle the union safety field3519 // TODO handle the union safety field
3520 //addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.pointee)));3520 //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee)));
3521 addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.addend)));3521 addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend)));
3522 addBuf(&bufs, mem.sliceAsBytes(wasm.uav_fixups.items));3522 addBuf(&bufs, @ptrCast(wasm.uav_fixups.items));
3523 addBuf(&bufs, mem.sliceAsBytes(wasm.nav_fixups.items));3523 addBuf(&bufs, @ptrCast(wasm.nav_fixups.items));
3524 addBuf(&bufs, mem.sliceAsBytes(wasm.func_table_fixups.items));3524 addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items));
3525 if (is_obj) {3525 if (is_obj) {
3526 addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.keys()));3526 addBuf(&bufs, @ptrCast(wasm.navs_obj.keys()));
3527 addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.values()));3527 addBuf(&bufs, @ptrCast(wasm.navs_obj.values()));
3528 addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.keys()));3528 addBuf(&bufs, @ptrCast(wasm.uavs_obj.keys()));
3529 addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.values()));3529 addBuf(&bufs, @ptrCast(wasm.uavs_obj.values()));
3530 } else {3530 } else {
3531 addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.keys()));3531 addBuf(&bufs, @ptrCast(wasm.navs_exe.keys()));
3532 addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.values()));3532 addBuf(&bufs, @ptrCast(wasm.navs_exe.values()));
3533 addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.keys()));3533 addBuf(&bufs, @ptrCast(wasm.uavs_exe.keys()));
3534 addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.values()));3534 addBuf(&bufs, @ptrCast(wasm.uavs_exe.values()));
3535 }3535 }
3536 addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.keys()));3536 addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.keys()));
3537 addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.values()));3537 addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.values()));
3538 addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.keys()));3538 addBuf(&bufs, @ptrCast(wasm.zcu_funcs.keys()));
3539 // TODO handle the union safety field3539 // TODO handle the union safety field
3540 // addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.values()));3540 // addBuf(&bufs, @ptrCast(wasm.zcu_funcs.values()));
3541 addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.keys()));3541 addBuf(&bufs, @ptrCast(wasm.nav_exports.keys()));
3542 addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.values()));3542 addBuf(&bufs, @ptrCast(wasm.nav_exports.values()));
3543 addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.keys()));3543 addBuf(&bufs, @ptrCast(wasm.uav_exports.keys()));
3544 addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.values()));3544 addBuf(&bufs, @ptrCast(wasm.uav_exports.values()));
3545 addBuf(&bufs, mem.sliceAsBytes(wasm.imports.keys()));3545 addBuf(&bufs, @ptrCast(wasm.imports.keys()));
3546 addBuf(&bufs, mem.sliceAsBytes(wasm.missing_exports.keys()));3546 addBuf(&bufs, @ptrCast(wasm.missing_exports.keys()));
3547 addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.keys()));3547 addBuf(&bufs, @ptrCast(wasm.function_exports.keys()));
3548 addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.values()));3548 addBuf(&bufs, @ptrCast(wasm.function_exports.values()));
3549 addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.keys()));3549 addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.keys()));
3550 addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.values()));3550 addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.values()));
3551 addBuf(&bufs, mem.sliceAsBytes(wasm.global_exports.items));3551 addBuf(&bufs, @ptrCast(wasm.global_exports.items));
3552 addBuf(&bufs, mem.sliceAsBytes(wasm.functions.keys()));3552 addBuf(&bufs, @ptrCast(wasm.functions.keys()));
3553 addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.keys()));3553 addBuf(&bufs, @ptrCast(wasm.function_imports.keys()));
3554 addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.values()));3554 addBuf(&bufs, @ptrCast(wasm.function_imports.values()));
3555 addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.keys()));3555 addBuf(&bufs, @ptrCast(wasm.data_imports.keys()));
3556 addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.values()));3556 addBuf(&bufs, @ptrCast(wasm.data_imports.values()));
3557 addBuf(&bufs, mem.sliceAsBytes(wasm.data_segments.keys()));3557 addBuf(&bufs, @ptrCast(wasm.data_segments.keys()));
3558 addBuf(&bufs, mem.sliceAsBytes(wasm.globals.keys()));3558 addBuf(&bufs, @ptrCast(wasm.globals.keys()));
3559 addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.keys()));3559 addBuf(&bufs, @ptrCast(wasm.global_imports.keys()));
3560 addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.values()));3560 addBuf(&bufs, @ptrCast(wasm.global_imports.values()));
3561 addBuf(&bufs, mem.sliceAsBytes(wasm.tables.keys()));3561 addBuf(&bufs, @ptrCast(wasm.tables.keys()));
3562 addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.keys()));3562 addBuf(&bufs, @ptrCast(wasm.table_imports.keys()));
3563 addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.values()));3563 addBuf(&bufs, @ptrCast(wasm.table_imports.values()));
3564 addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_indirect_function_set.keys()));3564 addBuf(&bufs, @ptrCast(wasm.zcu_indirect_function_set.keys()));
3565 addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_import_set.keys()));3565 addBuf(&bufs, @ptrCast(wasm.object_indirect_function_import_set.keys()));
3566 addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_set.keys()));3566 addBuf(&bufs, @ptrCast(wasm.object_indirect_function_set.keys()));
3567 addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.tag)));3567 addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.tag)));
3568 // TODO handle the union safety field3568 // TODO handle the union safety field
3569 //addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.data)));3569 //addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.data)));
3570 addBuf(&bufs, mem.sliceAsBytes(wasm.mir_extra.items));3570 addBuf(&bufs, @ptrCast(wasm.mir_extra.items));
3571 addBuf(&bufs, mem.sliceAsBytes(wasm.mir_locals.items));3571 addBuf(&bufs, @ptrCast(wasm.mir_locals.items));
3572 addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_bytes.items));3572 addBuf(&bufs, @ptrCast(wasm.tag_name_bytes.items));
3573 addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_offs.items));3573 addBuf(&bufs, @ptrCast(wasm.tag_name_offs.items));
35743574
3575 // TODO add as header fields3575 // TODO add as header fields
3576 // entry_resolution: FunctionImport.Resolution3576 // entry_resolution: FunctionImport.Resolution
...@@ -3596,16 +3596,16 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3596,16 +3596,16 @@ pub fn saveState(comp: *Compilation) !void {
35963596
3597 // Using an atomic file prevents a crash or power failure from corrupting3597 // Using an atomic file prevents a crash or power failure from corrupting
3598 // the previous incremental compilation state.3598 // the previous incremental compilation state.
3599 var af = try lf.emit.root_dir.handle.atomicFile(basename, .{});3599 var write_buffer: [1024]u8 = undefined;
3600 var af = try lf.emit.root_dir.handle.atomicFile(basename, .{ .write_buffer = &write_buffer });
3600 defer af.deinit();3601 defer af.deinit();
3601 try af.file.pwritevAll(bufs.items, 0);3602 try af.file_writer.interface.writeVecAll(bufs.items);
3602 try af.finish();3603 try af.finish();
3603}3604}
36043605
3605fn addBuf(list: *std.ArrayList(std.posix.iovec_const), buf: []const u8) void {3606fn addBuf(list: *std.ArrayList([]const u8), buf: []const u8) void {
3606 // Even when len=0, the undefined pointer might cause EFAULT.
3607 if (buf.len == 0) return;3607 if (buf.len == 0) return;
3608 list.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len });3608 list.appendAssumeCapacity(buf);
3609}3609}
36103610
3611/// This function is temporally single-threaded.3611/// This function is temporally single-threaded.
src/fmt.zig+2-2
...@@ -348,10 +348,10 @@ fn fmtPathFile(...@@ -348,10 +348,10 @@ fn fmtPathFile(
348 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});348 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
349 fmt.any_error = true;349 fmt.any_error = true;
350 } else {350 } else {
351 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });351 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode, .write_buffer = &.{} });
352 defer af.deinit();352 defer af.deinit();
353353
354 try af.file.writeAll(fmt.out_buffer.getWritten());354 try af.file_writer.interface.writeAll(fmt.out_buffer.getWritten());
355 try af.finish();355 try af.finish();
356 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});356 try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
357 }357 }
src/link/MachO.zig-1
...@@ -612,7 +612,6 @@ pub fn flush(...@@ -612,7 +612,6 @@ pub fn flush(
612 };612 };
613 const emit = self.base.emit;613 const emit = self.base.emit;
614 invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) {614 invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) {
615 error.OutOfMemory => return error.OutOfMemory,
616 else => |e| return diags.fail("failed to invalidate kernel cache: {s}", .{@errorName(e)}),615 else => |e| return diags.fail("failed to invalidate kernel cache: {s}", .{@errorName(e)}),
617 };616 };
618 }617 }
src/main.zig+3-1
...@@ -4624,7 +4624,9 @@ fn cmdTranslateC(...@@ -4624,7 +4624,9 @@ fn cmdTranslateC(
4624 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });4624 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
4625 };4625 };
4626 defer zig_file.close();4626 defer zig_file.close();
4627 try fs.File.stdout().writeFileAll(zig_file, .{});4627 var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
4628 var file_reader = zig_file.reader(&.{});
4629 _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited);
4628 return cleanExit();4630 return cleanExit();
4629 }4631 }
4630}4632}