RTDECL(int) RTPipeReadBlocking(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(pThis->fRead, VERR_ACCESS_DENIED); AssertPtr(pvBuf); int rc = rtPipeTryBlocking(pThis); if (RT_SUCCESS(rc)) { size_t cbTotalRead = 0; while (cbToRead > 0) { ssize_t cbRead = read(pThis->fd, pvBuf, RT_MIN(cbToRead, SSIZE_MAX)); if (cbRead < 0) { rc = RTErrConvertFromErrno(errno); break; } if (!cbRead && rtPipePosixHasHup(pThis)) { rc = VERR_BROKEN_PIPE; break; } /* advance */ pvBuf = (char *)pvBuf + cbRead; cbTotalRead += cbRead; cbToRead -= cbRead; } if (pcbRead) { *pcbRead = cbTotalRead; if ( RT_FAILURE(rc) && cbTotalRead && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } ASMAtomicDecU32(&pThis->u32State); } return rc; }
RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED); AssertPtr(pvBuf); AssertPtrNull(pcbWritten); int rc = rtPipeTryBlocking(pThis); if (RT_SUCCESS(rc)) { size_t cbTotalWritten = 0; while (cbToWrite > 0) { ssize_t cbWritten = write(pThis->fd, pvBuf, RT_MIN(cbToWrite, SSIZE_MAX)); if (cbWritten < 0) { rc = RTErrConvertFromErrno(errno); break; } /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } ASMAtomicDecU32(&pThis->u32State); } return rc; }
RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED); AssertPtr(pvBuf); AssertPtrNull(pcbWritten); int rc = RTCritSectEnter(&pThis->CritSect); if (RT_SUCCESS(rc)) { /* No concurrent readers, sorry. */ if (pThis->cUsers == 0) { pThis->cUsers++; /* * If I/O is pending, wait for it to complete. */ if (pThis->fIOPending) { rc = rtPipeWriteCheckCompletion(pThis); while (rc == VINF_TRY_AGAIN) { Assert(pThis->fIOPending); HANDLE hEvent = pThis->Overlapped.hEvent; RTCritSectLeave(&pThis->CritSect); WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); RTCritSectEnter(&pThis->CritSect); } } if (RT_SUCCESS(rc)) { Assert(!pThis->fIOPending); pThis->fPromisedWritable = false; /* * Try write everything. * No bounce buffering, cUsers protects us. */ size_t cbTotalWritten = 0; while (cbToWrite > 0) { rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE); pThis->fIOPending = true; RTCritSectLeave(&pThis->CritSect); DWORD cbWritten = 0; if (WriteFile(pThis->hPipe, pvBuf, cbToWrite <= ~(DWORD)0 ? (DWORD)cbToWrite : ~(DWORD)0, &cbWritten, &pThis->Overlapped)) rc = VINF_SUCCESS; else if (GetLastError() == ERROR_IO_PENDING) { WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); if (GetOverlappedResult(pThis->hPipe, &pThis->Overlapped, &cbWritten, TRUE /*fWait*/)) rc = VINF_SUCCESS; else rc = RTErrConvertFromWin32(GetLastError()); } else if (GetLastError() == ERROR_NO_DATA) rc = VERR_BROKEN_PIPE; else rc = RTErrConvertFromWin32(GetLastError()); RTCritSectEnter(&pThis->CritSect); pThis->fIOPending = false; if (RT_FAILURE(rc)) break; /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } } if (rc == VERR_BROKEN_PIPE) pThis->fBrokenPipe = true; pThis->cUsers--; } else rc = VERR_WRONG_ORDER; RTCritSectLeave(&pThis->CritSect); } return rc; #if 1 return VERR_NOT_IMPLEMENTED; #else int rc = rtPipeTryBlocking(pThis); if (RT_SUCCESS(rc)) { size_t cbTotalWritten = 0; while (cbToWrite > 0) { ssize_t cbWritten = write(pThis->fd, pvBuf, RT_MIN(cbToWrite, SSIZE_MAX)); if (cbWritten < 0) { rc = RTErrConvertFromErrno(errno); break; } /* advance */ pvBuf = (char const *)pvBuf + cbWritten; cbTotalWritten += cbWritten; cbToWrite -= cbWritten; } if (pcbWritten) { *pcbWritten = cbTotalWritten; if ( RT_FAILURE(rc) && cbTotalWritten && rc != VERR_INVALID_POINTER) rc = VINF_SUCCESS; } ASMAtomicDecU32(&pThis->u32State); } return rc; #endif }