mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
Add NtDll-based ftruncate implementation
This commit is contained in:
parent
bd0b51477a
commit
de53537f10
@ -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);
|
||||
}
|
||||
|
||||
@ -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" {
|
||||
|
||||
@ -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),
|
||||
};
|
||||
|
||||
if (windows.kernel32.SetEndOfFile(fd) == 0)
|
||||
return TruncateError.Unexpected;
|
||||
const rc = windows.ntdll.NtSetInformationFile(
|
||||
fd,
|
||||
&io_status_block,
|
||||
&eof_info,
|
||||
@sizeOf(windows.FILE_END_OF_FILE_INFORMATION),
|
||||
.FileEndOfFileInformation,
|
||||
);
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user