authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-13 12:24:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-13 12:24:14-07:00
log5e986fef1fa5cf04f3547cc4f5a8c0f490ea1d3d
tree88119d0e1a5696bd2637673d5653bd6a84c7de77
parenta495628862109950e938c0bdb9d5eaf989280443

std.fs.File.Reader: fix seekBy

Tested locally: stage3/bin/zig build test -Dskip-release -Dskip-non-native closes #24495 closes #24498 closes #24713

2 files changed, 19 insertions(+), 6 deletions(-)

lib/std/fs/File.zig+3-6
...@@ -1247,12 +1247,10 @@ pub const Reader = struct {...@@ -1247,12 +1247,10 @@ pub const Reader = struct {
1247 };1247 };
1248 var remaining = std.math.cast(u64, offset) orelse return seek_err;1248 var remaining = std.math.cast(u64, offset) orelse return seek_err;
1249 while (remaining > 0) {1249 while (remaining > 0) {
1250 const n = discard(&r.interface, .limited64(remaining)) catch |err| {1250 remaining -= discard(&r.interface, .limited64(remaining)) catch |err| {
1251 r.seek_err = err;1251 r.seek_err = err;
1252 return err;1252 return err;
1253 };1253 };
1254 r.pos += n;
1255 remaining -= n;
1256 }1254 }
1257 r.interface.seek = 0;1255 r.interface.seek = 0;
1258 r.interface.end = 0;1256 r.interface.end = 0;
...@@ -1436,9 +1434,8 @@ pub const Reader = struct {...@@ -1436,9 +1434,8 @@ pub const Reader = struct {
1436 fallback: {1434 fallback: {
1437 if (r.size_err == null and r.seek_err == null) break :fallback;1435 if (r.size_err == null and r.seek_err == null) break :fallback;
1438 var trash_buffer: [128]u8 = undefined;1436 var trash_buffer: [128]u8 = undefined;
1439 const trash = &trash_buffer;
1440 if (is_windows) {1437 if (is_windows) {
1441 const n = windows.ReadFile(file.handle, trash, null) catch |err| {1438 const n = windows.ReadFile(file.handle, limit.slice(&trash_buffer), null) catch |err| {
1442 r.err = err;1439 r.err = err;
1443 return error.ReadFailed;1440 return error.ReadFailed;
1444 };1441 };
...@@ -1453,7 +1450,7 @@ pub const Reader = struct {...@@ -1453,7 +1450,7 @@ pub const Reader = struct {
1453 var iovecs_i: usize = 0;1450 var iovecs_i: usize = 0;
1454 var remaining = @intFromEnum(limit);1451 var remaining = @intFromEnum(limit);
1455 while (remaining > 0 and iovecs_i < iovecs.len) {1452 while (remaining > 0 and iovecs_i < iovecs.len) {
1456 iovecs[iovecs_i] = .{ .base = trash, .len = @min(trash.len, remaining) };1453 iovecs[iovecs_i] = .{ .base = &trash_buffer, .len = @min(trash_buffer.len, remaining) };
1457 remaining -= iovecs[iovecs_i].len;1454 remaining -= iovecs[iovecs_i].len;
1458 iovecs_i += 1;1455 iovecs_i += 1;
1459 }1456 }
lib/std/fs/test.zig+16
...@@ -2129,3 +2129,19 @@ test "seek keeping partial buffer" {...@@ -2129,3 +2129,19 @@ test "seek keeping partial buffer" {
21292129
2130 try testing.expectEqualStrings("6789", &buf);2130 try testing.expectEqualStrings("6789", &buf);
2131}2131}
2132
2133test "seekBy" {
2134 var tmp_dir = testing.tmpDir(.{});
2135 defer tmp_dir.cleanup();
2136
2137 try tmp_dir.dir.writeFile(.{ .sub_path = "blah.txt", .data = "let's test seekBy" });
2138 const f = try tmp_dir.dir.openFile("blah.txt", .{ .mode = .read_only });
2139 defer f.close();
2140 var reader = f.readerStreaming(&.{});
2141 try reader.seekBy(2);
2142
2143 var buffer: [20]u8 = undefined;
2144 const n = try reader.interface.readSliceShort(&buffer);
2145 try testing.expectEqual(15, n);
2146 try testing.expectEqualStrings("t's test seekBy", buffer[0..15]);
2147}