static int pdmacFileEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize) { PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint; ASMAtomicWriteU64(&pEpFile->cbFile, cbSize); return RTFileSetSize(pEpFile->hFile, cbSize); }
void File::truncate() { int vrc = RTFileSetSize (m->handle, pos()); if (RT_SUCCESS (vrc)) return; throw EIPRTFailure(vrc, "Runtime error truncating file '%s'", m->strFileName.c_str()); }
static int pdmacFileEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize) { int rc; PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint; rc = RTFileSetSize(pEpFile->hFile, cbSize); if (RT_SUCCESS(rc)) ASMAtomicWriteU64(&pEpFile->cbFile, cbSize); return rc; }
static int fileSetSizeCallback(void * /* pvUser */, void *pvStorage, uint64_t cbSize) { /* Validate input. */ AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); PFILESTORAGEINTERNAL pInt = (PFILESTORAGEINTERNAL)pvStorage; DEBUG_PRINT_FLOW(); return RTFileSetSize(pInt->file, cbSize); }
VBOXDDU_DECL(int) VDDbgIoLogComplete(VDIOLOGGER hIoLogger, VDIOLOGENT hIoLogEntry, int rcReq, PCRTSGBUF pSgBuf) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; PVDIOLOGENTINT pIoLogEntry = hIoLogEntry; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(pIoLogEntry, VERR_INVALID_HANDLE); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); IoLogEntryComplete Entry; Entry.u32Type = VDIOLOG_EVENT_COMPLETE; Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart); Entry.msDuration = RTTimeProgramMilliTS() - RT_H2LE_U64(pIoLogEntry->tsStart); Entry.i32Rc = (int32_t)RT_H2LE_U32((uint32_t)rcReq); Entry.u64IoBuffer = RT_H2LE_U64(pIoLogEntry->cbIo); /* Write new entry. */ rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { pIoLogger->offWriteNext += sizeof(Entry); if (pIoLogEntry->cbIo) { rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, pIoLogEntry->cbIo); if (RT_SUCCESS(rc)) pIoLogger->offWriteNext += pIoLogEntry->cbIo; else { pIoLogger->offWriteNext -= sizeof(Entry); rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext); } } } RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry); RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser) { /* * Validate input. */ AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER); AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER); AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER); /* * Save file offset. */ RTFOFF offSrcSaved; int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved); if (RT_FAILURE(rc)) return rc; /* * Get the file size. */ RTFOFF cbSrc; rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc); if (RT_FAILURE(rc)) return rc; /* * Allocate buffer. */ size_t cbBuf; uint8_t *pbBufFree = NULL; uint8_t *pbBuf; if (cbSrc < _512K) { cbBuf = 8*_1K; pbBuf = (uint8_t *)alloca(cbBuf); } else { cbBuf = _128K; pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf); } if (pbBuf) { /* * Seek to the start of each file * and set the size of the destination file. */ rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) rc = RTFileSetSize(FileDst, cbSrc); if (RT_SUCCESS(rc) && pfnProgress) rc = pfnProgress(0, pvUser); if (RT_SUCCESS(rc)) { /* * Copy loop. */ unsigned uPercentage = 0; RTFOFF off = 0; RTFOFF cbPercent = cbSrc / 100; RTFOFF offNextPercent = cbPercent; while (off < cbSrc) { /* copy block */ RTFOFF cbLeft = cbSrc - off; size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft; rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL); if (RT_FAILURE(rc)) break; rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL); if (RT_FAILURE(rc)) break; /* advance */ off += cbBlock; if (pfnProgress && offNextPercent < off) { while (offNextPercent < off) { uPercentage++; offNextPercent += cbPercent; } rc = pfnProgress(uPercentage, pvUser); if (RT_FAILURE(rc)) break; } } #if 0 /* * Copy OS specific data (EAs and stuff). */ rtFileCopyOSStuff(FileSrc, FileDst); #endif /* 100% */ if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc)) rc = pfnProgress(100, pvUser); } } RTMemTmpFree(pbBufFree); } else rc = VERR_NO_MEMORY; /* * Restore source position. */ RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL); return rc; }
int main() { RTR3InitExeNoArguments(0); RTPrintf("tstFileLock: TESTING\n"); RTFILE File; int rc = RTFileOpen(&File, "tstLock.tst", RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); RTPrintf("File open: rc=%Rrc\n", rc); if (RT_FAILURE(rc)) { if (rc != VERR_FILE_NOT_FOUND && rc != VERR_OPEN_FAILED) { RTPrintf("FATAL\n"); return 1; } rc = RTFileOpen(&File, "tstLock.tst", RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_NONE); RTPrintf("File create: rc=%Rrc\n", rc); if (RT_FAILURE(rc)) { RTPrintf("FATAL\n"); return 2; } fRun = true; } /* grow file a little */ rc = RTFileSetSize(File, fRun ? 2048 : 20480); RTPrintf("File size: rc=%Rrc\n", rc); int buf; /* read test. */ rc = RTFileRead(File, &buf, sizeof(buf), NULL); RTPrintf("Read: rc=%Rrc\n", rc); /* write test. */ rc = RTFileWrite(File, achTest1, strlen(achTest1), NULL); RTPrintf("Write: rc=%Rrc\n", rc); /* lock: read, non-blocking. */ rc = RTFileLock(File, RTFILE_LOCK_READ | RTFILE_LOCK_IMMEDIATELY, 0, _4G); RTPrintf("Lock: read, non-blocking, rc=%Rrc\n", rc); bool fl = RT_SUCCESS(rc); /* read test. */ rc = RTFileRead(File, &buf, sizeof(buf), NULL); RTPrintf("Read: rc=%Rrc\n", rc); /* write test. */ rc = RTFileWrite(File, achTest2, strlen(achTest2), NULL); RTPrintf("Write: rc=%Rrc\n", rc); RTPrintf("Lock test will change in three seconds\n"); for (int i = 0; i < 3; i++) { RTThreadSleep(1000); RTPrintf("."); } RTPrintf("\n"); /* change lock: write, non-blocking. */ rc = RTFileLock(File, RTFILE_LOCK_WRITE | RTFILE_LOCK_IMMEDIATELY, 0, _4G); RTPrintf("Change lock: write, non-blocking, rc=%Rrc\n", rc); RTPrintf("Test will unlock in three seconds\n"); for (int i = 0; i < 3; i++) { RTThreadSleep(1000); RTPrintf("."); } RTPrintf("\n"); /* remove lock. */ if (fl) { fl = false; rc = RTFileUnlock(File, 0, _4G); RTPrintf("Unlock: rc=%Rrc\n", rc); RTPrintf("Write test will lock in three seconds\n"); for (int i = 0; i < 3; i++) { RTThreadSleep(1000); RTPrintf("."); } RTPrintf("\n"); } /* lock: write, non-blocking. */ rc = RTFileLock(File, RTFILE_LOCK_WRITE | RTFILE_LOCK_IMMEDIATELY, 0, _4G); RTPrintf("Lock: write, non-blocking, rc=%Rrc\n", rc); fl = RT_SUCCESS(rc); /* grow file test */ rc = RTFileSetSize(File, fRun ? 2048 : 20480); RTPrintf("File size: rc=%Rrc\n", rc); /* read test. */ rc = RTFileRead(File, &buf, sizeof(buf), NULL); RTPrintf("Read: rc=%Rrc\n", rc); /* write test. */ rc = RTFileWrite(File, achTest3, strlen(achTest3), NULL); RTPrintf("Write: rc=%Rrc\n", rc); RTPrintf("Continuing to next test in three seconds\n"); for (int i = 0; i < 3; i++) { RTThreadSleep(1000); RTPrintf("."); } RTPrintf("\n"); RTFileClose(File); RTFileDelete("tstLock.tst"); RTPrintf("tstFileLock: I've no recollection of this testcase succeeding or not, sorry.\n"); return 0; }
/** * Does one free space wipe, using the given filename. * * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure (fully * bitched). * @param pszFilename The filename to use for wiping free space. Will be * replaced and afterwards deleted. * @param pvFiller The filler block buffer. * @param cbFiller The size of the filler block buffer. * @param cbMinLeftOpt When to stop wiping. */ static RTEXITCODE doOneFreeSpaceWipe(const char *pszFilename, void const *pvFiller, size_t cbFiller, uint64_t cbMinLeftOpt) { /* * Open the file. */ RTEXITCODE rcExit = RTEXITCODE_SUCCESS; RTFILE hFile = NIL_RTFILE; int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_WRITE | RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | (0775 << RTFILE_O_CREATE_MODE_SHIFT)); if (RT_SUCCESS(rc)) { /* * Query the amount of available free space. Figure out which API we should use. */ RTFOFF cbTotal = 0; RTFOFF cbFree = 0; rc = RTFileQueryFsSizes(hFile, &cbTotal, &cbFree, NULL, NULL); bool const fFileHandleApiSupported = rc != VERR_NOT_SUPPORTED && rc != VERR_NOT_IMPLEMENTED; if (!fFileHandleApiSupported) rc = RTFsQuerySizes(pszFilename, &cbTotal, &cbFree, NULL, NULL); if (RT_SUCCESS(rc)) { RTPrintf("%s: %'9RTfoff MiB out of %'9RTfoff are free\n", pszFilename, cbFree / _1M, cbTotal / _1M); /* * Start filling up the free space, down to the last 32MB. */ uint64_t const nsStart = RTTimeNanoTS(); /* for speed calcs */ uint64_t nsStat = nsStart; /* for speed calcs */ uint64_t cbStatWritten = 0; /* for speed calcs */ RTFOFF const cbMinLeft = RT_MAX(cbMinLeftOpt, cbFiller * 2); RTFOFF cbLeftToWrite = cbFree - cbMinLeft; uint64_t cbWritten = 0; uint32_t iLoop = 0; while (cbLeftToWrite >= (RTFOFF)cbFiller) { rc = RTFileWrite(hFile, pvFiller, cbFiller, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_DISK_FULL) RTPrintf("%s: Disk full after writing %'9RU64 MiB\n", pszFilename, cbWritten / _1M); else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Write error after %'RU64 bytes: %Rrc\n", pszFilename, cbWritten, rc); break; } /* Flush every now and then as we approach a completely full disk. */ if (cbLeftToWrite <= _1G && (iLoop & (cbLeftToWrite > _128M ? 15 : 3)) == 0) RTFileFlush(hFile); /* * Advance and maybe recheck the amount of free space. */ cbWritten += cbFiller; cbLeftToWrite -= (ssize_t)cbFiller; iLoop++; if ((iLoop & (16 - 1)) == 0 || cbLeftToWrite < _256M) { RTFOFF cbFreeUpdated; if (fFileHandleApiSupported) rc = RTFileQueryFsSizes(hFile, NULL, &cbFreeUpdated, NULL, NULL); else rc = RTFsQuerySizes(pszFilename, NULL, &cbFreeUpdated, NULL, NULL); if (RT_SUCCESS(rc)) { cbFree = cbFreeUpdated; cbLeftToWrite = cbFree - cbMinLeft; } else { rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to query free space after %'RU64 bytes: %Rrc\n", pszFilename, cbWritten, rc); break; } if ((iLoop & (512 - 1)) == 0) { uint64_t const nsNow = RTTimeNanoTS(); uint64_t cNsInterval = nsNow - nsStat; uint64_t cbInterval = cbWritten - cbStatWritten; uint64_t cbIntervalPerSec = cbInterval ? (uint64_t)(cbInterval / (cNsInterval / (double)RT_NS_1SEC)) : 0; RTPrintf("%s: %'9RTfoff MiB out of %'9RTfoff are free after writing %'9RU64 MiB (%'5RU64 MiB/s)\n", pszFilename, cbFree / _1M, cbTotal / _1M, cbWritten / _1M, cbIntervalPerSec / _1M); nsStat = nsNow; cbStatWritten = cbWritten; } } } /* * Now flush the file and then reduce the size a little before closing * it so the system won't entirely run out of space. The flush should * ensure the data has actually hit the disk. */ rc = RTFileFlush(hFile); if (RT_FAILURE(rc)) rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Flush failed at %'RU64 bytes: %Rrc\n", pszFilename, cbWritten, rc); uint64_t cbReduced = cbWritten > _512M ? cbWritten - _512M : cbWritten / 2; rc = RTFileSetSize(hFile, cbReduced); if (RT_FAILURE(rc)) rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to reduce file size from %'RU64 to %'RU64 bytes: %Rrc\n", pszFilename, cbWritten, cbReduced, rc); /* Issue a summary statements. */ uint64_t cNsElapsed = RTTimeNanoTS() - nsStart; uint64_t cbPerSec = cbWritten ? (uint64_t)(cbWritten / (cNsElapsed / (double)RT_NS_1SEC)) : 0; RTPrintf("%s: Wrote %'RU64 MiB in %'RU64 s, avg %'RU64 MiB/s.\n", pszFilename, cbWritten / _1M, cNsElapsed / RT_NS_1SEC, cbPerSec / _1M); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Initial free space query failed: %Rrc \n", pszFilename, rc); RTFileClose(hFile); /* * Delete the file. */ rc = RTFileDelete(pszFilename); if (RT_FAILURE(rc)) rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Delete failed: %Rrc !!\n", pszFilename, rc); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Open failed: %Rrc\n", pszFilename, rc); return rcExit; }
/** * Processes a given task list for assigned to the given endpoint. */ static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTasks) { int rc = VINF_SUCCESS; while (pTasks) { RTMSINTERVAL msWhenNext; PPDMACTASKFILE pCurr = pTasks; if (!pdmacEpIsTransferAllowed(&pEndpoint->Core, (uint32_t)pCurr->DataSeg.cbSeg, &msWhenNext)) { pAioMgr->msBwLimitExpired = RT_MIN(pAioMgr->msBwLimitExpired, msWhenNext); break; } pTasks = pTasks->pNext; switch (pCurr->enmTransferType) { case PDMACTASKFILETRANSFER_FLUSH: { rc = RTFileFlush(pEndpoint->hFile); break; } case PDMACTASKFILETRANSFER_READ: case PDMACTASKFILETRANSFER_WRITE: { if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_READ) { rc = RTFileReadAt(pEndpoint->hFile, pCurr->Off, pCurr->DataSeg.pvSeg, pCurr->DataSeg.cbSeg, NULL); } else { if (RT_UNLIKELY((uint64_t)pCurr->Off + pCurr->DataSeg.cbSeg > pEndpoint->cbFile)) { ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg); RTFileSetSize(pEndpoint->hFile, pCurr->Off + pCurr->DataSeg.cbSeg); } rc = RTFileWriteAt(pEndpoint->hFile, pCurr->Off, pCurr->DataSeg.pvSeg, pCurr->DataSeg.cbSeg, NULL); } break; } default: AssertMsgFailed(("Invalid transfer type %d\n", pTasks->enmTransferType)); } pCurr->pfnCompleted(pCurr, pCurr->pvUser, rc); pdmacFileTaskFree(pEndpoint, pCurr); } if (pTasks) { /* Add the rest of the tasks to the pending list */ pdmacFileAioMgrEpAddTaskList(pEndpoint, pTasks); } return VINF_SUCCESS; }
VBOXDDU_DECL(int) VDDbgIoLogStartDiscard(VDIOLOGGER hIoLogger, bool fAsync, PCRTRANGE paRanges, unsigned cRanges, PVDIOLOGENT phIoLogEntry) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; PVDIOLOGENTINT pIoLogEntry = NULL; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries); if (pIoLogEntry) { IoLogEntryStart Entry; pIoLogEntry->idStart = pIoLogger->idNext++; Entry.u32Type = VDIOLOG_EVENT_START; Entry.u8AsyncIo = fAsync ? 1 : 0; Entry.u32ReqType = VDDBGIOLOGREQ_DISCARD; Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart); Entry.Discard.cRanges = RT_H2LE_U32(cRanges); /* Write new entry. */ rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { pIoLogger->offWriteNext += sizeof(Entry); IoLogEntryDiscard DiscardRange; for (unsigned i = 0; i < cRanges; i++) { DiscardRange.u64Off = RT_H2LE_U64(paRanges[i].offStart); DiscardRange.u32Discard = RT_H2LE_U32((uint32_t)paRanges[i].cbRange); rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext + i*sizeof(DiscardRange), &DiscardRange, sizeof(DiscardRange), NULL); if (RT_FAILURE(rc)) break; } if (RT_FAILURE(rc)) { pIoLogger->offWriteNext -= sizeof(Entry); rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext); } else pIoLogger->offWriteNext += cRanges * sizeof(DiscardRange); } if (RT_SUCCESS(rc)) { pIoLogEntry->tsStart = RTTimeProgramMilliTS(); pIoLogEntry->cbIo = 0; *phIoLogEntry = pIoLogEntry; } else { pIoLogger->idNext--; RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry); } } else rc = VERR_NO_MEMORY; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
VBOXDDU_DECL(int) VDDbgIoLogStart(VDIOLOGGER hIoLogger, bool fAsync, VDDBGIOLOGREQ enmTxDir, uint64_t off, size_t cbIo, PCRTSGBUF pSgBuf, PVDIOLOGENT phIoLogEntry) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; PVDIOLOGENTINT pIoLogEntry = NULL; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER); AssertReturn(enmTxDir > VDDBGIOLOGREQ_INVALID && enmTxDir <= VDDBGIOLOGREQ_FLUSH, VERR_INVALID_PARAMETER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries); if (pIoLogEntry) { IoLogEntryStart Entry; pIoLogEntry->idStart = pIoLogger->idNext++; Entry.u32Type = VDIOLOG_EVENT_START; Entry.u8AsyncIo = fAsync ? 1 : 0; Entry.u32ReqType = enmTxDir; Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart); Entry.Io.u64Off = RT_H2LE_U64(off); Entry.Io.u64IoSize = RT_H2LE_U64(cbIo); /* Write new entry. */ rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { pIoLogger->offWriteNext += sizeof(Entry); if ( enmTxDir == VDDBGIOLOGREQ_WRITE && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN)) { /* Write data. */ rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, cbIo); if (RT_FAILURE(rc)) { pIoLogger->offWriteNext -= sizeof(Entry); rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext); } else pIoLogger->offWriteNext += cbIo; } } if (RT_SUCCESS(rc)) { pIoLogEntry->tsStart = RTTimeProgramMilliTS(); if ( enmTxDir == VDDBGIOLOGREQ_READ && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_READ)) pIoLogEntry->cbIo = cbIo; else pIoLogEntry->cbIo = 0; *phIoLogEntry = pIoLogEntry; } else { pIoLogger->idNext--; RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry); } } else rc = VERR_NO_MEMORY; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
int main() { int cErrors = 0; RTPrintf("tstFile: TESTING\n"); RTR3InitExeNoArguments(0); RTFILE File; int rc = RTFileOpen(&File, "tstFile#1.tst", RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) { RTPrintf("tstFile: FATAL ERROR - Failed to open file #1. rc=%Rrc\n", rc); return 1; } RTFOFF cbMax = -2; rc = RTFileGetMaxSizeEx(File, &cbMax); if (RT_FAILURE(rc)) { RTPrintf("tstFile: RTFileGetMaxSizeEx failed: %Rrc\n", rc); cErrors++; } else if (cbMax <= 0) { RTPrintf("tstFile: RTFileGetMaxSizeEx failed: cbMax=%RTfoff\n", cbMax); cErrors++; } else if (RTFileGetMaxSize(File) != cbMax) { RTPrintf("tstFile: RTFileGetMaxSize failed; returns %RTfoff instead of %RTfoff\n", RTFileGetMaxSize(File), cbMax); cErrors++; } else RTPrintf("Maximum file size is %RTfoff bytes.\n", cbMax); /* grow file beyond 2G */ rc = RTFileSetSize(File, _2G + _1M); if (RT_FAILURE(rc)) { RTPrintf("Failed to grow file #1 to 2.001GB. rc=%Rrc\n", rc); cErrors++; } else { uint64_t cb; rc = RTFileGetSize(File, &cb); if (RT_FAILURE(rc)) { RTPrintf("Failed to get file size of #1. rc=%Rrc\n", rc); cErrors++; } else if (cb != _2G + _1M) { RTPrintf("RTFileGetSize return %RX64 bytes, expected %RX64.\n", cb, _2G + _1M); cErrors++; } else RTPrintf("tstFile: cb=%RX64\n", cb); /* * Try some writes at the beginning of the file. */ uint64_t offFile = RTFileTell(File); if (offFile != 0) { RTPrintf("RTFileTell -> %#RX64, expected 0 (#1)\n", offFile); cErrors++; } static const char szTestBuf[] = "Sausages and bacon for breakfast again!"; size_t cbWritten = 0; while (cbWritten < sizeof(szTestBuf)) { size_t cbWrittenPart; rc = RTFileWrite(File, &szTestBuf[cbWritten], sizeof(szTestBuf) - cbWritten, &cbWrittenPart); if (RT_FAILURE(rc)) break; cbWritten += cbWrittenPart; } if (RT_FAILURE(rc)) { RTPrintf("Failed to write to file #1 at offset 0. rc=%Rrc\n", rc); cErrors++; } else { /* check that it was written correctly. */ rc = RTFileSeek(File, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek offset 0 in file #1. rc=%Rrc\n", rc); cErrors++; } else { char szReadBuf[sizeof(szTestBuf)]; size_t cbRead = 0; while (cbRead < sizeof(szTestBuf)) { size_t cbReadPart; rc = RTFileRead(File, &szReadBuf[cbRead], sizeof(szTestBuf) - cbRead, &cbReadPart); if (RT_FAILURE(rc)) break; cbRead += cbReadPart; } if (RT_FAILURE(rc)) { RTPrintf("Failed to read from file #1 at offset 0. rc=%Rrc\n", rc); cErrors++; } else { if (!memcmp(szReadBuf, szTestBuf, sizeof(szTestBuf))) RTPrintf("tstFile: head write ok\n"); else { RTPrintf("Data read from file #1 at offset 0 differs from what we wrote there.\n"); cErrors++; } } } } /* * Try some writes at the end of the file. */ rc = RTFileSeek(File, _2G + _1M, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek to _2G + _1M in file #1. rc=%Rrc\n", rc); cErrors++; } else { offFile = RTFileTell(File); if (offFile != _2G + _1M) { RTPrintf("RTFileTell -> %#llx, expected %#llx (#2)\n", offFile, _2G + _1M); cErrors++; } else { cbWritten = 0; while (cbWritten < sizeof(szTestBuf)) { size_t cbWrittenPart; rc = RTFileWrite(File, &szTestBuf[cbWritten], sizeof(szTestBuf) - cbWritten, &cbWrittenPart); if (RT_FAILURE(rc)) break; cbWritten += cbWrittenPart; } if (RT_FAILURE(rc)) { RTPrintf("Failed to write to file #1 at offset 2G + 1M. rc=%Rrc\n", rc); cErrors++; } else { rc = RTFileSeek(File, offFile, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek offset %RX64 in file #1. rc=%Rrc\n", offFile, rc); cErrors++; } else { char szReadBuf[sizeof(szTestBuf)]; size_t cbRead = 0; while (cbRead < sizeof(szTestBuf)) { size_t cbReadPart; rc = RTFileRead(File, &szReadBuf[cbRead], sizeof(szTestBuf) - cbRead, &cbReadPart); if (RT_FAILURE(rc)) break; cbRead += cbReadPart; } if (RT_FAILURE(rc)) { RTPrintf("Failed to read from file #1 at offset 2G + 1M. rc=%Rrc\n", rc); cErrors++; } else { if (!memcmp(szReadBuf, szTestBuf, sizeof(szTestBuf))) RTPrintf("tstFile: tail write ok\n"); else { RTPrintf("Data read from file #1 at offset 2G + 1M differs from what we wrote there.\n"); cErrors++; } } } } } } /* * Some general seeking around. */ rc = RTFileSeek(File, _2G + 1, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek to _2G + 1 in file #1. rc=%Rrc\n", rc); cErrors++; } else { offFile = RTFileTell(File); if (offFile != _2G + 1) { RTPrintf("RTFileTell -> %#llx, expected %#llx (#3)\n", offFile, _2G + 1); cErrors++; } } /* seek end */ rc = RTFileSeek(File, 0, RTFILE_SEEK_END, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek to end of file #1. rc=%Rrc\n", rc); cErrors++; } else { offFile = RTFileTell(File); if (offFile != _2G + _1M + sizeof(szTestBuf)) /* assuming tail write was ok. */ { RTPrintf("RTFileTell -> %#RX64, expected %#RX64 (#4)\n", offFile, _2G + _1M + sizeof(szTestBuf)); cErrors++; } } /* seek start */ rc = RTFileSeek(File, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTPrintf("Failed to seek to end of file #1. rc=%Rrc\n", rc); cErrors++; } else { offFile = RTFileTell(File); if (offFile != 0) { RTPrintf("RTFileTell -> %#llx, expected 0 (#5)\n", offFile); cErrors++; } } } /* * Cleanup. */ rc = RTFileClose(File); if (RT_FAILURE(rc)) { RTPrintf("Failed to close file #1. rc=%Rrc\n", rc); cErrors++; } rc = RTFileDelete("tstFile#1.tst"); if (RT_FAILURE(rc)) { RTPrintf("Failed to delete file #1. rc=%Rrc\n", rc); cErrors++; } /* * Summary */ if (cErrors == 0) RTPrintf("tstFile: SUCCESS\n"); else RTPrintf("tstFile: FAILURE - %d errors\n", cErrors); return !!cErrors; }
/** * Modifies the autostart database. * * @returns VBox status code. * @param fAutostart Flag whether the autostart or autostop database is modified. * @param fAddVM Flag whether a VM is added or removed from the database. */ int AutostartDb::autostartModifyDb(bool fAutostart, bool fAddVM) { int rc = VINF_SUCCESS; char *pszUser = NULL; /* Check if the path is set. */ if (!m_pszAutostartDbPath) return VERR_PATH_NOT_FOUND; rc = RTProcQueryUsernameA(RTProcSelf(), &pszUser); if (RT_SUCCESS(rc)) { char *pszFile; uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE; RTFILE hAutostartFile; AssertPtr(pszUser); if (fAddVM) fOpen |= RTFILE_O_OPEN_CREATE; else fOpen |= RTFILE_O_OPEN; rc = RTStrAPrintf(&pszFile, "%s/%s.%s", m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop"); if (RT_SUCCESS(rc)) { rc = RTFileOpen(&hAutostartFile, pszFile, fOpen); if (RT_SUCCESS(rc)) { uint64_t cbFile; /* * Files with more than 16 bytes are rejected because they just contain * a number of the amount of VMs with autostart configured, so they * should be really really small. Anything else is bogus. */ rc = RTFileGetSize(hAutostartFile, &cbFile); if ( RT_SUCCESS(rc) && cbFile <= 16) { char abBuf[16 + 1]; /* trailing \0 */ uint32_t cAutostartVms = 0; RT_ZERO(abBuf); /* Check if the file was just created. */ if (cbFile) { rc = RTFileRead(hAutostartFile, abBuf, cbFile, NULL); if (RT_SUCCESS(rc)) { rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms); if ( rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES) rc = VINF_SUCCESS; } } if (RT_SUCCESS(rc)) { size_t cbBuf; /* Modify VM counter and write back. */ if (fAddVM) cAutostartVms++; else cAutostartVms--; if (cAutostartVms > 0) { cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms); rc = RTFileSetSize(hAutostartFile, cbBuf); if (RT_SUCCESS(rc)) rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL); } else { /* Just delete the file if there are no VMs left. */ RTFileClose(hAutostartFile); RTFileDelete(pszFile); hAutostartFile = NIL_RTFILE; } } } else if (RT_SUCCESS(rc)) rc = VERR_FILE_TOO_BIG; if (hAutostartFile != NIL_RTFILE) RTFileClose(hAutostartFile); } RTStrFree(pszFile); } RTStrFree(pszUser); } return rc; }