Commit 488f68069b
Changed files (3)
lib
std
fs
os
windows
lib/std/fs/file.zig
@@ -840,10 +840,37 @@ pub const File = struct {
/// TODO: integrate with async I/O
pub fn setLock(file: File, lock: Lock, non_blocking: bool) SetLockError!void {
if (is_windows) {
- @compileError("TODO implement fs.File.setLock for Windows");
+ const range_off: windows.LARGE_INTEGER = 0;
+ const range_len: windows.LARGE_INTEGER = 1;
+ const exclusive = switch (lock) {
+ .None => return windows.UnlockFile(
+ file.handle,
+ null,
+ &range_off,
+ &range_len,
+ null,
+ ) catch |err| switch (err) {
+ error.RangeNotLocked => return,
+ else => |e| return e,
+ },
+ .Shared => false,
+ .Exclusive => true,
+ };
+ return windows.LockFile(
+ file.handle,
+ null,
+ null,
+ null,
+ null,
+ &range_off,
+ &range_len,
+ null,
+ @boolToInt(non_blocking),
+ @boolToInt(exclusive),
+ );
}
const non_blocking_flag = if (non_blocking) os.LOCK_NB else @as(i32, 0);
- try os.flock(file.handle, switch (lock) {
+ return os.flock(file.handle, switch (lock) {
.None => os.LOCK_UN,
.Shared => os.LOCK_SH | non_blocking_flag,
.Exclusive => os.LOCK_EX | non_blocking_flag,
lib/std/os/windows/ntdll.zig
@@ -139,3 +139,24 @@ pub extern "NtDll" fn RtlWaitOnAddress(
AddressSize: SIZE_T,
Timeout: ?*const LARGE_INTEGER,
) callconv(WINAPI) NTSTATUS;
+
+pub extern "NtDll" fn NtLockFile(
+ FileHandle: HANDLE,
+ Event: ?HANDLE,
+ ApcRoutine: ?*IO_APC_ROUTINE,
+ ApcContext: ?*c_void,
+ IoStatusBlock: ?*IO_STATUS_BLOCK,
+ ByteOffset: *const LARGE_INTEGER,
+ Length: *const LARGE_INTEGER,
+ Key: ?*ULONG,
+ FailImmediately: BOOLEAN,
+ ExclusiveLock: BOOLEAN,
+) callconv(WINAPI) NTSTATUS;
+
+pub extern "NtDll" fn NtUnlockFile(
+ FileHandle: HANDLE,
+ IoStatusBlock: ?*IO_STATUS_BLOCK,
+ ByteOffset: *const LARGE_INTEGER,
+ Length: *const LARGE_INTEGER,
+ Key: ?*ULONG,
+) callconv(WINAPI) NTSTATUS;
lib/std/os/windows.zig
@@ -1679,6 +1679,62 @@ pub fn SetFileTime(
}
}
+pub const LockFileError = error{
+ SystemResources,
+ WouldBlock,
+} || std.os.UnexpectedError;
+
+pub fn LockFile(
+ FileHandle: HANDLE,
+ Event: ?HANDLE,
+ ApcRoutine: ?*IO_APC_ROUTINE,
+ ApcContext: ?*c_void,
+ IoStatusBlock: ?*IO_STATUS_BLOCK,
+ ByteOffset: *const LARGE_INTEGER,
+ Length: *const LARGE_INTEGER,
+ Key: ?*ULONG,
+ FailImmediately: BOOLEAN,
+ ExclusiveLock: BOOLEAN,
+) !void {
+ const rc = ntdll.NtLockFile(
+ FileHandle,
+ Event,
+ ApcRoutine,
+ ApcContext,
+ IoStatusBlock,
+ ByteOffset,
+ Length,
+ Key,
+ FailImmediately,
+ ExclusiveLock,
+ );
+ switch (rc) {
+ .SUCCESS => return,
+ .INSUFFICIENT_RESOURCES => return error.SystemResources,
+ .LOCK_NOT_GRANTED => return error.WouldBlock,
+ else => return unexpectedStatus(rc),
+ }
+}
+
+pub const UnlockFileError = error{
+ RangeNotLocked,
+} || std.os.UnexpectedError;
+
+pub fn UnlockFile(
+ FileHandle: HANDLE,
+ IoStatusBlock: ?*IO_STATUS_BLOCK,
+ ByteOffset: *const LARGE_INTEGER,
+ Length: *const LARGE_INTEGER,
+ Key: ?*ULONG,
+) !void {
+ const rc = ntdll.NtUnlockFile(FileHandle, IoStatusBlock, ByteOffset, Length, Key);
+ switch (rc) {
+ .SUCCESS => return,
+ .RANGE_NOT_LOCKED => return error.RangeNotLocked,
+ else => return unexpectedStatus(rc),
+ }
+}
+
pub fn teb() *TEB {
return switch (builtin.target.cpu.arch) {
.i386 => asm volatile (