mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
std: fix File.Writer sendfile with buffered contents
* File.Writer.seekBy passed wrong offset to setPosAdjustingBuffer. * File.Writer.sendFile incorrectly used non-logical position. Related to 1d764c1fdf04829cec5974d82cec901825a80e49 Test case provided by: Co-authored-by: Kendall Condon <goon.pri.low@gmail.com>
This commit is contained in:
parent
acd6ffdf69
commit
5c0ac90721
@ -1242,7 +1242,7 @@ pub const Reader = struct {
|
|||||||
pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
|
pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
|
||||||
switch (r.mode) {
|
switch (r.mode) {
|
||||||
.positional, .positional_reading => {
|
.positional, .positional_reading => {
|
||||||
setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
|
setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
|
||||||
},
|
},
|
||||||
.streaming, .streaming_reading => {
|
.streaming, .streaming_reading => {
|
||||||
if (posix.SEEK == void) {
|
if (posix.SEEK == void) {
|
||||||
@ -1251,7 +1251,7 @@ pub const Reader = struct {
|
|||||||
}
|
}
|
||||||
const seek_err = r.seek_err orelse e: {
|
const seek_err = r.seek_err orelse e: {
|
||||||
if (posix.lseek_CUR(r.file.handle, offset)) |_| {
|
if (posix.lseek_CUR(r.file.handle, offset)) |_| {
|
||||||
setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
|
setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
|
||||||
return;
|
return;
|
||||||
} else |err| {
|
} else |err| {
|
||||||
r.seek_err = err;
|
r.seek_err = err;
|
||||||
@ -1275,16 +1275,16 @@ pub const Reader = struct {
|
|||||||
pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
|
pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
|
||||||
switch (r.mode) {
|
switch (r.mode) {
|
||||||
.positional, .positional_reading => {
|
.positional, .positional_reading => {
|
||||||
setPosAdjustingBuffer(r, offset);
|
setLogicalPos(r, offset);
|
||||||
},
|
},
|
||||||
.streaming, .streaming_reading => {
|
.streaming, .streaming_reading => {
|
||||||
if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - r.pos));
|
if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - logicalPos(r)));
|
||||||
if (r.seek_err) |err| return err;
|
if (r.seek_err) |err| return err;
|
||||||
posix.lseek_SET(r.file.handle, offset) catch |err| {
|
posix.lseek_SET(r.file.handle, offset) catch |err| {
|
||||||
r.seek_err = err;
|
r.seek_err = err;
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
setPosAdjustingBuffer(r, offset);
|
setLogicalPos(r, offset);
|
||||||
},
|
},
|
||||||
.failure => return r.seek_err.?,
|
.failure => return r.seek_err.?,
|
||||||
}
|
}
|
||||||
@ -1294,7 +1294,7 @@ pub const Reader = struct {
|
|||||||
return r.pos - r.interface.bufferedLen();
|
return r.pos - r.interface.bufferedLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
|
fn setLogicalPos(r: *Reader, offset: u64) void {
|
||||||
const logical_pos = logicalPos(r);
|
const logical_pos = logicalPos(r);
|
||||||
if (offset < logical_pos or offset >= r.pos) {
|
if (offset < logical_pos or offset >= r.pos) {
|
||||||
r.interface.seek = 0;
|
r.interface.seek = 0;
|
||||||
@ -1855,7 +1855,7 @@ pub const Writer = struct {
|
|||||||
return error.EndOfStream;
|
return error.EndOfStream;
|
||||||
}
|
}
|
||||||
const consumed = io_w.consume(@intCast(sbytes));
|
const consumed = io_w.consume(@intCast(sbytes));
|
||||||
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
|
file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed;
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1916,7 +1916,7 @@ pub const Writer = struct {
|
|||||||
return error.EndOfStream;
|
return error.EndOfStream;
|
||||||
}
|
}
|
||||||
const consumed = io_w.consume(@bitCast(len));
|
const consumed = io_w.consume(@bitCast(len));
|
||||||
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
|
file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed;
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2049,7 +2049,7 @@ pub const Writer = struct {
|
|||||||
reader_buffered: []const u8,
|
reader_buffered: []const u8,
|
||||||
) std.Io.Writer.FileError!usize {
|
) std.Io.Writer.FileError!usize {
|
||||||
const n = try drain(io_w, &.{reader_buffered}, 1);
|
const n = try drain(io_w, &.{reader_buffered}, 1);
|
||||||
file_reader.seekTo(file_reader.pos + n) catch return error.ReadFailed;
|
file_reader.seekBy(@intCast(n)) catch return error.ReadFailed;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2145,3 +2145,34 @@ test "seekBy" {
|
|||||||
try testing.expectEqual(15, n);
|
try testing.expectEqual(15, n);
|
||||||
try testing.expectEqualStrings("t's test seekBy", buffer[0..15]);
|
try testing.expectEqualStrings("t's test seekBy", buffer[0..15]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "File.Writer sendfile with buffered contents" {
|
||||||
|
var tmp_dir = testing.tmpDir(.{});
|
||||||
|
defer tmp_dir.cleanup();
|
||||||
|
|
||||||
|
{
|
||||||
|
try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" });
|
||||||
|
const in = try tmp_dir.dir.openFile("a", .{});
|
||||||
|
defer in.close();
|
||||||
|
const out = try tmp_dir.dir.createFile("b", .{});
|
||||||
|
defer out.close();
|
||||||
|
|
||||||
|
var in_buf: [2]u8 = undefined;
|
||||||
|
var in_r = in.reader(&in_buf);
|
||||||
|
_ = try in_r.getSize(); // Catch seeks past end by populating size
|
||||||
|
try in_r.interface.fill(2);
|
||||||
|
|
||||||
|
var out_buf: [1]u8 = undefined;
|
||||||
|
var out_w = out.writerStreaming(&out_buf);
|
||||||
|
try out_w.interface.writeByte('a');
|
||||||
|
try testing.expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited));
|
||||||
|
try out_w.interface.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
var check = try tmp_dir.dir.openFile("b", .{});
|
||||||
|
defer check.close();
|
||||||
|
var check_buf: [4]u8 = undefined;
|
||||||
|
var check_r = check.reader(&check_buf);
|
||||||
|
try testing.expectEqualStrings("abcd", try check_r.interface.take(4));
|
||||||
|
try testing.expectError(error.EndOfStream, check_r.interface.takeByte());
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user