diff options
author | Dhruva Krishnamurthy <dhruvakm@gmail.com> | 2020-06-17 14:31:11 -0700 |
---|---|---|
committer | Dhruva Krishnamurthy <dhruvakm@gmail.com> | 2020-12-30 06:55:40 -0800 |
commit | 4ce8e01a7ada3c75f7407dc9fafd25b4ac38d037 (patch) | |
tree | 526cd9e3bf31ffd6e9fce4993b649ce2875713c4 /src/win32 | |
parent | a9f57a8919f264fa184320d1f5c3ed7a35b7576a (diff) | |
download | libgit2-4ce8e01a7ada3c75f7407dc9fafd25b4ac38d037.tar.gz |
Support build with NO_MMAP to disable use of system mmap
* Use pread/pwrite to avoid updating position in file descriptor
* Emulate missing pread/pwrite on win32 using overlapped file IO
Diffstat (limited to 'src/win32')
-rw-r--r-- | src/win32/posix_w32.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 5a5e92158..0a8f2bee0 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -981,3 +981,73 @@ int p_inet_pton(int af, const char *src, void *dst) errno = EINVAL; return -1; } + +ssize_t p_pread(int fd, void *data, size_t size, off64_t offset) +{ + HANDLE fh; + DWORD rsize = 0; + OVERLAPPED ov = {0}; + LARGE_INTEGER pos = {0}; + off64_t final_offset = 0; + + /* Fail if the final offset would have overflowed to match POSIX semantics. */ + if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) { + errno = EINVAL; + return -1; + } + + /* + * Truncate large writes to the maximum allowable size: the caller + * needs to always call this in a loop anyways. + */ + if (size > INT32_MAX) { + size = INT32_MAX; + } + + pos.QuadPart = offset; + ov.Offset = pos.LowPart; + ov.OffsetHigh = pos.HighPart; + fh = (HANDLE)_get_osfhandle(fd); + + if (ReadFile(fh, data, (DWORD)size, &rsize, &ov)) { + return (ssize_t)rsize; + } + + set_errno(); + return -1; +} + +ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset) +{ + HANDLE fh; + DWORD wsize = 0; + OVERLAPPED ov = {0}; + LARGE_INTEGER pos = {0}; + off64_t final_offset = 0; + + /* Fail if the final offset would have overflowed to match POSIX semantics. */ + if (!git__is_ssizet(size) || git__add_int64_overflow(&final_offset, offset, (int64_t)size)) { + errno = EINVAL; + return -1; + } + + /* + * Truncate large writes to the maximum allowable size: the caller + * needs to always call this in a loop anyways. + */ + if (size > INT32_MAX) { + size = INT32_MAX; + } + + pos.QuadPart = offset; + ov.Offset = pos.LowPart; + ov.OffsetHigh = pos.HighPart; + fh = (HANDLE)_get_osfhandle(fd); + + if (WriteFile(fh, data, (DWORD)size, &wsize, &ov)) { + return (ssize_t)wsize; + } + + set_errno(); + return -1; +} |