authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-11 23:41:57-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:09-08:00
log1ed845e1f6fabdde8795513de2d06bc9b573779c
treec2776003424d1bc483312b0f1c3202d6c5edf8d9
parent16f8af1b9a7a287ac6fdefec5949725c55cbe179

update occurences of setEndPos to setLength


11 files changed, 89 insertions(+), 73 deletions(-)

lib/compiler/objcopy.zig+2-1
...@@ -676,8 +676,9 @@ fn containsValidAddressRange(segments: []*BinaryElfSegment) bool {...@@ -676,8 +676,9 @@ fn containsValidAddressRange(segments: []*BinaryElfSegment) bool {
676}676}
677677
678fn padFile(out: *File.Writer, opt_size: ?u64) !void {678fn padFile(out: *File.Writer, opt_size: ?u64) !void {
679 const io = out.io;
679 const size = opt_size orelse return;680 const size = opt_size orelse return;
680 try out.file.setEndPos(size);681 try out.file.setLength(io, size);
681}682}
682683
683test "HexWriter.Record.Address has correct payload and checksum" {684test "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,16 +3,17 @@ const native_endian = builtin.cpu.arch.endian();
33
4const std = @import("std");4const std = @import("std");
5const Io = std.Io;5const Io = std.Io;
6const testing = std.testing;
7const expect = std.testing.expect;
8const expectEqual = std.testing.expectEqual;
9const expectError = std.testing.expectError;
10const DefaultPrng = std.Random.DefaultPrng;6const DefaultPrng = std.Random.DefaultPrng;
11const mem = std.mem;7const mem = std.mem;
12const fs = std.fs;8const fs = std.fs;
13const File = std.Io.File;9const File = std.Io.File;
14const assert = std.debug.assert;10const assert = std.debug.assert;
1511
12const testing = std.testing;
13const expect = std.testing.expect;
14const expectEqual = std.testing.expectEqual;
15const expectError = std.testing.expectError;
16const expectEqualStrings = std.testing.expectEqualStrings;
16const tmpDir = std.testing.tmpDir;17const tmpDir = std.testing.tmpDir;
1718
18test "write a file, read it, then delete it" {19test "write a file, read it, then delete it" {
...@@ -89,7 +90,7 @@ test "File seek ops" {...@@ -89,7 +90,7 @@ test "File seek ops" {
89 try expect((try file.getPos()) == 1234);90 try expect((try file.getPos()) == 1234);
90}91}
9192
92test "setEndPos" {93test "setLength" {
93 const io = testing.io;94 const io = testing.io;
9495
95 var tmp = tmpDir(.{});96 var tmp = tmpDir(.{});
...@@ -102,18 +103,69 @@ test "setEndPos" {...@@ -102,18 +103,69 @@ test "setEndPos" {
102 // Verify that the file size changes and the file offset is not moved103 // Verify that the file size changes and the file offset is not moved
103 try expect((try file.length(io)) == 0);104 try expect((try file.length(io)) == 0);
104 try expect((try file.getPos()) == 0);105 try expect((try file.getPos()) == 0);
105 try file.setEndPos(8192);106 try file.setLength(io, 8192);
106 try expect((try file.length(io)) == 8192);107 try expect((try file.length(io)) == 8192);
107 try expect((try file.getPos()) == 0);108 try expect((try file.getPos()) == 0);
108 try file.seekTo(100);109 try file.seekTo(100);
109 try file.setEndPos(4096);110 try file.setLength(io, 4096);
110 try expect((try file.length(io)) == 4096);111 try expect((try file.length(io)) == 4096);
111 try expect((try file.getPos()) == 100);112 try expect((try file.getPos()) == 100);
112 try file.setEndPos(0);113 try file.setLength(io, 0);
113 try expect((try file.length(io)) == 0);114 try expect((try file.length(io)) == 0);
114 try expect((try file.getPos()) == 100);115 try expect((try file.getPos()) == 100);
115}116}
116117
118test "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
117test "setTimestamps" {169test "setTimestamps" {
118 const io = testing.io;170 const io = testing.io;
119171
lib/std/fs/test.zig-51
...@@ -1451,57 +1451,6 @@ test "pwritev, preadv" {...@@ -1451,57 +1451,6 @@ test "pwritev, preadv" {
1451 try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1));1451 try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1));
1452}1452}
14531453
1454test "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
1505test "access file" {1454test "access file" {
1506 try testWithAllSupportedPathTypes(struct {1455 try testWithAllSupportedPathTypes(struct {
1507 fn impl(ctx: *TestContext) !void {1456 fn impl(ctx: *TestContext) !void {
src/Zcu/PerThread.zig+1-1
...@@ -245,7 +245,7 @@ pub fn updateFile(...@@ -245,7 +245,7 @@ pub fn updateFile(
245245
246 if (need_update) {246 if (need_update) {
247 // The cache is definitely stale so delete the contents to avoid an underwrite later.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 error.FileTooBig => unreachable, // 0 is not too big249 error.FileTooBig => unreachable, // 0 is not too big
250 else => |e| return e,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,7 +509,7 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
509 }, self.getString(av_block.code));509 }, self.getString(av_block.code));
510510
511 const file = self.base.file.?;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 var fw = file.writer(io, &.{});513 var fw = file.writer(io, &.{});
514 var w = &fw.interface;514 var w = &fw.interface;
515 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {515 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {
...@@ -800,7 +800,7 @@ pub fn flushEmitH(zcu: *Zcu) !void {...@@ -800,7 +800,7 @@ pub fn flushEmitH(zcu: *Zcu) !void {
800 });800 });
801 defer file.close(io);801 defer file.close(io);
802802
803 try file.setEndPos(file_size);803 try file.setLength(io, file_size);
804 try file.pwritevAll(all_buffers.items, 0);804 try file.pwritevAll(all_buffers.items, 0);
805}805}
806806
src/link/Elf.zig+9-4
...@@ -487,6 +487,8 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo...@@ -487,6 +487,8 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo
487487
488/// Returns end pos of collision, if any.488/// Returns end pos of collision, if any.
489fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {489fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
490 const comp = self.base.comp;
491 const io = comp.io;
490 const small_ptr = self.ptr_width == .p32;492 const small_ptr = self.ptr_width == .p32;
491 const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr);493 const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr);
492 if (start < ehdr_size)494 if (start < ehdr_size)
...@@ -526,7 +528,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {...@@ -526,7 +528,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
526 }528 }
527 }529 }
528530
529 if (at_end) try self.base.file.?.setEndPos(end);531 if (at_end) try self.base.file.?.setLength(io, end);
530 return null;532 return null;
531}533}
532534
...@@ -556,6 +558,8 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {...@@ -556,6 +558,8 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
556}558}
557559
558pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {560pub 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 const shdr = &self.sections.items(.shdr)[shdr_index];563 const shdr = &self.sections.items(.shdr)[shdr_index];
560564
561 if (shdr.sh_type != elf.SHT_NOBITS) {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,7 +593,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment:
589593
590 shdr.sh_offset = new_offset;594 shdr.sh_offset = new_offset;
591 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {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 }
595599
...@@ -4446,10 +4450,11 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu...@@ -4446,10 +4450,11 @@ pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{LinkFailu
4446 };4450 };
4447}4451}
44484452
4449pub fn setEndPos(elf_file: *Elf, length: u64) error{LinkFailure}!void {4453pub fn setLength(elf_file: *Elf, length: u64) error{LinkFailure}!void {
4450 const comp = elf_file.base.comp;4454 const comp = elf_file.base.comp;
4455 const io = comp.i;
4451 const diags = &comp.link_diags;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 return diags.fail("failed to set file end pos: {s}", .{@errorName(err)});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,5 +1,6 @@
1pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {1pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
2 const gpa = comp.gpa;2 const gpa = comp.gpa;
3 const io = comp.io;
3 const diags = &comp.link_diags;4 const diags = &comp.link_diags;
45
5 if (diags.hasErrors()) return error.LinkFailure;6 if (diags.hasErrors()) return error.LinkFailure;
...@@ -125,7 +126,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -125,7 +126,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
125126
126 assert(writer.buffered().len == total_size);127 assert(writer.buffered().len == total_size);
127128
128 try elf_file.base.file.?.setEndPos(total_size);129 try elf_file.base.file.?.setLength(io, total_size);
129 try elf_file.base.file.?.pwriteAll(writer.buffered(), 0);130 try elf_file.base.file.?.pwriteAll(writer.buffered(), 0);
130131
131 if (diags.hasErrors()) return error.LinkFailure;132 if (diags.hasErrors()) return error.LinkFailure;
src/link/MachO/DebugSymbols.zig+4-2
...@@ -125,6 +125,7 @@ pub fn growSection(...@@ -125,6 +125,7 @@ pub fn growSection(
125 requires_file_copy: bool,125 requires_file_copy: bool,
126 macho_file: *MachO,126 macho_file: *MachO,
127) !void {127) !void {
128 const io = self.io;
128 const sect = self.getSectionPtr(sect_index);129 const sect = self.getSectionPtr(sect_index);
129130
130 const allocated_size = self.allocatedSize(sect.offset);131 const allocated_size = self.allocatedSize(sect.offset);
...@@ -152,7 +153,7 @@ pub fn growSection(...@@ -152,7 +153,7 @@ pub fn growSection(
152153
153 sect.offset = @intCast(new_offset);154 sect.offset = @intCast(new_offset);
154 } else if (sect.offset + allocated_size == std.math.maxInt(u64)) {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 }
157158
158 sect.size = needed_size;159 sect.size = needed_size;
...@@ -176,6 +177,7 @@ pub fn markDirty(self: *DebugSymbols, sect_index: u8, macho_file: *MachO) void {...@@ -176,6 +177,7 @@ pub fn markDirty(self: *DebugSymbols, sect_index: u8, macho_file: *MachO) void {
176}177}
177178
178fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 {179fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 {
180 const io = self.io;
179 var at_end = true;181 var at_end = true;
180 const end = start + padToIdeal(size);182 const end = start + padToIdeal(size);
181183
...@@ -188,7 +190,7 @@ fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 {...@@ -188,7 +190,7 @@ fn detectAllocCollision(self: *DebugSymbols, start: u64, size: u64) !?u64 {
188 }190 }
189 }191 }
190192
191 if (at_end) try self.file.?.setEndPos(end);193 if (at_end) try self.file.?.setLength(io, end);
192 return null;194 return null;
193}195}
194196
src/link/MachO/relocatable.zig+2-1
...@@ -80,6 +80,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -80,6 +80,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
8080
81pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {81pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Path) link.File.FlushError!void {
82 const gpa = comp.gpa;82 const gpa = comp.gpa;
83 const io = comp.io;
83 const diags = &macho_file.base.comp.link_diags;84 const diags = &macho_file.base.comp.link_diags;
8485
85 var positionals = std.array_list.Managed(link.Input).init(gpa);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,7 +231,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
230231
231 assert(writer.end == total_size);232 assert(writer.end == total_size);
232233
233 try macho_file.setEndPos(total_size);234 try macho_file.setLength(io, total_size);
234 try macho_file.pwriteAll(writer.buffered(), 0);235 try macho_file.pwriteAll(writer.buffered(), 0);
235236
236 if (diags.hasErrors()) return error.LinkFailure;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,6 +35,11 @@ pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.Length
35 IsDir,35 IsDir,
36 Unseekable,36 Unseekable,
37 NoSpaceLeft,37 NoSpaceLeft,
38
39 InputOutput,
40 FileTooBig,
41 FileBusy,
42 NonResizable,
38};43};
3944
40pub fn init(file: std.Io.File, gpa: std.mem.Allocator, io: Io) !MappedFile {45pub 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,12 +3018,12 @@ pub fn createEmpty(
3018fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {3018fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
3019 const diags = &wasm.base.comp.link_diags;3019 const diags = &wasm.base.comp.link_diags;
3020 const obj = link.openObject(path, false, false) catch |err| {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 error.LinkFailure => return,3022 error.LinkFailure => return,
3023 }3023 }
3024 };3024 };
3025 wasm.parseObject(obj) catch |err| {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 error.LinkFailure => return,3027 error.LinkFailure => return,
3028 }3028 }
3029 };3029 };