| author | |
| committer | |
| log | 488f68069ba0a81f46a5afe721b908cfd3c61f76 |
| tree | 4f2316eefbe164a0b42864dbb0d2a3c128ed7417 |
| parent | 3d7ae63c6f0b01456a411b31bad2322166634868 |
3 files changed, 106 insertions(+), 2 deletions(-)
lib/std/fs/file.zig+29-2| ... | @@ -840,10 +840,37 @@ pub const File = struct { | ... | @@ -840,10 +840,37 @@ pub const File = struct { |
| 840 | /// TODO: integrate with async I/O | 840 | /// TODO: integrate with async I/O |
| 841 | pub fn setLock(file: File, lock: Lock, non_blocking: bool) SetLockError!void { | 841 | pub fn setLock(file: File, lock: Lock, non_blocking: bool) SetLockError!void { |
| 842 | if (is_windows) { | 842 | if (is_windows) { |
| 843 | @compileError("TODO implement fs.File.setLock for Windows"); | 843 | const range_off: windows.LARGE_INTEGER = 0; |
| 844 | const range_len: windows.LARGE_INTEGER = 1; | ||
| 845 | const exclusive = switch (lock) { | ||
| 846 | .None => return windows.UnlockFile( | ||
| 847 | file.handle, | ||
| 848 | null, | ||
| 849 | &range_off, | ||
| 850 | &range_len, | ||
| 851 | null, | ||
| 852 | ) catch |err| switch (err) { | ||
| 853 | error.RangeNotLocked => return, | ||
| 854 | else => |e| return e, | ||
| 855 | }, | ||
| 856 | .Shared => false, | ||
| 857 | .Exclusive => true, | ||
| 858 | }; | ||
| 859 | return windows.LockFile( | ||
| 860 | file.handle, | ||
| 861 | null, | ||
| 862 | null, | ||
| 863 | null, | ||
| 864 | null, | ||
| 865 | &range_off, | ||
| 866 | &range_len, | ||
| 867 | null, | ||
| 868 | @boolToInt(non_blocking), | ||
| 869 | @boolToInt(exclusive), | ||
| 870 | ); | ||
| 844 | } | 871 | } |
| 845 | const non_blocking_flag = if (non_blocking) os.LOCK_NB else @as(i32, 0); | 872 | const non_blocking_flag = if (non_blocking) os.LOCK_NB else @as(i32, 0); |
| 846 | try os.flock(file.handle, switch (lock) { | 873 | return os.flock(file.handle, switch (lock) { |
| 847 | .None => os.LOCK_UN, | 874 | .None => os.LOCK_UN, |
| 848 | .Shared => os.LOCK_SH | non_blocking_flag, | 875 | .Shared => os.LOCK_SH | non_blocking_flag, |
| 849 | .Exclusive => os.LOCK_EX | non_blocking_flag, | 876 | .Exclusive => os.LOCK_EX | non_blocking_flag, |
lib/std/os/windows.zig+56| ... | @@ -1679,6 +1679,62 @@ pub fn SetFileTime( | ... | @@ -1679,6 +1679,62 @@ pub fn SetFileTime( |
| 1679 | } | 1679 | } |
| 1680 | } | 1680 | } |
| 1681 | 1681 | ||
| 1682 | pub const LockFileError = error{ | ||
| 1683 | SystemResources, | ||
| 1684 | WouldBlock, | ||
| 1685 | } || std.os.UnexpectedError; | ||
| 1686 | |||
| 1687 | pub fn LockFile( | ||
| 1688 | FileHandle: HANDLE, | ||
| 1689 | Event: ?HANDLE, | ||
| 1690 | ApcRoutine: ?*IO_APC_ROUTINE, | ||
| 1691 | ApcContext: ?*c_void, | ||
| 1692 | IoStatusBlock: ?*IO_STATUS_BLOCK, | ||
| 1693 | ByteOffset: *const LARGE_INTEGER, | ||
| 1694 | Length: *const LARGE_INTEGER, | ||
| 1695 | Key: ?*ULONG, | ||
| 1696 | FailImmediately: BOOLEAN, | ||
| 1697 | ExclusiveLock: BOOLEAN, | ||
| 1698 | ) !void { | ||
| 1699 | const rc = ntdll.NtLockFile( | ||
| 1700 | FileHandle, | ||
| 1701 | Event, | ||
| 1702 | ApcRoutine, | ||
| 1703 | ApcContext, | ||
| 1704 | IoStatusBlock, | ||
| 1705 | ByteOffset, | ||
| 1706 | Length, | ||
| 1707 | Key, | ||
| 1708 | FailImmediately, | ||
| 1709 | ExclusiveLock, | ||
| 1710 | ); | ||
| 1711 | switch (rc) { | ||
| 1712 | .SUCCESS => return, | ||
| 1713 | .INSUFFICIENT_RESOURCES => return error.SystemResources, | ||
| 1714 | .LOCK_NOT_GRANTED => return error.WouldBlock, | ||
| 1715 | else => return unexpectedStatus(rc), | ||
| 1716 | } | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | pub const UnlockFileError = error{ | ||
| 1720 | RangeNotLocked, | ||
| 1721 | } || std.os.UnexpectedError; | ||
| 1722 | |||
| 1723 | pub fn UnlockFile( | ||
| 1724 | FileHandle: HANDLE, | ||
| 1725 | IoStatusBlock: ?*IO_STATUS_BLOCK, | ||
| 1726 | ByteOffset: *const LARGE_INTEGER, | ||
| 1727 | Length: *const LARGE_INTEGER, | ||
| 1728 | Key: ?*ULONG, | ||
| 1729 | ) !void { | ||
| 1730 | const rc = ntdll.NtUnlockFile(FileHandle, IoStatusBlock, ByteOffset, Length, Key); | ||
| 1731 | switch (rc) { | ||
| 1732 | .SUCCESS => return, | ||
| 1733 | .RANGE_NOT_LOCKED => return error.RangeNotLocked, | ||
| 1734 | else => return unexpectedStatus(rc), | ||
| 1735 | } | ||
| 1736 | } | ||
| 1737 | |||
| 1682 | pub fn teb() *TEB { | 1738 | pub fn teb() *TEB { |
| 1683 | return switch (builtin.target.cpu.arch) { | 1739 | return switch (builtin.target.cpu.arch) { |
| 1684 | .i386 => asm volatile ( | 1740 | .i386 => asm volatile ( |
lib/std/os/windows/ntdll.zig+21| ... | @@ -139,3 +139,24 @@ pub extern "NtDll" fn RtlWaitOnAddress( | ... | @@ -139,3 +139,24 @@ pub extern "NtDll" fn RtlWaitOnAddress( |
| 139 | AddressSize: SIZE_T, | 139 | AddressSize: SIZE_T, |
| 140 | Timeout: ?*const LARGE_INTEGER, | 140 | Timeout: ?*const LARGE_INTEGER, |
| 141 | ) callconv(WINAPI) NTSTATUS; | 141 | ) callconv(WINAPI) NTSTATUS; |
| 142 | |||
| 143 | pub extern "NtDll" fn NtLockFile( | ||
| 144 | FileHandle: HANDLE, | ||
| 145 | Event: ?HANDLE, | ||
| 146 | ApcRoutine: ?*IO_APC_ROUTINE, | ||
| 147 | ApcContext: ?*c_void, | ||
| 148 | IoStatusBlock: ?*IO_STATUS_BLOCK, | ||
| 149 | ByteOffset: *const LARGE_INTEGER, | ||
| 150 | Length: *const LARGE_INTEGER, | ||
| 151 | Key: ?*ULONG, | ||
| 152 | FailImmediately: BOOLEAN, | ||
| 153 | ExclusiveLock: BOOLEAN, | ||
| 154 | ) callconv(WINAPI) NTSTATUS; | ||
| 155 | |||
| 156 | pub extern "NtDll" fn NtUnlockFile( | ||
| 157 | FileHandle: HANDLE, | ||
| 158 | IoStatusBlock: ?*IO_STATUS_BLOCK, | ||
| 159 | ByteOffset: *const LARGE_INTEGER, | ||
| 160 | Length: *const LARGE_INTEGER, | ||
| 161 | Key: ?*ULONG, | ||
| 162 | ) callconv(WINAPI) NTSTATUS; |