/**
 * 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;
}
Exemplo n.º 3
0
/**
 * 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;
}