Skip to content

Commit

Permalink
Supply win32 pread and pwrite
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahbeckford authored and Jonah Beckford committed Jun 1, 2022
1 parent f9f1221 commit 00c00ce
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
4 changes: 2 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
49 changes: 47 additions & 2 deletions src/unix/pread.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,53 @@
#include <caml/unixsupport.h>

#ifdef _MSC_VER
#include <Windows.h>
#include <BaseTsd.h>
#include <Intsafe.h>
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
Expand All @@ -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);
Expand All @@ -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);
Expand Down
46 changes: 44 additions & 2 deletions src/unix/pwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,50 @@
#include <caml/unixsupport.h>

#ifdef _MSC_VER
#include <Windows.h>
#include <BaseTsd.h>
#include <Intsafe.h>
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
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 00c00ce

Please sign in to comment.