| author | |
| committer | |
| log | 1ed845e1f6fabdde8795513de2d06bc9b573779c |
| tree | c2776003424d1bc483312b0f1c3202d6c5edf8d9 |
| parent | 16f8af1b9a7a287ac6fdefec5949725c55cbe179 |
11 files changed, 89 insertions(+), 73 deletions(-)
lib/compiler/objcopy.zig+2-1| ... | ... | @@ -676,8 +676,9 @@ fn containsValidAddressRange(segments: []*BinaryElfSegment) bool { |
| 676 | 676 | } |
| 677 | 677 | |
| 678 | 678 | fn padFile(out: *File.Writer, opt_size: ?u64) !void { |
| 679 | const io = out.io; | |
| 679 | 680 | const size = opt_size orelse return; |
| 680 | try out.file.setEndPos(size); | |
| 681 | try out.file.setLength(io, size); | |
| 681 | 682 | } |
| 682 | 683 | |
| 683 | 684 | test "HexWriter.Record.Address has correct payload and checksum" { |
lib/std/Io/test.zig+60-8| ... | ... | @@ -3,16 +3,17 @@ const native_endian = builtin.cpu.arch.endian(); |
| 3 | 3 | |
| 4 | 4 | const std = @import("std"); |
| 5 | 5 | const Io = std.Io; |
| 6 | const testing = std.testing; | |
| 7 | const expect = std.testing.expect; | |
| 8 | const expectEqual = std.testing.expectEqual; | |
| 9 | const expectError = std.testing.expectError; | |
| 10 | 6 | const DefaultPrng = std.Random.DefaultPrng; |
| 11 | 7 | const mem = std.mem; |
| 12 | 8 | const fs = std.fs; |
| 13 | 9 | const File = std.Io.File; |
| 14 | 10 | const assert = std.debug.assert; |
| 15 | 11 | |
| 12 | const testing = std.testing; | |
| 13 | const expect = std.testing.expect; | |
| 14 | const expectEqual = std.testing.expectEqual; | |
| 15 | const expectError = std.testing.expectError; | |
| 16 | const expectEqualStrings = std.testing.expectEqualStrings; | |
| 16 | 17 | const tmpDir = std.testing.tmpDir; |
| 17 | 18 | |
| 18 | 19 | test "write a file, read it, then delete it" { |
| ... | ... | @@ -89,7 +90,7 @@ test "File seek ops" { |
| 89 | 90 | try expect((try file.getPos()) == 1234); |
| 90 | 91 | } |
| 91 | 92 | |
| 92 | test "setEndPos" { | |
| 93 | test "setLength" { | |
| 93 | 94 | const io = testing.io; |
| 94 | 95 | |
| 95 | 96 | var tmp = tmpDir(.{}); |
| ... | ... | @@ -102,18 +103,69 @@ test "setEndPos" { |
| 102 | 103 | // Verify that the file size changes and the file offset is not moved |
| 103 | 104 | try expect((try file.length(io)) == 0); |
| 104 | 105 | try expect((try file.getPos()) == 0); |
| 105 | try file.setEndPos(8192); | |
| 106 | try file.setLength(io, 8192); | |
| 106 | 107 | try expect((try file.length(io)) == 8192); |
| 107 | 108 | try expect((try file.getPos()) == 0); |
| 108 | 109 | try file.seekTo(100); |
| 109 | try file.setEndPos(4096); | |
| 110 | try file.setLength(io, 4096); | |
| 110 | 111 | try expect((try file.length(io)) == 4096); |
| 111 | 112 | try expect((try file.getPos()) == 100); |
| 112 | try file.setEndPos(0); | |
| 113 | try file.setLength(io, 0); | |
| 113 | 114 | try expect((try file.length(io)) == 0); |
| 114 | 115 | try expect((try file.getPos()) == 100); |
| 115 | 116 | } |
| 116 | 117 | |
| 118 | test "legacy setLength" { | |
| 119 | // https://github.com/ziglang/zig/issues/20747 (open fd does not have write permission) | |
| 120 | if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest; | |
| 121 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23806 | |
| 122 | ||
| 123 | const io = testing.io; | |
| 124 | ||
| 125 | var tmp = tmpDir(.{}); | |
| 126 | defer tmp.cleanup(); | |
| 127 | ||
| 128 | const file_name = "afile.txt"; | |
| 129 | try tmp.dir.writeFile(io, .{ .sub_path = file_name, .data = "ninebytes" }); | |
| 130 | const f = try tmp.dir.openFile(io, file_name, .{ .mode = .read_write }); | |
| 131 | defer f.close(io); | |
| 132 | ||
| 133 | const initial_size = try f.length(io); | |
| 134 | var buffer: [32]u8 = undefined; | |
| 135 | var reader = f.reader(io, &.{}); | |
| 136 | ||
| 137 | { | |
| 138 | try f.setLength(io, initial_size); | |
| 139 | try expectEqual(initial_size, try f.length(io)); | |
| 140 | try reader.seekTo(0); | |
| 141 | try expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); | |
| 142 | try expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); | |
| 143 | } | |
| 144 | ||
| 145 | { | |
| 146 | const larger = initial_size + 4; | |
| 147 | try f.setLength(io, larger); | |
| 148 | try expectEqual(larger, try f.length(io)); | |
| 149 | try reader.seekTo(0); | |
| 150 | try expectEqual(larger, try reader.interface.readSliceShort(&buffer)); | |
| 151 | try expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); | |
| 152 | } | |
| 153 | ||
| 154 | { | |
| 155 | const smaller = initial_size - 5; | |
| 156 | try f.setLength(io, smaller); | |
| 157 | try expectEqual(smaller, try f.length(io)); | |
| 158 | try reader.seekTo(0); | |
| 159 | try expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); | |
| 160 | try expectEqualStrings("nine", buffer[0..@intCast(smaller)]); | |
| 161 | } | |
| 162 | ||
| 163 | try f.setLength(io, 0); | |
| 164 | try expectEqual(0, try f.length(io)); | |
| 165 | try reader.seekTo(0); | |
| 166 | try expectEqual(0, try reader.interface.readSliceShort(&buffer)); | |
| 167 | } | |
| 168 | ||
| 117 | 169 | test "setTimestamps" { |
| 118 | 170 | const io = testing.io; |
| 119 | 171 |
lib/std/fs/test.zig-51| ... | ... | @@ -1451,57 +1451,6 @@ test "pwritev, preadv" { |
| 1451 | 1451 | try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1452 | 1452 | } |
| 1453 | 1453 | |
| 1454 | test "setEndPos" { | |
| 1455 | // https://github.com/ziglang/zig/issues/20747 (open fd does not have write permission) | |
| 1456 | if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; | |
| 1457 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23806 | |
| 1458 | ||
| 1459 | const io = testing.io; | |
| 1460 | ||
| 1461 | var tmp = tmpDir(.{}); | |
| 1462 | defer tmp.cleanup(); | |
| 1463 | ||
| 1464 | const file_name = "afile.txt"; | |
| 1465 | try tmp.dir.writeFile(io, .{ .sub_path = file_name, .data = "ninebytes" }); | |
| 1466 | const f = try tmp.dir.openFile(io, file_name, .{ .mode = .read_write }); | |
| 1467 | defer f.close(io); | |
| 1468 | ||
| 1469 | const initial_size = try f.length(io); | |
| 1470 | var buffer: [32]u8 = undefined; | |
| 1471 | var reader = f.reader(io, &.{}); | |
| 1472 | ||
| 1473 | { | |
| 1474 | try f.setEndPos(initial_size); | |
| 1475 | try expectEqual(initial_size, try f.length(io)); | |
| 1476 | try reader.seekTo(0); | |
| 1477 | try expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); | |
| 1478 | try expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); | |
| 1479 | } | |
| 1480 | ||
| 1481 | { | |
| 1482 | const larger = initial_size + 4; | |
| 1483 | try f.setEndPos(larger); | |
| 1484 | try expectEqual(larger, try f.length(io)); | |
| 1485 | try reader.seekTo(0); | |
| 1486 | try expectEqual(larger, try reader.interface.readSliceShort(&buffer)); | |
| 1487 | try expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); | |
| 1488 | } | |
| 1489 | ||
| 1490 | { | |
| 1491 | const smaller = initial_size - 5; | |
| 1492 | try f.setEndPos(smaller); | |
| 1493 | try expectEqual(smaller, try f.length(io)); | |
| 1494 | try reader.seekTo(0); | |
| 1495 | try expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); | |
| 1496 | try expectEqualStrings("nine", buffer[0..@intCast(smaller)]); | |
| 1497 | } | |
| 1498 | ||
| 1499 | try f.setEndPos(0); | |
| 1500 | try expectEqual(0, try f.length(io)); | |
| 1501 | try reader.seekTo(0); | |
| 1502 | try expectEqual(0, try reader.interface.readSliceShort(&buffer)); | |
| 1503 | } | |
| 1504 | ||
| 1505 | 1454 | test "access file" { |
| 1506 | 1455 | try testWithAllSupportedPathTypes(struct { |
| 1507 | 1456 | fn impl(ctx: *TestContext) !void { |
src/Zcu/PerThread.zig+1-1| ... | ... | @@ -245,7 +245,7 @@ pub fn updateFile( |
| 245 | 245 | |
| 246 | 246 | if (need_update) { |
| 247 | 247 | // The cache is definitely stale so delete the contents to avoid an underwrite later. |
| 248 | cache_file.setEndPos(0) catch |err| switch (err) { | |
| 248 | cache_file.setLength(io, 0) catch |err| switch (err) { | |
| 249 | 249 | error.FileTooBig => unreachable, // 0 is not too big |
| 250 | 250 | else => |e| return e, |
| 251 | 251 | }; |
src/link/C.zig+2-2| ... | ... | @@ -509,7 +509,7 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P |
| 509 | 509 | }, self.getString(av_block.code)); |
| 510 | 510 | |
| 511 | 511 | const file = self.base.file.?; |
| 512 | file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)}); | |
| 512 | file.setLength(io, f.file_size) catch |err| return diags.fail("failed to allocate file: {t}", .{err}); | |
| 513 | 513 | var fw = file.writer(io, &.{}); |
| 514 | 514 | var w = &fw.interface; |
| 515 | 515 | w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { |
| ... | ... | @@ -800,7 +800,7 @@ pub fn flushEmitH(zcu: *Zcu) !void { |
| 800 | 800 | }); |
| 801 | 801 | defer file.close(io); |
| 802 | 802 | |
| 803 | try file.setEndPos(file_size); | |
| 803 | try file.setLength(io, file_size); | |
| 804 | 804 | try file.pwritevAll(all_buffers.items, 0); |
| 805 | 805 | } |
| 806 | 806 |
src/link/Elf.zig+9-4| ... | ... | @@ -487,6 +487,8 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo |
| 487 | 487 | |
| 488 | 488 | /// Returns end pos of collision, if any. |
| 489 | 489 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 490 | const comp = self.base.comp; | |
| 491 | const io = comp.io; | |
| 490 | 492 | const small_ptr = self.ptr_width == .p32; |
| 491 | 493 | const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); |
| 492 | 494 | if (start < ehdr_size) |
| ... | ... | @@ -526,7 +528,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 526 | 528 | } |
| 527 | 529 | } |
| 528 | 530 | |
| 529 | if (at_end) try self.base.file.?.setEndPos(end); | |
| 531 | if (at_end) try self.base.file.?.setLength(io, end); | |
| 530 | 532 | return null; |
| 531 | 533 | } |
| 532 | 534 | |
| ... | ... | @@ -556,6 +558,8 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { |
| 556 | 558 | } |
| 557 | 559 | |
| 558 | 560 | pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { |
| 561 | const comp = self.base.comp; | |
| 562 | const io = comp.io; | |
| 559 | 563 | const shdr = &self.sections.items(.shdr)[shdr_index]; |
| 560 | 564 | |
| 561 | 565 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| ... | ... | @@ -589,7 +593,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: |
| 589 | 593 | |
| 590 | 594 | shdr.sh_offset = new_offset; |
| 591 | 595 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| 592 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | |
| 596 | try self.base.file.?.setLength(io, shdr.sh_offset + needed_size); | |
| 593 | 597 | } |
| 594 | 598 | } |
| 595 | 599 | |
| ... | ... | @@ -4446,10 +4450,11 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu |
| 4446 | 4450 | }; |
| 4447 | 4451 | } |
| 4448 | 4452 | |
| 4449 | pub fn setEndPos(elf_file: *Elf, length: u64) error{LinkFailure}!void { | |
| 4453 | pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void { | |
| 4450 | 4454 | const comp = elf_file.base.comp; |
| 4455 | const io = comp.i; | |
| 4451 | 4456 | const diags = &comp.link_diags; |
| 4452 | elf_file.base.file.?.setEndPos(length) catch |err| { | |
| 4457 | elf_file.base.file.?.setLength(io, length) catch |err| { | |
| 4453 | 4458 | return diags.fail("failed to set file end pos: {s}", .{@errorName(err)}); |
| 4454 | 4459 | }; |
| 4455 | 4460 | } |
src/link/Elf/relocatable.zig+2-1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 2 | 2 | const gpa = comp.gpa; |
| 3 | const io = comp.io; | |
| 3 | 4 | const diags = &comp.link_diags; |
| 4 | 5 | |
| 5 | 6 | if (diags.hasErrors()) return error.LinkFailure; |
| ... | ... | @@ -125,7 +126,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 125 | 126 | |
| 126 | 127 | assert(writer.buffered().len == total_size); |
| 127 | 128 | |
| 128 | try elf_file.base.file.?.setEndPos(total_size); | |
| 129 | try elf_file.base.file.?.setLength(io, total_size); | |
| 129 | 130 | try elf_file.base.file.?.pwriteAll(writer.buffered(), 0); |
| 130 | 131 | |
| 131 | 132 | if (diags.hasErrors()) return error.LinkFailure; |
src/link/MachO/DebugSymbols.zig+4-2| ... | ... | @@ -125,6 +125,7 @@ pub fn growSection( |
| 125 | 125 | requires_file_copy: bool, |
| 126 | 126 | macho_file: *MachO, |
| 127 | 127 | ) !void { |
| 128 | const io = self.io; | |
| 128 | 129 | const sect = self.getSectionPtr(sect_index); |
| 129 | 130 | |
| 130 | 131 | const allocated_size = self.allocatedSize(sect.offset); |
| ... | ... | @@ -152,7 +153,7 @@ pub fn growSection( |
| 152 | 153 | |
| 153 | 154 | sect.offset = @intCast(new_offset); |
| 154 | 155 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { |
| 155 | try self.file.?.setEndPos(sect.offset + needed_size); | |
| 156 | try self.file.?.setLength(io, sect.offset + needed_size); | |
| 156 | 157 | } |
| 157 | 158 | |
| 158 | 159 | sect.size = needed_size; |
| ... | ... | @@ -176,6 +177,7 @@ pub fn markDirty(self: *DebugSymbols, sect_index: u8, macho_file: *MachO) void { |
| 176 | 177 | } |
| 177 | 178 | |
| 178 | 179 | fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 { |
| 180 | const io = self.io; | |
| 179 | 181 | var at_end = true; |
| 180 | 182 | const end = start + padToIdeal(size); |
| 181 | 183 | |
| ... | ... | @@ -188,7 +190,7 @@ fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 { |
| 188 | 190 | } |
| 189 | 191 | } |
| 190 | 192 | |
| 191 | if (at_end) try self.file.?.setEndPos(end); | |
| 193 | if (at_end) try self.file.?.setLength(io, end); | |
| 192 | 194 | return null; |
| 193 | 195 | } |
| 194 | 196 |
src/link/MachO/relocatable.zig+2-1| ... | ... | @@ -80,6 +80,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat |
| 80 | 80 | |
| 81 | 81 | pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void { |
| 82 | 82 | const gpa = comp.gpa; |
| 83 | const io = comp.io; | |
| 83 | 84 | const diags = &macho_file.base.comp.link_diags; |
| 84 | 85 | |
| 85 | 86 | var positionals = std.array_list.Managed(link.Input).init(gpa); |
| ... | ... | @@ -230,7 +231,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 230 | 231 | |
| 231 | 232 | assert(writer.end == total_size); |
| 232 | 233 | |
| 233 | try macho_file.setEndPos(total_size); | |
| 234 | try macho_file.setLength(io, total_size); | |
| 234 | 235 | try macho_file.pwriteAll(writer.buffered(), 0); |
| 235 | 236 | |
| 236 | 237 | if (diags.hasErrors()) return error.LinkFailure; |
src/link/MappedFile.zig+5| ... | ... | @@ -35,6 +35,11 @@ pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.Length |
| 35 | 35 | IsDir, |
| 36 | 36 | Unseekable, |
| 37 | 37 | NoSpaceLeft, |
| 38 | ||
| 39 | InputOutput, | |
| 40 | FileTooBig, | |
| 41 | FileBusy, | |
| 42 | NonResizable, | |
| 38 | 43 | }; |
| 39 | 44 | |
| 40 | 45 | pub fn init(file: std.Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile { |
src/link/Wasm.zig+2-2| ... | ... | @@ -3018,12 +3018,12 @@ pub fn createEmpty( |
| 3018 | 3018 | fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void { |
| 3019 | 3019 | const diags = &wasm.base.comp.link_diags; |
| 3020 | 3020 | const obj = link.openObject(path, false, false) catch |err| { |
| 3021 | switch (diags.failParse(path, "failed to open object: {s}", .{@errorName(err)})) { | |
| 3021 | switch (diags.failParse(path, "failed to open object: {t}", .{err})) { | |
| 3022 | 3022 | error.LinkFailure => return, |
| 3023 | 3023 | } |
| 3024 | 3024 | }; |
| 3025 | 3025 | wasm.parseObject(obj) catch |err| { |
| 3026 | switch (diags.failParse(path, "failed to parse object: {s}", .{@errorName(err)})) { | |
| 3026 | switch (diags.failParse(path, "failed to parse object: {t}", .{err})) { | |
| 3027 | 3027 | error.LinkFailure => return, |
| 3028 | 3028 | } |
| 3029 | 3029 | }; |