diff options
| -rw-r--r-- | lib/std/fs/file.zig | 2 | ||||
| -rw-r--r-- | lib/std/io/test.zig | 10 | ||||
| -rw-r--r-- | lib/std/os.zig | 24 | ||||
| -rw-r--r-- | lib/std/os/windows/bits.zig | 4 | ||||
| -rw-r--r-- | lib/std/os/windows/ntdll.zig | 7 |
5 files changed, 40 insertions, 7 deletions
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index c3809cd510..c4991a81ff 100644 --- a/lib/std/fs/file.zig +++ b/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); } diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 9615377070..d8ee9612ea 100644 --- a/lib/std/io/test.zig +++ b/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" { diff --git a/lib/std/os.zig b/lib/std/os.zig index 6614453a38..2c18a13250 100644 --- a/lib/std/os.zig +++ b/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), } } diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 41466234ed..1e49b903cb 100644 --- a/lib/std/os/windows/bits.zig +++ b/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, }; diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 49e60803bc..7ba58b2392 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/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, |
