From f9f1221aae9f74d737720e5f9b411b81b92cd395 Mon Sep 17 00:00:00 2001 From: Jonah Beckford <71855677+jonahbeckford@users.noreply.github.com> Date: Thu, 10 Mar 2022 19:22:55 -0800 Subject: [PATCH 1/2] Add ssize_t typedef for MSVC --- CHANGES.md | 2 ++ src/unix/pread.c | 5 +++++ src/unix/pwrite.c | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 00157499..227b2e9c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,8 @@ ## Unreleased - Support all version of cmdliner (#386) +- Support MSVC compiler. Still missing implementations of pread and + pwrite. (#383) # 1.6.0 (2022-02-12) diff --git a/src/unix/pread.c b/src/unix/pread.c index 666d2670..012ef1ef 100644 --- a/src/unix/pread.c +++ b/src/unix/pread.c @@ -4,6 +4,11 @@ #include #include +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#endif + CAMLprim value caml_index_pread_int (value v_fd, value v_fd_off, value v_buf, value v_buf_off, value v_len) { diff --git a/src/unix/pwrite.c b/src/unix/pwrite.c index e91b71ca..4bc8eac6 100644 --- a/src/unix/pwrite.c +++ b/src/unix/pwrite.c @@ -4,6 +4,11 @@ #include #include +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#endif + CAMLprim value caml_index_pwrite_int (value v_fd, value v_fd_off, value v_buf, value v_buf_off, value v_len) { From 00c00ce2a39b6e776b2817a2d96626bdaaa4789f Mon Sep 17 00:00:00 2001 From: Jonah Beckford <71855677+jonahbeckford@users.noreply.github.com> Date: Fri, 11 Mar 2022 23:49:26 -0800 Subject: [PATCH 2/2] Supply win32 pread and pwrite --- CHANGES.md | 4 ++-- src/unix/pread.c | 49 +++++++++++++++++++++++++++++++++++++++++++++-- src/unix/pwrite.c | 46 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 227b2e9c..53e19d92 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,8 @@ ## Unreleased - Support all version of cmdliner (#386) -- Support MSVC compiler. Still missing implementations of pread and - pwrite. (#383) +- Support MSVC compiler. Supply Windows implementations of pread and pwrite. + (#383) # 1.6.0 (2022-02-12) diff --git a/src/unix/pread.c b/src/unix/pread.c index 012ef1ef..b5f27d4f 100644 --- a/src/unix/pread.c +++ b/src/unix/pread.c @@ -5,8 +5,53 @@ #include #ifdef _MSC_VER +#include #include +#include typedef SSIZE_T ssize_t; +typedef HANDLE file_descr_t; +#define File_descr_val Handle_val + +ssize_t pread(file_descr_t fd, void *buf, size_t count, size_t offset) +{ + OVERLAPPED oOverlap; + BOOL bResult; + DWORD dwError; + ssize_t ret; + HRESULT hr; + + /* https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile#synchronization-and-file-position */ + oOverlap.Internal = 0; + oOverlap.InternalHigh = 0; + oOverlap.Offset = LODWORD(offset); + oOverlap.OffsetHigh = HIDWORD(offset); + oOverlap.hEvent = 0; + bResult = ReadFile(fd, buf, count, NULL, &oOverlap); + + if (!bResult) { + /* ReadFile failed, or is completing asynchrously if opened with + FILE_FLAG_OVERLAPPED. OCaml does not use FILE_FLAG_OVERLAPPED. */ + dwError = GetLastError(); + if (dwError == ERROR_HANDLE_EOF) { + /* pread returns 0 on EOF */ + ret = 0; + } else { + /* pread returns -1 on any error */ + ret = -1; + } + } else { + /* pread returns number of bytes read */ + hr = ULongPtrToSSIZET(oOverlap.InternalHigh, &ret); + if(hr != S_OK) { + /* overflow. too many bytes read */ + ret = -1; + } + } + return ret; +} +#else +typedef size_t file_descr_t; +#define File_descr_val Int_val #endif CAMLprim value caml_index_pread_int @@ -15,7 +60,7 @@ CAMLprim value caml_index_pread_int CAMLparam5(v_fd, v_fd_off, v_buf, v_buf_off, v_len); ssize_t ret; - size_t fd = Int_val(v_fd); + file_descr_t fd = File_descr_val(v_fd); size_t fd_off = Long_val(v_fd_off); size_t buf_off = Long_val(v_buf_off); size_t len = Long_val(v_len); @@ -34,7 +79,7 @@ CAMLprim value caml_index_pread_int64 CAMLparam5(v_fd, v_fd_off, v_buf, v_buf_off, v_len); ssize_t ret; - size_t fd = Int_val(v_fd); + file_descr_t fd = File_descr_val(v_fd); size_t fd_off = Int64_val(v_fd_off); size_t buf_off = Long_val(v_buf_off); size_t len = Long_val(v_len); diff --git a/src/unix/pwrite.c b/src/unix/pwrite.c index 4bc8eac6..78d267fe 100644 --- a/src/unix/pwrite.c +++ b/src/unix/pwrite.c @@ -5,8 +5,50 @@ #include #ifdef _MSC_VER +#include #include +#include typedef SSIZE_T ssize_t; +typedef HANDLE file_descr_t; +#define File_descr_val Handle_val + +ssize_t pwrite(file_descr_t fd, const void *buf, size_t count, size_t offset) +{ + OVERLAPPED oOverlap; + DWORD dwBytesWritten; + BOOL bResult; + DWORD dwError; + ssize_t ret; + HRESULT hr; + + /* https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile#synchronization-and-file-position */ + /* &dwBytesWritten - ignored but non-NULL for Windows 7 compatibility */ + oOverlap.Internal = 0; + oOverlap.InternalHigh = 0; + oOverlap.Offset = LODWORD(offset); + oOverlap.OffsetHigh = HIDWORD(offset); + oOverlap.hEvent = 0; + bResult = WriteFile(fd, buf, count, &dwBytesWritten, &oOverlap); + + if (!bResult) { + /* WriteFile failed, or is completing asynchrously if opened with + FILE_FLAG_OVERLAPPED. OCaml does not use FILE_FLAG_OVERLAPPED. */ + dwError = GetLastError(); + /* pwrite returns -1 on any error */ + ret = -1; + } else { + /* pwrite returns number of bytes written */ + hr = ULongPtrToSSIZET(oOverlap.InternalHigh, &ret); + if(hr != S_OK) { + /* overflow. too many bytes written */ + ret = -1; + } + } + return ret; +} +#else +typedef size_t file_descr_t; +#define File_descr_val Int_val #endif CAMLprim value caml_index_pwrite_int @@ -15,7 +57,7 @@ CAMLprim value caml_index_pwrite_int CAMLparam5(v_fd, v_fd_off, v_buf, v_buf_off, v_len); ssize_t ret; - size_t fd = Int_val(v_fd); + file_descr_t fd = File_descr_val(v_fd); size_t fd_off = Long_val(v_fd_off); size_t buf_off = Long_val(v_buf_off); size_t len = Long_val(v_len); @@ -34,7 +76,7 @@ CAMLprim value caml_index_pwrite_int64 CAMLparam5(v_fd, v_fd_off, v_buf, v_buf_off, v_len); ssize_t ret; - size_t fd = Int_val(v_fd); + file_descr_t fd = File_descr_val(v_fd); size_t fd_off = Int64_val(v_fd_off); size_t buf_off = Long_val(v_buf_off); size_t len = Long_val(v_len);