aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-03-11 13:06:30 -0400
committerAndrew Kelley <andrew@ziglang.org>2020-03-11 13:06:30 -0400
commitd96b6c0d9f7a4fc6e7e28dd92d18e548f00885de (patch)
tree1c2774d9d9ffe279fa1ae330eec529dbdc9cb994 /lib/std/fs
parented13cffca4c42718cc7239faf7aab642ac67ef77 (diff)
downloadzig-d96b6c0d9f7a4fc6e7e28dd92d18e548f00885de.tar.gz
zig-d96b6c0d9f7a4fc6e7e28dd92d18e548f00885de.zip
fix footguns in File readAll functions
Diffstat (limited to 'lib/std/fs')
-rw-r--r--lib/std/fs/file.zig42
1 files changed, 33 insertions, 9 deletions
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 845e4bc75e..8362f94ca5 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -250,11 +250,16 @@ pub const File = struct {
}
}
- pub fn readAll(self: File, buffer: []u8) ReadError!void {
+ /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
+ /// means the file reached the end. Reaching the end of a file is not an error condition.
+ pub fn readAll(self: File, buffer: []u8) ReadError!usize {
var index: usize = 0;
- while (index < buffer.len) {
- index += try self.read(buffer[index..]);
+ while (index != buffer.len) {
+ const amt = try self.read(buffer[index..]);
+ if (amt == 0) break;
+ index += amt;
}
+ return index;
}
pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
@@ -265,11 +270,16 @@ pub const File = struct {
}
}
- pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!void {
+ /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
+ /// means the file reached the end. Reaching the end of a file is not an error condition.
+ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
var index: usize = 0;
- while (index < buffer.len) {
- index += try self.pread(buffer[index..], offset + index);
+ while (index != buffer.len) {
+ const amt = try self.pread(buffer[index..], offset + index);
+ if (amt == 0) break;
+ index += amt;
}
+ return index;
}
pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize {
@@ -280,19 +290,27 @@ pub const File = struct {
}
}
+ /// Returns the number of bytes read. If the number read is smaller than the total bytes
+ /// from all the buffers, it means the file reached the end. Reaching the end of a file
+ /// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
- pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!void {
+ pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
if (iovecs.len == 0) return;
var i: usize = 0;
+ var off: usize = 0;
while (true) {
var amt = try self.readv(iovecs[i..]);
+ var eof = amt == 0;
+ off += amt;
while (amt >= iovecs[i].iov_len) {
amt -= iovecs[i].iov_len;
i += 1;
- if (i >= iovecs.len) return;
+ if (i >= iovecs.len) return off;
+ eof = false;
}
+ if (eof) return off;
iovecs[i].iov_base += amt;
iovecs[i].iov_len -= amt;
}
@@ -306,6 +324,9 @@ pub const File = struct {
}
}
+ /// Returns the number of bytes read. If the number read is smaller than the total bytes
+ /// from all the buffers, it means the file reached the end. Reaching the end of a file
+ /// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void {
@@ -315,12 +336,15 @@ pub const File = struct {
var off: usize = 0;
while (true) {
var amt = try self.preadv(iovecs[i..], offset + off);
+ var eof = amt == 0;
off += amt;
while (amt >= iovecs[i].iov_len) {
amt -= iovecs[i].iov_len;
i += 1;
- if (i >= iovecs.len) return;
+ if (i >= iovecs.len) return off;
+ eof = false;
}
+ if (eof) return off;
iovecs[i].iov_base += amt;
iovecs[i].iov_len -= amt;
}