-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Leverage fileapi for opening files on windows
#13178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a7688c8
c96bc28
8cedeb6
dfc0148
bce559b
3886053
3da1fdf
3be6087
dd12001
e3bf5a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,11 +26,85 @@ 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 = self.posix_to_open_opts flags, perm | ||
|
|
||
| fd = LibC._wopen(System.to_wstr(filename), flags, perm) | ||
| handle = LibC.CreateFileW( | ||
| System.to_wstr(filename), | ||
| access, | ||
| LibC::DEFAULT_SHARE_MODE, # UNIX semantics | ||
| nil, | ||
| disposition, | ||
| attributes, | ||
| LibC::HANDLE.null | ||
| ) | ||
|
|
||
| if handle == LibC::INVALID_HANDLE_VALUE | ||
| # Map ERROR_FILE_EXISTS to Errno::EEXIST to avoid changing semantics of other systems | ||
| return {-1, WinError.value.error_file_exists? ? Errno::EEXIST : Errno.value} | ||
| end | ||
|
|
||
| fd = LibC._open_osfhandle handle, flags | ||
|
|
||
| if fd == -1 | ||
| return {-1, Errno.value} | ||
| end | ||
|
|
||
| # Only binary mode is supported | ||
| LibC._setmode fd, LibC::O_BINARY | ||
|
|
||
| {fd, Errno::NONE} | ||
| end | ||
|
|
||
| private def self.posix_to_open_opts(flags : Int32, perm : ::File::Permissions) | ||
| 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 | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Windows only says:
So this check is fine on Windows, but to be precise, these flags are not bit flags at all. POSIX defines also access =
case flags & LibC::O_ACCMODE # unavailable on MSVC
when LibC::O_RDONLY
when LibC::O_WRONLY
when LibC::O_RDWR
when LibC::O_SEARCH # unavailable on most platforms
when LibC::O_EXEC # unavailable on most platforms
else
raise "not allowed"
end |
||
| end | ||
|
|
||
| if flags.bits_set? LibC::O_APPEND | ||
| access |= LibC::FILE_APPEND_DATA | ||
| end | ||
|
|
||
| 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.bits_set? LibC::O_CREAT | ||
| if flags.bits_set? LibC::O_EXCL | ||
| disposition = LibC::CREATE_NEW | ||
| else | ||
| disposition = LibC::OPEN_ALWAYS | ||
| end | ||
| else | ||
| disposition = LibC::OPEN_EXISTING | ||
| end | ||
|
|
||
| attributes = LibC::FILE_ATTRIBUTE_NORMAL | ||
| unless perm.owner_write? | ||
| attributes |= LibC::FILE_ATTRIBUTE_READONLY | ||
| end | ||
|
|
||
| if flags.bits_set? LibC::O_TEMPORARY | ||
| attributes |= LibC::FILE_FLAG_DELETE_ON_CLOSE | LibC::FILE_ATTRIBUTE_TEMPORARY | ||
| access |= LibC::DELETE | ||
| end | ||
|
|
||
| if flags.bits_set? LibC::O_SHORT_LIVED | ||
| attributes |= LibC::FILE_ATTRIBUTE_TEMPORARY | ||
| end | ||
|
|
||
| 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 | ||
|
|
||
| {fd, fd == -1 ? Errno.value : Errno::NONE} | ||
| {access, disposition, attributes} | ||
| end | ||
|
|
||
| NOT_FOUND_ERRORS = { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should keep these mandatory flags
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensuring
O_BINARYis added should address your below comment.EDIT: But to make the code cleaner, might just hardcode/inline the
_setmodecall.O_NOINHERITseems to be controlled via thebInheritHandleproperty of https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85) which is the 4th argument toCreateFileW. However, the documentation also says:So given we'd always be applying
O_NOINHERIT, I think we'll be fine as it is.