| author | |
| committer | |
| log | f2a3ac7c0534a74ee544fdf6ef9d2176a8d62389 |
| tree | 548115489df6c29b38049d8727b5be74806b488f |
| parent | 5df52ca0a28d204da0557e88c6c9fe1818bcd6af |
please use File.Writer for these use cases
also breaking API changes to std.fs.AtomicFile10 files changed, 274 insertions(+), 416 deletions(-)
lib/std/Build/Step/Run.zig+14-5| ... | ... | @@ -169,7 +169,7 @@ pub const Output = struct { |
| 169 | 169 | pub fn create(owner: *std.Build, name: []const u8) *Run { |
| 170 | 170 | const run = owner.allocator.create(Run) catch @panic("OOM"); |
| 171 | 171 | run.* = .{ |
| 172 | .step = Step.init(.{ | |
| 172 | .step = .init(.{ | |
| 173 | 173 | .id = base_id, |
| 174 | 174 | .name = name, |
| 175 | 175 | .owner = owner, |
| ... | ... | @@ -1769,13 +1769,22 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult { |
| 1769 | 1769 | child.stdin = null; |
| 1770 | 1770 | }, |
| 1771 | 1771 | .lazy_path => |lazy_path| { |
| 1772 | const path = lazy_path.getPath2(b, &run.step); | |
| 1773 | const file = b.build_root.handle.openFile(path, .{}) catch |err| { | |
| 1772 | const path = lazy_path.getPath3(b, &run.step); | |
| 1773 | const file = path.root_dir.handle.openFile(path.subPathOrDot(), .{}) catch |err| { | |
| 1774 | 1774 | return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)}); |
| 1775 | 1775 | }; |
| 1776 | 1776 | defer file.close(); |
| 1777 | child.stdin.?.writeFileAll(file, .{}) catch |err| { | |
| 1778 | return run.step.fail("unable to write file to stdin: {s}", .{@errorName(err)}); | |
| 1777 | // TODO https://github.com/ziglang/zig/issues/23955 | |
| 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 | 1789 | child.stdin.?.close(); |
| 1781 | 1790 | child.stdin = null; |
lib/std/fs/AtomicFile.zig+52-46| ... | ... | @@ -1,6 +1,13 @@ |
| 1 | file: File, | |
| 2 | // TODO either replace this with rand_buf or use []u16 on Windows | |
| 3 | tmp_path_buf: [tmp_path_len:0]u8, | |
| 1 | const AtomicFile = @This(); | |
| 2 | const std = @import("../std.zig"); | |
| 3 | const File = std.fs.File; | |
| 4 | const Dir = std.fs.Dir; | |
| 5 | const fs = std.fs; | |
| 6 | const assert = std.debug.assert; | |
| 7 | const posix = std.posix; | |
| 8 | ||
| 9 | file_writer: File.Writer, | |
| 10 | random_integer: u64, | |
| 4 | 11 | dest_basename: []const u8, |
| 5 | 12 | file_open: bool, |
| 6 | 13 | file_exists: bool, |
| ... | ... | @@ -9,35 +16,24 @@ dir: Dir, |
| 9 | 16 | |
| 10 | 17 | pub const InitError = File.OpenError; |
| 11 | 18 | |
| 12 | pub const random_bytes_len = 12; | |
| 13 | const tmp_path_len = fs.base64_encoder.calcSize(random_bytes_len); | |
| 14 | ||
| 15 | 19 | /// Note that the `Dir.atomicFile` API may be more handy than this lower-level function. |
| 16 | 20 | pub fn init( |
| 17 | 21 | dest_basename: []const u8, |
| 18 | 22 | mode: File.Mode, |
| 19 | 23 | dir: Dir, |
| 20 | 24 | close_dir_on_deinit: bool, |
| 25 | write_buffer: []u8, | |
| 21 | 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 | 27 | while (true) { |
| 26 | std.crypto.random.bytes(rand_buf[0..]); | |
| 27 | const tmp_path = fs.base64_encoder.encode(&tmp_path_buf, &rand_buf); | |
| 28 | tmp_path_buf[tmp_path.len] = 0; | |
| 29 | ||
| 30 | const file = dir.createFile( | |
| 31 | tmp_path, | |
| 32 | .{ .mode = mode, .exclusive = true }, | |
| 33 | ) catch |err| switch (err) { | |
| 28 | const random_integer = std.crypto.random.int(u64); | |
| 29 | const tmp_sub_path = std.fmt.hex(random_integer); | |
| 30 | const file = dir.createFile(&tmp_sub_path, .{ .mode = mode, .exclusive = true }) catch |err| switch (err) { | |
| 34 | 31 | error.PathAlreadyExists => continue, |
| 35 | 32 | else => |e| return e, |
| 36 | 33 | }; |
| 37 | ||
| 38 | return AtomicFile{ | |
| 39 | .file = file, | |
| 40 | .tmp_path_buf = tmp_path_buf, | |
| 34 | return .{ | |
| 35 | .file_writer = file.writer(write_buffer), | |
| 36 | .random_integer = random_integer, | |
| 41 | 37 | .dest_basename = dest_basename, |
| 42 | 38 | .file_open = true, |
| 43 | 39 | .file_exists = true, |
| ... | ... | @@ -48,41 +44,51 @@ pub fn init( |
| 48 | 44 | } |
| 49 | 45 | |
| 50 | 46 | /// Always call deinit, even after a successful finish(). |
| 51 | pub fn deinit(self: *AtomicFile) void { | |
| 52 | if (self.file_open) { | |
| 53 | self.file.close(); | |
| 54 | self.file_open = false; | |
| 47 | pub fn deinit(af: *AtomicFile) void { | |
| 48 | if (af.file_open) { | |
| 49 | af.file_writer.file.close(); | |
| 50 | af.file_open = false; | |
| 55 | 51 | } |
| 56 | if (self.file_exists) { | |
| 57 | self.dir.deleteFile(&self.tmp_path_buf) catch {}; | |
| 58 | self.file_exists = false; | |
| 52 | if (af.file_exists) { | |
| 53 | const tmp_sub_path = std.fmt.hex(af.random_integer); | |
| 54 | af.dir.deleteFile(&tmp_sub_path) catch {}; | |
| 55 | af.file_exists = false; | |
| 59 | 56 | } |
| 60 | if (self.close_dir_on_deinit) { | |
| 61 | self.dir.close(); | |
| 57 | if (af.close_dir_on_deinit) { | |
| 58 | af.dir.close(); | |
| 62 | 59 | } |
| 63 | self.* = undefined; | |
| 60 | af.* = undefined; | |
| 64 | 61 | } |
| 65 | 62 | |
| 66 | pub const FinishError = posix.RenameError; | |
| 63 | pub const FlushError = File.WriteError; | |
| 64 | ||
| 65 | pub 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 | ||
| 71 | pub const RenameIntoPlaceError = posix.RenameError; | |
| 67 | 72 | |
| 68 | 73 | /// On Windows, this function introduces a period of time where some file |
| 69 | 74 | /// system operations on the destination file will result in |
| 70 | 75 | /// `error.AccessDenied`, including rename operations (such as the one used in |
| 71 | 76 | /// this function). |
| 72 | pub fn finish(self: *AtomicFile) FinishError!void { | |
| 73 | assert(self.file_exists); | |
| 74 | if (self.file_open) { | |
| 75 | self.file.close(); | |
| 76 | self.file_open = false; | |
| 77 | pub fn renameIntoPlace(af: *AtomicFile) RenameIntoPlaceError!void { | |
| 78 | assert(af.file_exists); | |
| 79 | if (af.file_open) { | |
| 80 | af.file_writer.file.close(); | |
| 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); | |
| 79 | self.file_exists = false; | |
| 83 | const tmp_sub_path = std.fmt.hex(af.random_integer); | |
| 84 | try posix.renameat(af.dir.fd, &tmp_sub_path, af.dir.fd, af.dest_basename); | |
| 85 | af.file_exists = false; | |
| 80 | 86 | } |
| 81 | 87 | |
| 82 | const AtomicFile = @This(); | |
| 83 | const std = @import("../std.zig"); | |
| 84 | const File = std.fs.File; | |
| 85 | const Dir = std.fs.Dir; | |
| 86 | const fs = std.fs; | |
| 87 | const assert = std.debug.assert; | |
| 88 | const posix = std.posix; | |
| 88 | pub const FinishError = FlushError || RenameIntoPlaceError; | |
| 89 | ||
| 90 | /// Combination of `flush` followed by `renameIntoPlace`. | |
| 91 | pub fn finish(af: *AtomicFile) FinishError!void { | |
| 92 | try af.flush(); | |
| 93 | try af.renameIntoPlace(); | |
| 94 | } |
lib/std/fs/Dir.zig+71-109| ... | ... | @@ -1,3 +1,20 @@ |
| 1 | const Dir = @This(); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const std = @import("../std.zig"); | |
| 4 | const File = std.fs.File; | |
| 5 | const AtomicFile = std.fs.AtomicFile; | |
| 6 | const base64_encoder = fs.base64_encoder; | |
| 7 | const posix = std.posix; | |
| 8 | const mem = std.mem; | |
| 9 | const path = fs.path; | |
| 10 | const fs = std.fs; | |
| 11 | const Allocator = std.mem.Allocator; | |
| 12 | const assert = std.debug.assert; | |
| 13 | const linux = std.os.linux; | |
| 14 | const windows = std.os.windows; | |
| 15 | const native_os = builtin.os.tag; | |
| 16 | const have_flock = @TypeOf(posix.system.flock) != void; | |
| 17 | ||
| 1 | 18 | fd: Handle, |
| 2 | 19 | |
| 3 | 20 | pub const Handle = posix.fd_t; |
| ... | ... | @@ -1862,9 +1879,10 @@ pub fn symLinkW( |
| 1862 | 1879 | |
| 1863 | 1880 | /// Same as `symLink`, except tries to create the symbolic link until it |
| 1864 | 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/). | |
| 1866 | /// On WASI, both paths should be encoded as valid UTF-8. | |
| 1867 | /// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. | |
| 1882 | /// | |
| 1883 | /// * On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | |
| 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. | |
| 1868 | 1886 | pub fn atomicSymLink( |
| 1869 | 1887 | dir: Dir, |
| 1870 | 1888 | target_path: []const u8, |
| ... | ... | @@ -1880,9 +1898,8 @@ pub fn atomicSymLink( |
| 1880 | 1898 | |
| 1881 | 1899 | const dirname = path.dirname(sym_link_path) orelse "."; |
| 1882 | 1900 | |
| 1883 | var rand_buf: [AtomicFile.random_bytes_len]u8 = undefined; | |
| 1884 | ||
| 1885 | const temp_path_len = dirname.len + 1 + base64_encoder.calcSize(rand_buf.len); | |
| 1901 | const rand_len = @sizeOf(u64) * 2; | |
| 1902 | const temp_path_len = dirname.len + 1 + rand_len; | |
| 1886 | 1903 | var temp_path_buf: [fs.max_path_bytes]u8 = undefined; |
| 1887 | 1904 | |
| 1888 | 1905 | if (temp_path_len > temp_path_buf.len) return error.NameTooLong; |
| ... | ... | @@ -1892,8 +1909,8 @@ pub fn atomicSymLink( |
| 1892 | 1909 | const temp_path = temp_path_buf[0..temp_path_len]; |
| 1893 | 1910 | |
| 1894 | 1911 | while (true) { |
| 1895 | crypto.random.bytes(rand_buf[0..]); | |
| 1896 | _ = base64_encoder.encode(temp_path[dirname.len + 1 ..], rand_buf[0..]); | |
| 1912 | const random_integer = std.crypto.random.int(u64); | |
| 1913 | temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer); | |
| 1897 | 1914 | |
| 1898 | 1915 | if (dir.symLink(target_path, temp_path, flags)) { |
| 1899 | 1916 | return dir.rename(temp_path, sym_link_path); |
| ... | ... | @@ -2552,25 +2569,42 @@ pub fn updateFile( |
| 2552 | 2569 | try dest_dir.makePath(dirname); |
| 2553 | 2570 | } |
| 2554 | 2571 | |
| 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 | 2577 | defer atomic_file.deinit(); |
| 2557 | 2578 | |
| 2558 | try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size }); | |
| 2559 | try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime); | |
| 2579 | var src_reader: File.Reader = .initSize(src_file, &.{}, src_stat.size); | |
| 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 | 2587 | try atomic_file.finish(); |
| 2561 | return PrevStatus.stale; | |
| 2588 | return .stale; | |
| 2562 | 2589 | } |
| 2563 | 2590 | |
| 2564 | 2591 | pub const CopyFileError = File.OpenError || File.StatError || |
| 2565 | AtomicFile.InitError || CopyFileRawError || AtomicFile.FinishError; | |
| 2592 | AtomicFile.InitError || AtomicFile.FinishError || | |
| 2593 | File.ReadError || File.WriteError; | |
| 2566 | 2594 | |
| 2567 | /// Guaranteed to be atomic. | |
| 2568 | /// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available, | |
| 2569 | /// there is a possibility of power loss or application termination leaving temporary files present | |
| 2570 | /// in the same directory as dest_path. | |
| 2571 | /// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | |
| 2572 | /// On WASI, both paths should be encoded as valid UTF-8. | |
| 2573 | /// On other platforms, both paths are an opaque sequence of bytes with no particular encoding. | |
| 2595 | /// Atomically creates a new file at `dest_path` within `dest_dir` with the | |
| 2596 | /// same contents as `source_path` within `source_dir`, overwriting any already | |
| 2597 | /// existing file. | |
| 2598 | /// | |
| 2599 | /// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and | |
| 2600 | /// readily available, there is a possibility of power loss or application | |
| 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. | |
| 2574 | 2608 | pub fn copyFile( |
| 2575 | 2609 | source_dir: Dir, |
| 2576 | 2610 | source_path: []const u8, |
| ... | ... | @@ -2578,79 +2612,34 @@ pub fn copyFile( |
| 2578 | 2612 | dest_path: []const u8, |
| 2579 | 2613 | options: CopyFileOptions, |
| 2580 | 2614 | ) CopyFileError!void { |
| 2581 | var in_file = try source_dir.openFile(source_path, .{}); | |
| 2582 | defer in_file.close(); | |
| 2615 | var file_reader: File.Reader = .init(try source_dir.openFile(source_path, .{}), &.{}); | |
| 2616 | defer file_reader.file.close(); | |
| 2583 | 2617 | |
| 2584 | var size: ?u64 = null; | |
| 2585 | 2618 | const mode = options.override_mode orelse blk: { |
| 2586 | const st = try in_file.stat(); | |
| 2587 | size = st.size; | |
| 2619 | const st = try file_reader.file.stat(); | |
| 2620 | file_reader.size = st.size; | |
| 2588 | 2621 | break :blk st.mode; |
| 2589 | 2622 | }; |
| 2590 | 2623 | |
| 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 | 2629 | defer atomic_file.deinit(); |
| 2593 | 2630 | |
| 2594 | try copy_file(in_file.handle, atomic_file.file.handle, size); | |
| 2595 | try atomic_file.finish(); | |
| 2596 | } | |
| 2597 | ||
| 2598 | const 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. | |
| 2603 | fn 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 | } | |
| 2631 | _ = atomic_file.file_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) { | |
| 2632 | error.ReadFailed => return file_reader.err.?, | |
| 2633 | error.WriteFailed => return atomic_file.file_writer.err.?, | |
| 2634 | }; | |
| 2635 | 2635 | |
| 2636 | // Sendfile is a zero-copy mechanism iff the OS supports it, otherwise the | |
| 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 | } | |
| 2636 | try atomic_file.finish(); | |
| 2649 | 2637 | } |
| 2650 | 2638 | |
| 2651 | 2639 | pub const AtomicFileOptions = struct { |
| 2652 | 2640 | mode: File.Mode = File.default_mode, |
| 2653 | 2641 | make_path: bool = false, |
| 2642 | write_buffer: []u8, | |
| 2654 | 2643 | }; |
| 2655 | 2644 | |
| 2656 | 2645 | /// 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 | 2657 | else |
| 2669 | 2658 | try self.openDir(dirname, .{}); |
| 2670 | 2659 | |
| 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 | 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 | } |
| 2676 | 2665 | |
| ... | ... | @@ -2768,30 +2757,3 @@ pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!v |
| 2768 | 2757 | const file: File = .{ .handle = self.fd }; |
| 2769 | 2758 | try file.setPermissions(permissions); |
| 2770 | 2759 | } |
| 2771 | ||
| 2772 | const Metadata = File.Metadata; | |
| 2773 | pub const MetadataError = File.MetadataError; | |
| 2774 | ||
| 2775 | /// Returns a `Metadata` struct, representing the permissions on the directory | |
| 2776 | pub fn metadata(self: Dir) MetadataError!Metadata { | |
| 2777 | const file: File = .{ .handle = self.fd }; | |
| 2778 | return try file.metadata(); | |
| 2779 | } | |
| 2780 | ||
| 2781 | const Dir = @This(); | |
| 2782 | const builtin = @import("builtin"); | |
| 2783 | const std = @import("../std.zig"); | |
| 2784 | const File = std.fs.File; | |
| 2785 | const AtomicFile = std.fs.AtomicFile; | |
| 2786 | const base64_encoder = fs.base64_encoder; | |
| 2787 | const crypto = std.crypto; | |
| 2788 | const posix = std.posix; | |
| 2789 | const mem = std.mem; | |
| 2790 | const path = fs.path; | |
| 2791 | const fs = std.fs; | |
| 2792 | const Allocator = std.mem.Allocator; | |
| 2793 | const assert = std.debug.assert; | |
| 2794 | const linux = std.os.linux; | |
| 2795 | const windows = std.os.windows; | |
| 2796 | const native_os = builtin.os.tag; | |
| 2797 | const 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 | 1089 | return total_bytes_copied; |
| 1090 | 1090 | } |
| 1091 | 1091 | |
| 1092 | /// Deprecated in favor of `Writer`. | |
| 1093 | pub 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`. | |
| 1101 | pub const WriteFileError = ReadError || error{EndOfStream} || WriteError; | |
| 1102 | ||
| 1103 | /// Deprecated in favor of `Writer`. | |
| 1104 | pub 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`. | |
| 1119 | pub 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`. | |
| 1135 | fn 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 | 1092 | /// Deprecated in favor of `Reader`. |
| 1200 | 1093 | pub const DeprecatedReader = io.GenericReader(File, ReadError, read); |
| 1201 | 1094 |
lib/std/fs/test.zig+13-26| ... | ... | @@ -1499,32 +1499,18 @@ test "sendfile" { |
| 1499 | 1499 | const header2 = "second header\n"; |
| 1500 | 1500 | const trailer1 = "trailer1\n"; |
| 1501 | 1501 | const trailer2 = "second trailer\n"; |
| 1502 | var hdtr = [_]posix.iovec_const{ | |
| 1503 | .{ | |
| 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 | }; | |
| 1502 | var headers: [2][]const u8 = .{ header1, header2 }; | |
| 1503 | var trailers: [2][]const u8 = .{ trailer1, trailer2 }; | |
| 1520 | 1504 | |
| 1521 | 1505 | var written_buf: [100]u8 = undefined; |
| 1522 | try dest_file.writeFileAll(src_file, .{ | |
| 1523 | .in_offset = 1, | |
| 1524 | .in_len = 10, | |
| 1525 | .headers_and_trailers = &hdtr, | |
| 1526 | .header_count = 2, | |
| 1527 | }); | |
| 1506 | var file_reader = src_file.reader(&.{}); | |
| 1507 | var fallback_buffer: [50]u8 = undefined; | |
| 1508 | var file_writer = dest_file.writer(&fallback_buffer); | |
| 1509 | try file_writer.interface.writeVecAll(&headers); | |
| 1510 | try file_reader.seekTo(1); | |
| 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 | 1514 | const amt = try dest_file.preadAll(&written_buf, 0); |
| 1529 | 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 | 1581 | ; |
| 1596 | 1582 | |
| 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 | 1586 | defer af.deinit(); |
| 1600 | try af.file.writeAll(test_content); | |
| 1587 | try af.file_writer.interface.writeAll(test_content); | |
| 1601 | 1588 | try af.finish(); |
| 1602 | 1589 | } |
| 1603 | 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 | 342 | } |
| 343 | 343 | |
| 344 | 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 | 346 | defer af.deinit(); |
| 347 | try af.file.writeAll(file.source.?); | |
| 347 | try af.file_writer.interface.writeAll(file.source.?); | |
| 348 | 348 | af.finish() catch |err| switch (err) { |
| 349 | 349 | error.AccessDenied => switch (builtin.os.tag) { |
| 350 | 350 | .windows => { |
src/Compilation.zig+117-117| ... | ... | @@ -3382,7 +3382,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 3382 | 3382 | |
| 3383 | 3383 | const gpa = comp.gpa; |
| 3384 | 3384 | |
| 3385 | var bufs = std.ArrayList(std.posix.iovec_const).init(gpa); | |
| 3385 | var bufs = std.ArrayList([]const u8).init(gpa); | |
| 3386 | 3386 | defer bufs.deinit(); |
| 3387 | 3387 | |
| 3388 | 3388 | var pt_headers = std.ArrayList(Header.PerThread).init(gpa); |
| ... | ... | @@ -3421,50 +3421,50 @@ pub fn saveState(comp: *Compilation) !void { |
| 3421 | 3421 | |
| 3422 | 3422 | try bufs.ensureTotalCapacityPrecise(14 + 8 * pt_headers.items.len); |
| 3423 | 3423 | addBuf(&bufs, mem.asBytes(&header)); |
| 3424 | addBuf(&bufs, mem.sliceAsBytes(pt_headers.items)); | |
| 3425 | ||
| 3426 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); | |
| 3427 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); | |
| 3428 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); | |
| 3429 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values())); | |
| 3430 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys())); | |
| 3431 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values())); | |
| 3432 | addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.keys())); | |
| 3433 | addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.values())); | |
| 3434 | addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.keys())); | |
| 3435 | addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.values())); | |
| 3436 | addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.keys())); | |
| 3437 | addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.values())); | |
| 3438 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys())); | |
| 3439 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values())); | |
| 3440 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys())); | |
| 3441 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.values())); | |
| 3442 | ||
| 3443 | addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.keys())); | |
| 3444 | addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.values())); | |
| 3445 | addBuf(&bufs, mem.sliceAsBytes(ip.dep_entries.items)); | |
| 3446 | addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items)); | |
| 3424 | addBuf(&bufs, @ptrCast(pt_headers.items)); | |
| 3425 | ||
| 3426 | addBuf(&bufs, @ptrCast(ip.src_hash_deps.keys())); | |
| 3427 | addBuf(&bufs, @ptrCast(ip.src_hash_deps.values())); | |
| 3428 | addBuf(&bufs, @ptrCast(ip.nav_val_deps.keys())); | |
| 3429 | addBuf(&bufs, @ptrCast(ip.nav_val_deps.values())); | |
| 3430 | addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys())); | |
| 3431 | addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); | |
| 3432 | addBuf(&bufs, @ptrCast(ip.interned_deps.keys())); | |
| 3433 | addBuf(&bufs, @ptrCast(ip.interned_deps.values())); | |
| 3434 | addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); | |
| 3435 | addBuf(&bufs, @ptrCast(ip.zon_file_deps.values())); | |
| 3436 | addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys())); | |
| 3437 | addBuf(&bufs, @ptrCast(ip.embed_file_deps.values())); | |
| 3438 | addBuf(&bufs, @ptrCast(ip.namespace_deps.keys())); | |
| 3439 | addBuf(&bufs, @ptrCast(ip.namespace_deps.values())); | |
| 3440 | addBuf(&bufs, @ptrCast(ip.namespace_name_deps.keys())); | |
| 3441 | addBuf(&bufs, @ptrCast(ip.namespace_name_deps.values())); | |
| 3442 | ||
| 3443 | addBuf(&bufs, @ptrCast(ip.first_dependency.keys())); | |
| 3444 | addBuf(&bufs, @ptrCast(ip.first_dependency.values())); | |
| 3445 | addBuf(&bufs, @ptrCast(ip.dep_entries.items)); | |
| 3446 | addBuf(&bufs, @ptrCast(ip.free_dep_entries.items)); | |
| 3447 | 3447 | |
| 3448 | 3448 | for (ip.locals, pt_headers.items) |*local, pt_header| { |
| 3449 | 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 | 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 | 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])); | |
| 3457 | addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[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, @ptrCast(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len])); | |
| 3458 | 3458 | } |
| 3459 | 3459 | if (pt_header.intern_pool.string_bytes_len > 0) { |
| 3460 | 3460 | addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]); |
| 3461 | 3461 | } |
| 3462 | 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 | 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])); | |
| 3467 | addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[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, @ptrCast(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len])); | |
| 3468 | 3468 | } |
| 3469 | 3469 | } |
| 3470 | 3470 | |
| ... | ... | @@ -3482,95 +3482,95 @@ pub fn saveState(comp: *Compilation) !void { |
| 3482 | 3482 | try bufs.ensureUnusedCapacity(85); |
| 3483 | 3483 | addBuf(&bufs, wasm.string_bytes.items); |
| 3484 | 3484 | // TODO make it well-defined memory layout |
| 3485 | //addBuf(&bufs, mem.sliceAsBytes(wasm.objects.items)); | |
| 3486 | addBuf(&bufs, mem.sliceAsBytes(wasm.func_types.keys())); | |
| 3487 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.keys())); | |
| 3488 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.values())); | |
| 3489 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_functions.items)); | |
| 3490 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.keys())); | |
| 3491 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.values())); | |
| 3492 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_globals.items)); | |
| 3493 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.keys())); | |
| 3494 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.values())); | |
| 3495 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_tables.items)); | |
| 3496 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.keys())); | |
| 3497 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.values())); | |
| 3498 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_memories.items)); | |
| 3499 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.tag))); | |
| 3500 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.offset))); | |
| 3485 | //addBuf(&bufs, @ptrCast(wasm.objects.items)); | |
| 3486 | addBuf(&bufs, @ptrCast(wasm.func_types.keys())); | |
| 3487 | addBuf(&bufs, @ptrCast(wasm.object_function_imports.keys())); | |
| 3488 | addBuf(&bufs, @ptrCast(wasm.object_function_imports.values())); | |
| 3489 | addBuf(&bufs, @ptrCast(wasm.object_functions.items)); | |
| 3490 | addBuf(&bufs, @ptrCast(wasm.object_global_imports.keys())); | |
| 3491 | addBuf(&bufs, @ptrCast(wasm.object_global_imports.values())); | |
| 3492 | addBuf(&bufs, @ptrCast(wasm.object_globals.items)); | |
| 3493 | addBuf(&bufs, @ptrCast(wasm.object_table_imports.keys())); | |
| 3494 | addBuf(&bufs, @ptrCast(wasm.object_table_imports.values())); | |
| 3495 | addBuf(&bufs, @ptrCast(wasm.object_tables.items)); | |
| 3496 | addBuf(&bufs, @ptrCast(wasm.object_memory_imports.keys())); | |
| 3497 | addBuf(&bufs, @ptrCast(wasm.object_memory_imports.values())); | |
| 3498 | addBuf(&bufs, @ptrCast(wasm.object_memories.items)); | |
| 3499 | addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.tag))); | |
| 3500 | addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.offset))); | |
| 3501 | 3501 | // TODO handle the union safety field |
| 3502 | //addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.pointee))); | |
| 3503 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.addend))); | |
| 3504 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_init_funcs.items)); | |
| 3505 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_segments.items)); | |
| 3506 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_datas.items)); | |
| 3507 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.keys())); | |
| 3508 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.values())); | |
| 3509 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.keys())); | |
| 3510 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.values())); | |
| 3502 | //addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.pointee))); | |
| 3503 | addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.addend))); | |
| 3504 | addBuf(&bufs, @ptrCast(wasm.object_init_funcs.items)); | |
| 3505 | addBuf(&bufs, @ptrCast(wasm.object_data_segments.items)); | |
| 3506 | addBuf(&bufs, @ptrCast(wasm.object_datas.items)); | |
| 3507 | addBuf(&bufs, @ptrCast(wasm.object_data_imports.keys())); | |
| 3508 | addBuf(&bufs, @ptrCast(wasm.object_data_imports.values())); | |
| 3509 | addBuf(&bufs, @ptrCast(wasm.object_custom_segments.keys())); | |
| 3510 | addBuf(&bufs, @ptrCast(wasm.object_custom_segments.values())); | |
| 3511 | 3511 | // TODO make it well-defined memory layout |
| 3512 | // addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdats.items)); | |
| 3513 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.keys())); | |
| 3514 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.values())); | |
| 3515 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.kind))); | |
| 3516 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.index))); | |
| 3517 | addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.tag))); | |
| 3518 | addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.offset))); | |
| 3512 | // addBuf(&bufs, @ptrCast(wasm.object_comdats.items)); | |
| 3513 | addBuf(&bufs, @ptrCast(wasm.object_relocations_table.keys())); | |
| 3514 | addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values())); | |
| 3515 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind))); | |
| 3516 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index))); | |
| 3517 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag))); | |
| 3518 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset))); | |
| 3519 | 3519 | // TODO handle the union safety field |
| 3520 | //addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.pointee))); | |
| 3521 | addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.addend))); | |
| 3522 | addBuf(&bufs, mem.sliceAsBytes(wasm.uav_fixups.items)); | |
| 3523 | addBuf(&bufs, mem.sliceAsBytes(wasm.nav_fixups.items)); | |
| 3524 | addBuf(&bufs, mem.sliceAsBytes(wasm.func_table_fixups.items)); | |
| 3520 | //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee))); | |
| 3521 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend))); | |
| 3522 | addBuf(&bufs, @ptrCast(wasm.uav_fixups.items)); | |
| 3523 | addBuf(&bufs, @ptrCast(wasm.nav_fixups.items)); | |
| 3524 | addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items)); | |
| 3525 | 3525 | if (is_obj) { |
| 3526 | addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.keys())); | |
| 3527 | addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.values())); | |
| 3528 | addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.keys())); | |
| 3529 | addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.values())); | |
| 3526 | addBuf(&bufs, @ptrCast(wasm.navs_obj.keys())); | |
| 3527 | addBuf(&bufs, @ptrCast(wasm.navs_obj.values())); | |
| 3528 | addBuf(&bufs, @ptrCast(wasm.uavs_obj.keys())); | |
| 3529 | addBuf(&bufs, @ptrCast(wasm.uavs_obj.values())); | |
| 3530 | 3530 | } else { |
| 3531 | addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.keys())); | |
| 3532 | addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.values())); | |
| 3533 | addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.keys())); | |
| 3534 | addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.values())); | |
| 3531 | addBuf(&bufs, @ptrCast(wasm.navs_exe.keys())); | |
| 3532 | addBuf(&bufs, @ptrCast(wasm.navs_exe.values())); | |
| 3533 | addBuf(&bufs, @ptrCast(wasm.uavs_exe.keys())); | |
| 3534 | addBuf(&bufs, @ptrCast(wasm.uavs_exe.values())); | |
| 3535 | 3535 | } |
| 3536 | addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.keys())); | |
| 3537 | addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.values())); | |
| 3538 | addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.keys())); | |
| 3536 | addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.keys())); | |
| 3537 | addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.values())); | |
| 3538 | addBuf(&bufs, @ptrCast(wasm.zcu_funcs.keys())); | |
| 3539 | 3539 | // TODO handle the union safety field |
| 3540 | // addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.values())); | |
| 3541 | addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.keys())); | |
| 3542 | addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.values())); | |
| 3543 | addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.keys())); | |
| 3544 | addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.values())); | |
| 3545 | addBuf(&bufs, mem.sliceAsBytes(wasm.imports.keys())); | |
| 3546 | addBuf(&bufs, mem.sliceAsBytes(wasm.missing_exports.keys())); | |
| 3547 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.keys())); | |
| 3548 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.values())); | |
| 3549 | addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.keys())); | |
| 3550 | addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.values())); | |
| 3551 | addBuf(&bufs, mem.sliceAsBytes(wasm.global_exports.items)); | |
| 3552 | addBuf(&bufs, mem.sliceAsBytes(wasm.functions.keys())); | |
| 3553 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.keys())); | |
| 3554 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.values())); | |
| 3555 | addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.keys())); | |
| 3556 | addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.values())); | |
| 3557 | addBuf(&bufs, mem.sliceAsBytes(wasm.data_segments.keys())); | |
| 3558 | addBuf(&bufs, mem.sliceAsBytes(wasm.globals.keys())); | |
| 3559 | addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.keys())); | |
| 3560 | addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.values())); | |
| 3561 | addBuf(&bufs, mem.sliceAsBytes(wasm.tables.keys())); | |
| 3562 | addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.keys())); | |
| 3563 | addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.values())); | |
| 3564 | addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_indirect_function_set.keys())); | |
| 3565 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_import_set.keys())); | |
| 3566 | addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_set.keys())); | |
| 3567 | addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.tag))); | |
| 3540 | // addBuf(&bufs, @ptrCast(wasm.zcu_funcs.values())); | |
| 3541 | addBuf(&bufs, @ptrCast(wasm.nav_exports.keys())); | |
| 3542 | addBuf(&bufs, @ptrCast(wasm.nav_exports.values())); | |
| 3543 | addBuf(&bufs, @ptrCast(wasm.uav_exports.keys())); | |
| 3544 | addBuf(&bufs, @ptrCast(wasm.uav_exports.values())); | |
| 3545 | addBuf(&bufs, @ptrCast(wasm.imports.keys())); | |
| 3546 | addBuf(&bufs, @ptrCast(wasm.missing_exports.keys())); | |
| 3547 | addBuf(&bufs, @ptrCast(wasm.function_exports.keys())); | |
| 3548 | addBuf(&bufs, @ptrCast(wasm.function_exports.values())); | |
| 3549 | addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.keys())); | |
| 3550 | addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.values())); | |
| 3551 | addBuf(&bufs, @ptrCast(wasm.global_exports.items)); | |
| 3552 | addBuf(&bufs, @ptrCast(wasm.functions.keys())); | |
| 3553 | addBuf(&bufs, @ptrCast(wasm.function_imports.keys())); | |
| 3554 | addBuf(&bufs, @ptrCast(wasm.function_imports.values())); | |
| 3555 | addBuf(&bufs, @ptrCast(wasm.data_imports.keys())); | |
| 3556 | addBuf(&bufs, @ptrCast(wasm.data_imports.values())); | |
| 3557 | addBuf(&bufs, @ptrCast(wasm.data_segments.keys())); | |
| 3558 | addBuf(&bufs, @ptrCast(wasm.globals.keys())); | |
| 3559 | addBuf(&bufs, @ptrCast(wasm.global_imports.keys())); | |
| 3560 | addBuf(&bufs, @ptrCast(wasm.global_imports.values())); | |
| 3561 | addBuf(&bufs, @ptrCast(wasm.tables.keys())); | |
| 3562 | addBuf(&bufs, @ptrCast(wasm.table_imports.keys())); | |
| 3563 | addBuf(&bufs, @ptrCast(wasm.table_imports.values())); | |
| 3564 | addBuf(&bufs, @ptrCast(wasm.zcu_indirect_function_set.keys())); | |
| 3565 | addBuf(&bufs, @ptrCast(wasm.object_indirect_function_import_set.keys())); | |
| 3566 | addBuf(&bufs, @ptrCast(wasm.object_indirect_function_set.keys())); | |
| 3567 | addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.tag))); | |
| 3568 | 3568 | // TODO handle the union safety field |
| 3569 | //addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.data))); | |
| 3570 | addBuf(&bufs, mem.sliceAsBytes(wasm.mir_extra.items)); | |
| 3571 | addBuf(&bufs, mem.sliceAsBytes(wasm.mir_locals.items)); | |
| 3572 | addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_bytes.items)); | |
| 3573 | addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_offs.items)); | |
| 3569 | //addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.data))); | |
| 3570 | addBuf(&bufs, @ptrCast(wasm.mir_extra.items)); | |
| 3571 | addBuf(&bufs, @ptrCast(wasm.mir_locals.items)); | |
| 3572 | addBuf(&bufs, @ptrCast(wasm.tag_name_bytes.items)); | |
| 3573 | addBuf(&bufs, @ptrCast(wasm.tag_name_offs.items)); | |
| 3574 | 3574 | |
| 3575 | 3575 | // TODO add as header fields |
| 3576 | 3576 | // entry_resolution: FunctionImport.Resolution |
| ... | ... | @@ -3596,16 +3596,16 @@ pub fn saveState(comp: *Compilation) !void { |
| 3596 | 3596 | |
| 3597 | 3597 | // Using an atomic file prevents a crash or power failure from corrupting |
| 3598 | 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 | 3601 | defer af.deinit(); |
| 3601 | try af.file.pwritevAll(bufs.items, 0); | |
| 3602 | try af.file_writer.interface.writeVecAll(bufs.items); | |
| 3602 | 3603 | try af.finish(); |
| 3603 | 3604 | } |
| 3604 | 3605 | |
| 3605 | fn addBuf(list: *std.ArrayList(std.posix.iovec_const), buf: []const u8) void { | |
| 3606 | // Even when len=0, the undefined pointer might cause EFAULT. | |
| 3606 | fn addBuf(list: *std.ArrayList([]const u8), buf: []const u8) void { | |
| 3607 | 3607 | if (buf.len == 0) return; |
| 3608 | list.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len }); | |
| 3608 | list.appendAssumeCapacity(buf); | |
| 3609 | 3609 | } |
| 3610 | 3610 | |
| 3611 | 3611 | /// This function is temporally single-threaded. |
src/fmt.zig+2-2| ... | ... | @@ -348,10 +348,10 @@ fn fmtPathFile( |
| 348 | 348 | try fmt.stdout_writer.interface.print("{s}\n", .{file_path}); |
| 349 | 349 | fmt.any_error = true; |
| 350 | 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 | 352 | defer af.deinit(); |
| 353 | 353 | |
| 354 | try af.file.writeAll(fmt.out_buffer.getWritten()); | |
| 354 | try af.file_writer.interface.writeAll(fmt.out_buffer.getWritten()); | |
| 355 | 355 | try af.finish(); |
| 356 | 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 | 612 | }; |
| 613 | 613 | const emit = self.base.emit; |
| 614 | 614 | invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) { |
| 615 | error.OutOfMemory => return error.OutOfMemory, | |
| 616 | 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 | 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 | 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 | 4630 | return cleanExit(); |
| 4629 | 4631 | } |
| 4630 | 4632 | } |