From a7688c8c4b2da3223cb67924c16cca35d12335ea Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Fri, 10 Mar 2023 22:34:46 -0500 Subject: [PATCH 1/9] Leverage `fileapi` for opening files on windows --- spec/std/file_spec.cr | 9 +++ src/crystal/system/file.cr | 2 +- src/crystal/system/win32/file.cr | 72 +++++++++++++++++++++- src/lib_c/x86_64-windows-msvc/c/fileapi.cr | 24 +++++++- src/lib_c/x86_64-windows-msvc/c/io.cr | 2 + src/lib_c/x86_64-windows-msvc/c/winnt.cr | 5 +- 6 files changed, 105 insertions(+), 9 deletions(-) diff --git a/spec/std/file_spec.cr b/spec/std/file_spec.cr index 104cf3e16186..8513b3bebacf 100644 --- a/spec/std/file_spec.cr +++ b/spec/std/file_spec.cr @@ -517,6 +517,15 @@ describe "File" do end end + it "deletes an open file" do + with_tempfile("delete-file.txt") do |filename| + file = File.open filename, "w" + File.exists?(file.path).should be_true + file.delete + File.exists?(file.path).should be_false + end + end + it "deletes? a file" do with_tempfile("delete-file.txt") do |filename| File.open(filename, "w") { } diff --git a/src/crystal/system/file.cr b/src/crystal/system/file.cr index 0f645fd8a3ec..c98a013edf88 100644 --- a/src/crystal/system/file.cr +++ b/src/crystal/system/file.cr @@ -81,7 +81,7 @@ module Crystal::System::File end private def self.error_is_file_exists?(errno) - Errno.value.in?(Errno::EEXIST, WinError::ERROR_ALREADY_EXISTS) + Errno.value.in?(Errno::EEXIST, Errno::ENOENT, WinError::ERROR_ALREADY_EXISTS, WinError::ERROR_FILE_EXISTS) end # Closes the internal file descriptor without notifying libevent. diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index 225a345723cc..f3814017f8a1 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -26,11 +26,77 @@ module Crystal::System::File end def self.open(filename : String, flags : Int32, perm : ::File::Permissions) : {LibC::Int, Errno} - flags |= LibC::O_BINARY | LibC::O_NOINHERIT + access, disposition, attributes, share = self.posix_to_open_opts flags, perm - fd = LibC._wopen(System.to_wstr(filename), flags, perm) + handle = LibC.CreateFileW( + System.to_wstr(filename), + access, + share, # UNIX semantics + nil, + disposition, + attributes, + LibC::HANDLE.null + ) + + if handle == LibC::INVALID_HANDLE_VALUE + return {-1, Errno.value} + end + + fd = LibC._open_osfhandle handle, LibC::O_CREAT | LibC::O_TRUNC | LibC::O_RDWR | LibC::O_BINARY + + if fd == -1 + return {-1, Errno.value} + end + + LibC._setmode fd, LibC::O_BINARY + + {fd, Errno::NONE} + end + + private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) + access = disposition = attributes = 0 + + case flags & (LibC::O_RDONLY | LibC::O_WRONLY | LibC::O_RDWR) + when LibC::O_RDONLY then access = LibC::GENERIC_READ + when LibC::O_WRONLY then access = LibC::GENERIC_WRITE + when LibC::O_RDWR then access = LibC::GENERIC_READ | LibC::GENERIC_WRITE + end + + if flags & LibC::O_APPEND > 0 + access |= LibC::FILE_APPEND_DATA + attributes &= ~LibC::FILE_FLAG_BACKUP_SEMANTICS + end + + share = LibC::DEFAULT_SHARE_MODE + + case flags & (LibC::O_CREAT | LibC::O_EXCL | LibC::O_TRUNC) + when 0, LibC::O_EXCL then disposition = LibC::OPEN_EXISTING + when LibC::O_CREAT then disposition = LibC::OPEN_ALWAYS + when LibC::O_CREAT | LibC::O_EXCL, LibC::O_CREAT | LibC::O_TRUNC | LibC::O_EXCL then disposition = LibC::CREATE_NEW + when LibC::O_TRUNC, LibC::O_TRUNC | LibC::O_EXCL then disposition = LibC::TRUNCATE_EXISTING + when LibC::O_CREAT | LibC::O_TRUNC then disposition = LibC::CREATE_ALWAYS + end + + attributes |= LibC::FILE_ATTRIBUTE_NORMAL + unless perm.owner_write? + attributes |= LibC::FILE_ATTRIBUTE_READONLY + end + + if flags & LibC::O_TEMPORARY > 0 + attributes |= LibC::FILE_FLAG_DELETE_ON_CLOSE | LibC::FILE_ATTRIBUTE_TEMPORARY + access |= LibC::DELETE + end + + if flags & LibC::O_SHORT_LIVED > 0 + attributes |= LibC::FILE_ATTRIBUTE_TEMPORARY + end + + case flags & (LibC::O_SEQUENTIAL | LibC::O_RANDOM) + when LibC::O_SEQUENTIAL then attributes |= LibC::FILE_FLAG_SEQUENTIAL_SCAN + when LibC::O_RANDOM then attributes |= LibC::FILE_FLAG_RANDOM_ACCESS + end - {fd, fd == -1 ? Errno.value : Errno::NONE} + {access, disposition, attributes, share} end NOT_FOUND_ERRORS = { diff --git a/src/lib_c/x86_64-windows-msvc/c/fileapi.cr b/src/lib_c/x86_64-windows-msvc/c/fileapi.cr index 701a9590ca22..77c807984987 100644 --- a/src/lib_c/x86_64-windows-msvc/c/fileapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/fileapi.cr @@ -41,19 +41,37 @@ lib LibC fun SetFileAttributesW(lpFileName : LPWSTR, dwFileAttributes : DWORD) : BOOL fun GetFileAttributesExW(lpFileName : LPWSTR, fInfoLevelId : GET_FILEEX_INFO_LEVELS, lpFileInformation : Void*) : BOOL - OPEN_EXISTING = 3 + CREATE_NEW = 1 + CREATE_ALWAYS = 2 + OPEN_EXISTING = 3 + OPEN_ALWAYS = 4 + TRUNCATE_EXISTING = 5 - FILE_ATTRIBUTE_NORMAL = 0x80 - FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 + FILE_ATTRIBUTE_NORMAL = 0x80 + FILE_ATTRIBUTE_TEMPORARY = 0x100 + + FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 + FILE_FLAG_DELETE_ON_CLOSE = 0x04000000 + FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 + FILE_FLAG_RANDOM_ACCESS = 0x10000000 + FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000 FILE_SHARE_READ = 0x1 FILE_SHARE_WRITE = 0x2 FILE_SHARE_DELETE = 0x4 + DEFAULT_SHARE_MODE = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + + GENERIC_READ = 0x80000000 + GENERIC_WRITE = 0x40000000 + fun CreateFileW(lpFileName : LPWSTR, dwDesiredAccess : DWORD, dwShareMode : DWORD, lpSecurityAttributes : SECURITY_ATTRIBUTES*, dwCreationDisposition : DWORD, dwFlagsAndAttributes : DWORD, hTemplateFile : HANDLE) : HANDLE + fun _open_osfhandle(osfhandle : HANDLE, flags : LibC::Int) : LibC::Int + fun _setmode(fd : LibC::Int, mode : LibC::Int) : LibC::Int + fun ReadFile(hFile : HANDLE, lpBuffer : Void*, nNumberOfBytesToRead : DWORD, lpNumberOfBytesRead : DWORD*, lpOverlapped : OVERLAPPED*) : BOOL MAX_PATH = 260 diff --git a/src/lib_c/x86_64-windows-msvc/c/io.cr b/src/lib_c/x86_64-windows-msvc/c/io.cr index dc3dfd345523..a76fb62a6115 100644 --- a/src/lib_c/x86_64-windows-msvc/c/io.cr +++ b/src/lib_c/x86_64-windows-msvc/c/io.cr @@ -16,4 +16,6 @@ lib LibC fun _pipe(pfds : Int*, psize : UInt, textmode : Int) : Int fun _dup2(fd1 : Int, fd2 : Int) : Int fun _commit(fd : Int) : Int + + FILE_APPEND_DATA = 0x00000004 end diff --git a/src/lib_c/x86_64-windows-msvc/c/winnt.cr b/src/lib_c/x86_64-windows-msvc/c/winnt.cr index edd247c2c723..5fdd69988317 100644 --- a/src/lib_c/x86_64-windows-msvc/c/winnt.cr +++ b/src/lib_c/x86_64-windows-msvc/c/winnt.cr @@ -19,8 +19,9 @@ lib LibC FILE_ATTRIBUTE_READONLY = 0x1 FILE_ATTRIBUTE_REPARSE_POINT = 0x400 - FILE_READ_ATTRIBUTES = 0x80 - FILE_WRITE_ATTRIBUTES = 0x0100 + DELETE = 0x00010000 + FILE_READ_ATTRIBUTES = 0x80 + FILE_WRITE_ATTRIBUTES = 0x0100 # Memory protection constants PAGE_READWRITE = 0x04 From c96bc283d6897eda0fdc0ea45164a76873af1c5e Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Fri, 10 Mar 2023 23:41:42 -0500 Subject: [PATCH 2/9] Scope difference in file already existing conflict to windows --- src/crystal/system/file.cr | 2 +- src/crystal/system/win32/file.cr | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/crystal/system/file.cr b/src/crystal/system/file.cr index c98a013edf88..0f645fd8a3ec 100644 --- a/src/crystal/system/file.cr +++ b/src/crystal/system/file.cr @@ -81,7 +81,7 @@ module Crystal::System::File end private def self.error_is_file_exists?(errno) - Errno.value.in?(Errno::EEXIST, Errno::ENOENT, WinError::ERROR_ALREADY_EXISTS, WinError::ERROR_FILE_EXISTS) + Errno.value.in?(Errno::EEXIST, WinError::ERROR_ALREADY_EXISTS) end # Closes the internal file descriptor without notifying libevent. diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index f3814017f8a1..88035ecff44b 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -39,6 +39,11 @@ module Crystal::System::File ) if handle == LibC::INVALID_HANDLE_VALUE + # Map ERROR_FILE_EXISTS to Errno::EEXIST to avoid changing semantics of other systems + if WinError.value.error_file_exists? + Errno.value = Errno::EEXIST + end + return {-1, Errno.value} end From 8cedeb69c074e6c455db2135be5e2d50a072ef95 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Sat, 11 Mar 2023 00:32:39 -0500 Subject: [PATCH 3/9] Pass correct flags to `_open_osfhandle` --- src/crystal/system/win32/file.cr | 8 ++++++-- src/lib_c/x86_64-windows-msvc/c/io.cr | 2 -- src/lib_c/x86_64-windows-msvc/c/winnt.cr | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index 88035ecff44b..5b7cb03a6fe0 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -47,13 +47,17 @@ module Crystal::System::File return {-1, Errno.value} end - fd = LibC._open_osfhandle handle, LibC::O_CREAT | LibC::O_TRUNC | LibC::O_RDWR | LibC::O_BINARY + fd = LibC._open_osfhandle handle, flags if fd == -1 return {-1, Errno.value} end - LibC._setmode fd, LibC::O_BINARY + if flags & LibC::O_BINARY > 0 + LibC._setmode fd, LibC::O_BINARY + elsif flags & LibC::O_TEXT > 0 + LibC._setmode fd, LibC::O_TEXT + end {fd, Errno::NONE} end diff --git a/src/lib_c/x86_64-windows-msvc/c/io.cr b/src/lib_c/x86_64-windows-msvc/c/io.cr index a76fb62a6115..dc3dfd345523 100644 --- a/src/lib_c/x86_64-windows-msvc/c/io.cr +++ b/src/lib_c/x86_64-windows-msvc/c/io.cr @@ -16,6 +16,4 @@ lib LibC fun _pipe(pfds : Int*, psize : UInt, textmode : Int) : Int fun _dup2(fd1 : Int, fd2 : Int) : Int fun _commit(fd : Int) : Int - - FILE_APPEND_DATA = 0x00000004 end diff --git a/src/lib_c/x86_64-windows-msvc/c/winnt.cr b/src/lib_c/x86_64-windows-msvc/c/winnt.cr index 5fdd69988317..36c887f78ba7 100644 --- a/src/lib_c/x86_64-windows-msvc/c/winnt.cr +++ b/src/lib_c/x86_64-windows-msvc/c/winnt.cr @@ -19,6 +19,8 @@ lib LibC FILE_ATTRIBUTE_READONLY = 0x1 FILE_ATTRIBUTE_REPARSE_POINT = 0x400 + FILE_APPEND_DATA = 0x00000004 + DELETE = 0x00010000 FILE_READ_ATTRIBUTES = 0x80 FILE_WRITE_ATTRIBUTES = 0x0100 From dfc0148a3d415f7b8857f729ec6864e5cc5c7c66 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Sat, 11 Mar 2023 10:14:51 -0500 Subject: [PATCH 4/9] Simplify `posix_to_open_opts` logic --- src/crystal/system/win32/file.cr | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index 5b7cb03a6fe0..88184715ece9 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -63,21 +63,20 @@ module Crystal::System::File end private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) - access = disposition = attributes = 0 + disposition = 0 - case flags & (LibC::O_RDONLY | LibC::O_WRONLY | LibC::O_RDWR) - when LibC::O_RDONLY then access = LibC::GENERIC_READ - when LibC::O_WRONLY then access = LibC::GENERIC_WRITE - when LibC::O_RDWR then access = LibC::GENERIC_READ | LibC::GENERIC_WRITE - end + access = if flags & LibC::O_WRONLY > 0 + LibC::GENERIC_WRITE + elsif flags & LibC::O_RDWR > 0 + LibC::GENERIC_READ | LibC::GENERIC_WRITE + else + LibC::GENERIC_READ + end if flags & LibC::O_APPEND > 0 access |= LibC::FILE_APPEND_DATA - attributes &= ~LibC::FILE_FLAG_BACKUP_SEMANTICS end - share = LibC::DEFAULT_SHARE_MODE - case flags & (LibC::O_CREAT | LibC::O_EXCL | LibC::O_TRUNC) when 0, LibC::O_EXCL then disposition = LibC::OPEN_EXISTING when LibC::O_CREAT then disposition = LibC::OPEN_ALWAYS @@ -86,7 +85,7 @@ module Crystal::System::File when LibC::O_CREAT | LibC::O_TRUNC then disposition = LibC::CREATE_ALWAYS end - attributes |= LibC::FILE_ATTRIBUTE_NORMAL + attributes = LibC::FILE_ATTRIBUTE_NORMAL unless perm.owner_write? attributes |= LibC::FILE_ATTRIBUTE_READONLY end @@ -105,7 +104,7 @@ module Crystal::System::File when LibC::O_RANDOM then attributes |= LibC::FILE_FLAG_RANDOM_ACCESS end - {access, disposition, attributes, share} + {access, disposition, attributes, LibC::DEFAULT_SHARE_MODE} end NOT_FOUND_ERRORS = { From 3886053339942eedaa9b39de323e4455342f0990 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Mon, 13 Mar 2023 12:34:37 -0400 Subject: [PATCH 5/9] Address PR feedback --- src/crystal/system/file.cr | 2 +- src/crystal/system/win32/file.cr | 44 +++++++++++++++----------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/crystal/system/file.cr b/src/crystal/system/file.cr index 0f645fd8a3ec..89d29512c28e 100644 --- a/src/crystal/system/file.cr +++ b/src/crystal/system/file.cr @@ -81,7 +81,7 @@ module Crystal::System::File end private def self.error_is_file_exists?(errno) - Errno.value.in?(Errno::EEXIST, WinError::ERROR_ALREADY_EXISTS) + errno.in?(Errno::EEXIST, WinError::ERROR_ALREADY_EXISTS) end # Closes the internal file descriptor without notifying libevent. diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index 88184715ece9..c0f80fb5e694 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -26,12 +26,12 @@ module Crystal::System::File end def self.open(filename : String, flags : Int32, perm : ::File::Permissions) : {LibC::Int, Errno} - access, disposition, attributes, share = self.posix_to_open_opts flags, perm + access, disposition, attributes = self.posix_to_open_opts flags, perm handle = LibC.CreateFileW( System.to_wstr(filename), access, - share, # UNIX semantics + LibC::DEFAULT_SHARE_MODE, # UNIX semantics nil, disposition, attributes, @@ -40,11 +40,7 @@ module Crystal::System::File if handle == LibC::INVALID_HANDLE_VALUE # Map ERROR_FILE_EXISTS to Errno::EEXIST to avoid changing semantics of other systems - if WinError.value.error_file_exists? - Errno.value = Errno::EEXIST - end - - return {-1, Errno.value} + return {-1, WinError.value.error_file_exists? ? Errno::EEXIST : Errno.value} end fd = LibC._open_osfhandle handle, flags @@ -63,26 +59,28 @@ module Crystal::System::File end private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) - disposition = 0 - - access = if flags & LibC::O_WRONLY > 0 - LibC::GENERIC_WRITE - elsif flags & LibC::O_RDWR > 0 - LibC::GENERIC_READ | LibC::GENERIC_WRITE - else - LibC::GENERIC_READ - end + access = 0 + access |= LibC::GENERIC_WRITE unless flags == LibC::O_RDONLY + access |= LibC::GENERIC_READ unless flags & LibC::O_WRONLY > 0 if flags & LibC::O_APPEND > 0 access |= LibC::FILE_APPEND_DATA end - case flags & (LibC::O_CREAT | LibC::O_EXCL | LibC::O_TRUNC) - when 0, LibC::O_EXCL then disposition = LibC::OPEN_EXISTING - when LibC::O_CREAT then disposition = LibC::OPEN_ALWAYS - when LibC::O_CREAT | LibC::O_EXCL, LibC::O_CREAT | LibC::O_TRUNC | LibC::O_EXCL then disposition = LibC::CREATE_NEW - when LibC::O_TRUNC, LibC::O_TRUNC | LibC::O_EXCL then disposition = LibC::TRUNCATE_EXISTING - when LibC::O_CREAT | LibC::O_TRUNC then disposition = LibC::CREATE_ALWAYS + if flags & LibC::O_TRUNC > 0 + if flags & LibC::O_CREAT > 0 + disposition = LibC::CREATE_ALWAYS + else + disposition = LibC::TRUNCATE_EXISTING + end + elsif flags & LibC::O_CREAT > 0 + if flags & LibC::O_EXCL > 0 + disposition = LibC::CREATE_NEW + else + disposition = LibC::OPEN_ALWAYS + end + else + disposition = LibC::OPEN_EXISTING end attributes = LibC::FILE_ATTRIBUTE_NORMAL @@ -104,7 +102,7 @@ module Crystal::System::File when LibC::O_RANDOM then attributes |= LibC::FILE_FLAG_RANDOM_ACCESS end - {access, disposition, attributes, LibC::DEFAULT_SHARE_MODE} + {access, disposition, attributes} end NOT_FOUND_ERRORS = { From 3da1fdf0122551e9c03650e91fd30e074dfddf01 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Mon, 13 Mar 2023 17:36:21 -0400 Subject: [PATCH 6/9] Leverage `Int#bits_set?` --- src/crystal/system/win32/file.cr | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index c0f80fb5e694..fea4d0a9ca0e 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -49,9 +49,9 @@ module Crystal::System::File return {-1, Errno.value} end - if flags & LibC::O_BINARY > 0 + if flags.bits_set? LibC::O_BINARY LibC._setmode fd, LibC::O_BINARY - elsif flags & LibC::O_TEXT > 0 + elsif flags.bits_set? LibC::O_TEXT LibC._setmode fd, LibC::O_TEXT end @@ -61,20 +61,20 @@ module Crystal::System::File private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) access = 0 access |= LibC::GENERIC_WRITE unless flags == LibC::O_RDONLY - access |= LibC::GENERIC_READ unless flags & LibC::O_WRONLY > 0 + access |= LibC::GENERIC_READ unless flags.bits_set? LibC::O_WRONLY - if flags & LibC::O_APPEND > 0 + if flags.bits_set? LibC::O_APPEND access |= LibC::FILE_APPEND_DATA end - if flags & LibC::O_TRUNC > 0 - if flags & LibC::O_CREAT > 0 + if flags.bits_set? LibC::O_TRUNC + if flags.bits_set? LibC::O_CREAT disposition = LibC::CREATE_ALWAYS else disposition = LibC::TRUNCATE_EXISTING end - elsif flags & LibC::O_CREAT > 0 - if flags & LibC::O_EXCL > 0 + elsif flags.bits_set? LibC::O_CREAT + if flags.bits_set? LibC::O_EXCL disposition = LibC::CREATE_NEW else disposition = LibC::OPEN_ALWAYS @@ -88,18 +88,19 @@ module Crystal::System::File attributes |= LibC::FILE_ATTRIBUTE_READONLY end - if flags & LibC::O_TEMPORARY > 0 + if flags.bits_set? LibC::O_TEMPORARY attributes |= LibC::FILE_FLAG_DELETE_ON_CLOSE | LibC::FILE_ATTRIBUTE_TEMPORARY access |= LibC::DELETE end - if flags & LibC::O_SHORT_LIVED > 0 + if flags.bits_set? LibC::O_SHORT_LIVED attributes |= LibC::FILE_ATTRIBUTE_TEMPORARY end - case flags & (LibC::O_SEQUENTIAL | LibC::O_RANDOM) - when LibC::O_SEQUENTIAL then attributes |= LibC::FILE_FLAG_SEQUENTIAL_SCAN - when LibC::O_RANDOM then attributes |= LibC::FILE_FLAG_RANDOM_ACCESS + if flags.bits_set? LibC::O_SEQUENTIAL + attributes |= LibC::FILE_FLAG_SEQUENTIAL_SCAN + elsif flags.bits_set? LibC::O_RANDOM + attributes |= LibC::FILE_FLAG_RANDOM_ACCESS end {access, disposition, attributes} From 3be60879212c6260b16e68ee32579b72ec47e66d Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Tue, 14 Mar 2023 09:08:54 -0400 Subject: [PATCH 7/9] Move some bindings to proper file --- src/lib_c/x86_64-windows-msvc/c/fileapi.cr | 3 --- src/lib_c/x86_64-windows-msvc/c/io.cr | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib_c/x86_64-windows-msvc/c/fileapi.cr b/src/lib_c/x86_64-windows-msvc/c/fileapi.cr index 77c807984987..9b88b5341c09 100644 --- a/src/lib_c/x86_64-windows-msvc/c/fileapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/fileapi.cr @@ -69,9 +69,6 @@ lib LibC lpSecurityAttributes : SECURITY_ATTRIBUTES*, dwCreationDisposition : DWORD, dwFlagsAndAttributes : DWORD, hTemplateFile : HANDLE) : HANDLE - fun _open_osfhandle(osfhandle : HANDLE, flags : LibC::Int) : LibC::Int - fun _setmode(fd : LibC::Int, mode : LibC::Int) : LibC::Int - fun ReadFile(hFile : HANDLE, lpBuffer : Void*, nNumberOfBytesToRead : DWORD, lpNumberOfBytesRead : DWORD*, lpOverlapped : OVERLAPPED*) : BOOL MAX_PATH = 260 diff --git a/src/lib_c/x86_64-windows-msvc/c/io.cr b/src/lib_c/x86_64-windows-msvc/c/io.cr index dc3dfd345523..94a5b7b582a3 100644 --- a/src/lib_c/x86_64-windows-msvc/c/io.cr +++ b/src/lib_c/x86_64-windows-msvc/c/io.cr @@ -16,4 +16,6 @@ lib LibC fun _pipe(pfds : Int*, psize : UInt, textmode : Int) : Int fun _dup2(fd1 : Int, fd2 : Int) : Int fun _commit(fd : Int) : Int + fun _open_osfhandle(osfhandle : HANDLE, flags : LibC::Int) : LibC::Int + fun _setmode(fd : LibC::Int, mode : LibC::Int) : LibC::Int end From dd120016a7b762bcdea5266ba50ee1426a5250c0 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Tue, 14 Mar 2023 11:30:09 -0400 Subject: [PATCH 8/9] Always open in binary mode --- src/crystal/system/win32/file.cr | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index fea4d0a9ca0e..52073b8ebf1f 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -49,11 +49,8 @@ module Crystal::System::File return {-1, Errno.value} end - if flags.bits_set? LibC::O_BINARY - LibC._setmode fd, LibC::O_BINARY - elsif flags.bits_set? LibC::O_TEXT - LibC._setmode fd, LibC::O_TEXT - end + # Only binary mode is supported + LibC._setmode fd, LibC::O_BINARY {fd, Errno::NONE} end From e3bf5a0c5f1dcd4fdcd1eccdfe001c5c67e72bee Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Tue, 14 Mar 2023 11:54:03 -0400 Subject: [PATCH 9/9] Revert to previous `access` handling logic --- src/crystal/system/win32/file.cr | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/crystal/system/win32/file.cr b/src/crystal/system/win32/file.cr index 52073b8ebf1f..49ebf92702ae 100644 --- a/src/crystal/system/win32/file.cr +++ b/src/crystal/system/win32/file.cr @@ -56,9 +56,13 @@ module Crystal::System::File end private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) - access = 0 - access |= LibC::GENERIC_WRITE unless flags == LibC::O_RDONLY - access |= LibC::GENERIC_READ unless flags.bits_set? LibC::O_WRONLY + access = if flags.bits_set? LibC::O_WRONLY + LibC::GENERIC_WRITE + elsif flags.bits_set? LibC::O_RDWR + LibC::GENERIC_READ | LibC::GENERIC_WRITE + else + LibC::GENERIC_READ + end if flags.bits_set? LibC::O_APPEND access |= LibC::FILE_APPEND_DATA