/** * Read bytes from a file at a given offset into a S/G buffer. * This function may modify the file position. * * @returns iprt status code. * @param hFile Handle to the file. * @param off Where to read. * @param pSgBuf Pointer to the S/G buffer to read into. * @param cbToRead How much to read. * @param pcbRead How much we actually read. * If NULL an error will be returned for a partial read. */ RTR3DECL(int) RTFileSgReadAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToRead, size_t *pcbRead) { int rc = VINF_SUCCESS; size_t cbRead = 0; while (cbToRead) { size_t cbThisRead = 0; size_t cbBuf = cbToRead; void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf); rc = RTFileReadAt(hFile, off, pvBuf, cbBuf, pcbRead ? &cbThisRead : NULL); if (RT_SUCCESS(rc)) cbRead += cbThisRead; if ( RT_FAILURE(rc) || ( cbThisRead < cbBuf && pcbRead)) break; cbToRead -= cbBuf; off += cbBuf; } if (pcbRead) *pcbRead = cbRead; return rc; }
/** * Write bytes from a S/G buffer to a file at a given offset. * This function may modify the file position. * * @returns iprt status code. * @param hFile Handle to the file. * @param off Where to write. * @param pSgBuf What to write. * @param cbToWrite How much to write. * @param pcbWritten How much we actually wrote. * If NULL an error will be returned for a partial write. */ RTR3DECL(int) RTFileSgWriteAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToWrite, size_t *pcbWritten) { int rc = VINF_SUCCESS; size_t cbWritten = 0; while (cbToWrite) { size_t cbThisWritten = 0; size_t cbBuf = cbToWrite; void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf); rc = RTFileWriteAt(hFile, off, pvBuf, cbBuf, pcbWritten ? &cbThisWritten : NULL); if (RT_SUCCESS(rc)) cbWritten += cbThisWritten; if ( RT_FAILURE(rc) || ( cbThisWritten < cbBuf && pcbWritten)) break; cbToWrite -= cbBuf; off += cbBuf; } if (pcbWritten) *pcbWritten = cbWritten; return rc; }
/** * Writes data from the given S/G buffer into the I/O log. * * @returns VBox status code. * @param pIoLogger The I/O logger to use. * @param off The start offset in the log to write to. * @param pSgBuf The S/G buffer to write. * @param cbSgBuf How much data to write. */ static int vddbgIoLogWriteSgBuf(PVDIOLOGGERINT pIoLogger, uint64_t off, PCRTSGBUF pSgBuf, size_t cbSgBuf) { int rc = VINF_SUCCESS; RTSGBUF SgBuf; RTSgBufClone(&SgBuf, pSgBuf); while (cbSgBuf) { void *pvSeg; size_t cbSeg = cbSgBuf; pvSeg = RTSgBufGetNextSegment(&SgBuf, &cbSeg); AssertPtrBreakStmt(pvSeg, rc = VERR_INTERNAL_ERROR); rc = RTFileWriteAt(pIoLogger->hFile, off, pvSeg, cbSeg, NULL); if (RT_FAILURE(rc)) break; cbSgBuf -= cbSeg; off += cbSeg; } return rc; }