implement std.fs.File.setLock for Windows
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user