diff --git a/posix/fd.cpp b/posix/fd.cpp index dc04de17..c910d8b1 100644 --- a/posix/fd.cpp +++ b/posix/fd.cpp @@ -180,14 +180,26 @@ fd::pwrite (const void *buf, size_t count, size_t offset) ::pwrite (native (), buf, count, offset) ); #else - DWORD written; - OVERLAPPED overlapped; - memset (&overlapped, 0, sizeof (overlapped)); - overlapped.Offset = offset & 0xffffffff; - overlapped.OffsetHigh = offset >> 32u; + // Ideally we'd to use something like WriteFile with an OVERLAPPED + // structure applied to the handle extracted with _get_osfhandle (m_fd). + // + // But this modifies the file cursor, and if we need to seek anyway then + // we may as well just emulate the entire with a query and two seeks. + // + // NOTE: It is thus possible to observe the fd with an 'incorrect' file + // pointer. Do not rely on POSIX behaviour across multiple threads. - if (!WriteFile (reinterpret_cast (_get_osfhandle (m_fd)), buf, count, &written, &overlapped)) - error::throw_code (EINVAL); + auto const initial = lseek (0, SEEK_CUR); + ssize_t written = -1; + try { + (void)lseek (offset, SEEK_SET); + written = write (buf, count); + } catch (...) { + (void)lseek (initial, SEEK_SET); + throw; + } + + (void)lseek (initial, SEEK_SET); return written; #endif }