Commit de53537f10
lib/std/fs/file.zig
@@ -102,7 +102,7 @@ pub const File = struct {
pub const SetEndPosError = os.TruncateError;
/// Shrinks or expands the file.
- /// The file offset after this call is undefined.
+ /// The file offset after this call is left unchanged.
pub fn setEndPos(self: File, length: u64) SetEndPosError!void {
try os.ftruncate(self.handle, length);
}
lib/std/io/test.zig
@@ -1,5 +1,5 @@
-const builtin = @import("builtin");
-const std = @import("../std.zig");
+const std = @import("std");
+const builtin = std.builtin;
const io = std.io;
const meta = std.meta;
const trait = std.trait;
@@ -133,13 +133,19 @@ test "setEndPos" {
fs.cwd().deleteFile(tmp_file_name) catch {};
}
+ // Verify that the file size changes and the file offset is not moved
std.testing.expect((try file.getEndPos()) == 0);
+ std.testing.expect((try file.getPos()) == 0);
try file.setEndPos(8192);
std.testing.expect((try file.getEndPos()) == 8192);
+ std.testing.expect((try file.getPos()) == 0);
+ try file.seekTo(100);
try file.setEndPos(4096);
std.testing.expect((try file.getEndPos()) == 4096);
+ std.testing.expect((try file.getPos()) == 100);
try file.setEndPos(0);
std.testing.expect((try file.getEndPos()) == 0);
+ std.testing.expect((try file.getPos()) == 100);
}
test "updateTimes" {
lib/std/os/windows/bits.zig
@@ -225,6 +225,10 @@ pub const FILE_POSITION_INFORMATION = extern struct {
CurrentByteOffset: LARGE_INTEGER,
};
+pub const FILE_END_OF_FILE_INFORMATION = extern struct {
+ EndOfFile: LARGE_INTEGER,
+};
+
pub const FILE_MODE_INFORMATION = extern struct {
Mode: ULONG,
};
lib/std/os/windows/ntdll.zig
@@ -16,6 +16,13 @@ pub extern "NtDll" fn NtQueryInformationFile(
Length: ULONG,
FileInformationClass: FILE_INFORMATION_CLASS,
) callconv(.Stdcall) NTSTATUS;
+pub extern "NtDll" fn NtSetInformationFile(
+ FileHandle: HANDLE,
+ IoStatusBlock: *IO_STATUS_BLOCK,
+ FileInformation: PVOID,
+ Length: ULONG,
+ FileInformationClass: FILE_INFORMATION_CLASS,
+) callconv(.Stdcall) NTSTATUS;
pub extern "NtDll" fn NtQueryAttributesFile(
ObjectAttributes: *OBJECT_ATTRIBUTES,
lib/std/os.zig
@@ -447,10 +447,25 @@ pub const TruncateError = error{
pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
if (std.Target.current.os.tag == .windows) {
- try windows.SetFilePointerEx_BEGIN(fd, length);
+ var io_status_block: windows.IO_STATUS_BLOCK = undefined;
+ var eof_info = windows.FILE_END_OF_FILE_INFORMATION{
+ .EndOfFile = @bitCast(windows.LARGE_INTEGER, length),
+ };
+
+ const rc = windows.ntdll.NtSetInformationFile(
+ fd,
+ &io_status_block,
+ &eof_info,
+ @sizeOf(windows.FILE_END_OF_FILE_INFORMATION),
+ .FileEndOfFileInformation,
+ );
- if (windows.kernel32.SetEndOfFile(fd) == 0)
- return TruncateError.Unexpected;
+ switch (rc) {
+ .SUCCESS => {},
+ .INVALID_HANDLE => unreachable, // Handle not open for writing
+ .ACCESS_DENIED => return error.CannotTruncate,
+ else => return windows.unexpectedStatus(rc),
+ }
return;
}
@@ -471,7 +486,8 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
EIO => return error.InputOutput,
EPERM => return error.CannotTruncate,
ETXTBSY => return error.FileBusy,
- EBADF, EINVAL => unreachable,
+ EBADF => unreachable, // Handle not open for writing
+ EINVAL => unreachable, // Handle not open for writing
else => |err| return unexpectedErrno(err),
}
}