/** * Writes a GSO frame to a file. * * @returns IPRT status code, @see RTFileWrite. * * @param File The file handle. * @param StartNanoTS What to subtract from the RTTimeNanoTS output. * @param pGso Pointer to the GSO context. * @param pvFrame The start of the GSO frame. * @param cbFrame The size of the GSO frame. * @param cbSegMax The max number of bytes to include in the file for * each segment. */ int PcapFileGsoFrame(RTFILE File, uint64_t StartNanoTS, PCPDMNETWORKGSO pGso, const void *pvFrame, size_t cbFrame, size_t cbSegMax) { struct pcaprec_hdr Hdr; pcapCalcHeader(&Hdr, StartNanoTS, 0, 0); uint8_t const *pbFrame = (uint8_t const *)pvFrame; uint8_t abHdrs[256]; uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame); for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++) { uint32_t cbSegPayload; uint32_t offSegPayload = PDMNetGsoCarveSegment(pGso, pbFrame, cbFrame, iSeg, cSegs, abHdrs, &cbSegPayload); pcapUpdateHeader(&Hdr, pGso->cbHdrs + cbSegPayload, cbSegMax); int rc = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL); if (RT_FAILURE(rc)) return rc; rc = RTFileWrite(File, abHdrs, RT_MIN(Hdr.incl_len, pGso->cbHdrs), NULL); if (RT_SUCCESS(rc) && Hdr.incl_len > pGso->cbHdrs) rc = RTFileWrite(File, pbFrame + offSegPayload, Hdr.incl_len - pGso->cbHdrs, NULL); if (RT_FAILURE(rc)) return rc; } return VINF_SUCCESS; }
/** * Writes a frame to a file. * * @returns IPRT status code, @see RTFileWrite. * * @param File The file handle. * @param StartNanoTS What to subtract from the RTTimeNanoTS output. * @param pvFrame The start of the frame. * @param cbFrame The size of the frame. * @param cbMax The max number of bytes to include in the file. */ int PcapFileFrame(RTFILE File, uint64_t StartNanoTS, const void *pvFrame, size_t cbFrame, size_t cbMax) { struct pcaprec_hdr Hdr; pcapCalcHeader(&Hdr, StartNanoTS, cbFrame, cbMax); int rc1 = RTFileWrite(File, &Hdr, sizeof(Hdr), NULL); int rc2 = RTFileWrite(File, pvFrame, Hdr.incl_len, NULL); return RT_SUCCESS(rc1) ? rc2 : rc1; }
/** * Commits the current block to the capture file. * * @returns VBox status code. * @param pThis The VUSB sniffer instance. */ static int vusbSnifferBlockCommit(PVUSBSNIFFERINT pThis) { int rc = VINF_SUCCESS; AssertPtr(pThis->pBlockHdr); rc = vusbSnifferBlockAlign(pThis); if (RT_SUCCESS(rc)) { /* Update the block total length field. */ uint32_t *pcbTotalLength = (uint32_t *)vusbSnifferBlockAllocSpace(pThis, 4); if (pcbTotalLength) { *pcbTotalLength = pThis->cbBlockCur; pThis->pBlockHdr->u32BlockTotalLength = pThis->cbBlockCur; /* Write the data. */ rc = RTFileWrite(pThis->hFile, pThis->pbBlockData, pThis->cbBlockCur, NULL); pThis->cbBlockCur = 0; pThis->pBlockHdr = NULL; } else rc = VERR_NO_MEMORY; } return rc; }
/** * Writes the stream to a file. * * @returns IPRT status code * @param pStream The stream. * @param pszFilenameFmt The filename format string. * @param ... Format arguments. */ int ScmStreamWriteToFile(PSCMSTREAM pStream, const char *pszFilenameFmt, ...) { int rc; #ifdef RT_STRICT /* * Check that what we're going to write makes sense first. */ rc = ScmStreamCheckItegrity(pStream); if (RT_FAILURE(rc)) return rc; #endif /* * Do the actual writing. */ RTFILE hFile; va_list va; va_start(va, pszFilenameFmt); rc = RTFileOpenV(&hFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE, pszFilenameFmt, va); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, pStream->pch, pStream->cb, NULL); RTFileClose(hFile); } va_end(va); return rc; }
/** * Creates a PID File and returns the open file descriptor. * * On DOS based system, file sharing (deny write) is used for locking the PID * file. * * On Unix-y systems, an exclusive advisory lock is used for locking the PID * file since the file sharing support is usually missing there. * * This API will overwrite any existing PID Files without a lock on them, on the * assumption that they are stale files which an old process did not properly * clean up. * * @returns IPRT status code. * @param pszPath The path and filename to create the PID File under * @param phFile Where to store the file descriptor of the open (and locked * on Unix-y systems) PID File. On failure, or if another * process owns the PID File, this will be set to NIL_RTFILE. */ VBGLR3DECL(int) VbglR3PidFile(const char *pszPath, PRTFILE phFile) { AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER); AssertPtrReturn(phFile, VERR_INVALID_PARAMETER); *phFile = NIL_RTFILE; RTFILE hPidFile; int rc = RTFileOpen(&hPidFile, pszPath, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | (0644 << RTFILE_O_CREATE_MODE_SHIFT)); if (RT_SUCCESS(rc)) { #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) /** @todo using size 0 for locking means lock all on Posix. * We should adopt this as our convention too, or something * similar. */ rc = RTFileLock(hPidFile, RTFILE_LOCK_WRITE, 0, 0); if (RT_FAILURE(rc)) RTFileClose(hPidFile); else #endif { char szBuf[256]; size_t cbPid = RTStrPrintf(szBuf, sizeof(szBuf), "%d\n", RTProcSelf()); RTFileWrite(hPidFile, szBuf, cbPid, NULL); *phFile = hPidFile; } } return rc; }
/** * Writes the stream to standard output. * * @returns IPRT status code * @param pStream The stream. */ int ScmStreamWriteToStdOut(PSCMSTREAM pStream) { int rc; #ifdef RT_STRICT /* * Check that what we're going to write makes sense first. */ rc = ScmStreamCheckItegrity(pStream); if (RT_FAILURE(rc)) return rc; #endif /* * Do the actual writing. */ RTHANDLE h; rc = RTHandleGetStandard(RTHANDLESTD_OUTPUT, &h); if (RT_SUCCESS(rc)) { switch (h.enmType) { case RTHANDLETYPE_FILE: rc = RTFileWrite(h.u.hFile, pStream->pch, pStream->cb, NULL); break; case RTHANDLETYPE_PIPE: rc = RTPipeWriteBlocking(h.u.hPipe, pStream->pch, pStream->cb, NULL); break; default: rc = VERR_INVALID_HANDLE; break; } } return rc; }
/** * ELF function to write 64-bit ELF header. * * @param hFile The file to write to. * @param cProgHdrs Number of program headers. * @param cSecHdrs Number of section headers. * * @return IPRT status code. */ static int Elf64WriteElfHdr(RTFILE hFile, uint16_t cProgHdrs, uint16_t cSecHdrs) { Elf64_Ehdr ElfHdr; RT_ZERO(ElfHdr); ElfHdr.e_ident[EI_MAG0] = ELFMAG0; ElfHdr.e_ident[EI_MAG1] = ELFMAG1; ElfHdr.e_ident[EI_MAG2] = ELFMAG2; ElfHdr.e_ident[EI_MAG3] = ELFMAG3; ElfHdr.e_ident[EI_DATA] = ELFDATA2LSB; ElfHdr.e_type = ET_CORE; ElfHdr.e_version = EV_CURRENT; ElfHdr.e_ident[EI_CLASS] = ELFCLASS64; /* 32-bit builds will produce cores with e_machine EM_386. */ #ifdef RT_ARCH_AMD64 ElfHdr.e_machine = EM_X86_64; #else ElfHdr.e_machine = EM_386; #endif ElfHdr.e_phnum = cProgHdrs; ElfHdr.e_shnum = cSecHdrs; ElfHdr.e_ehsize = sizeof(ElfHdr); ElfHdr.e_phoff = sizeof(ElfHdr); ElfHdr.e_phentsize = sizeof(Elf64_Phdr); ElfHdr.e_shentsize = sizeof(Elf64_Shdr); return RTFileWrite(hFile, &ElfHdr, sizeof(ElfHdr), NULL /* all */); }
/** * Handles VMMDevCpuEventType_Unplug. * * @param idCpuCore The CPU core ID. * @param idCpuPackage The CPU package ID. */ static void VBoxServiceCpuHotPlugHandleUnplugEvent(uint32_t idCpuCore, uint32_t idCpuPackage) { #ifdef RT_OS_LINUX char *pszCpuDevicePath = NULL; int rc = VBoxServiceCpuHotPlugGetACPIDevicePath(&pszCpuDevicePath, idCpuCore, idCpuPackage); if (RT_SUCCESS(rc)) { RTFILE hFileCpuEject; rc = RTFileOpenF(&hFileCpuEject, RTFILE_O_WRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, "%s/eject", pszCpuDevicePath); if (RT_SUCCESS(rc)) { /* Write a 1 to eject the CPU */ rc = RTFileWrite(hFileCpuEject, "1", 1, NULL); if (RT_SUCCESS(rc)) VBoxServiceVerbose(1, "CpuHotPlug: CPU %u/%u was ejected\n", idCpuPackage, idCpuCore); else VBoxServiceError("CpuHotPlug: Failed to eject CPU %u/%u rc=%Rrc\n", idCpuPackage, idCpuCore, rc); RTFileClose(hFileCpuEject); } else VBoxServiceError("CpuHotPlug: Failed to open \"%s/eject\" rc=%Rrc\n", pszCpuDevicePath, rc); RTStrFree(pszCpuDevicePath); } else VBoxServiceError("CpuHotPlug: Failed to get CPU device path rc=%Rrc\n", rc); #else # error "Port me" #endif }
/** * Write bytes to a file at a given offset. * This function may modify the file position. * * @returns iprt status code. * @param File Handle to the file. * @param off Where to write. * @param pvBuf 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) RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) { int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) rc = RTFileWrite(File, pvBuf, cbToWrite, pcbWritten); return rc; }
static size_t rtHttpWriteDataToFile(void *pvBuf, size_t cb, size_t n, void *pvUser) { size_t cbAll = cb * n; RTFILE hFile = (RTFILE)(intptr_t)pvUser; size_t cbWritten = 0; int rc = RTFileWrite(hFile, pvBuf, cbAll, &cbWritten); if (RT_SUCCESS(rc)) return cbWritten; return 0; }
int File::write(const char *aBuf, int aLen) { size_t len = aLen; int vrc = RTFileWrite (m->handle, aBuf, len, &len); if (RT_SUCCESS (vrc)) return (int)len; throw EIPRTFailure(vrc, "Runtime error writing to file '%s'", m->strFileName.c_str()); return -1 /* failure */; }
void GuestProcessStream::Dump(const char *pszFile) { LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n", m_pbBuffer, m_cbAllocated, m_cbSize, m_cbOffset, pszFile)); RTFILE hFile; int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, m_pbBuffer, m_cbSize, NULL /* pcbWritten */); RTFileClose(hFile); } }
static void benchmarkFileWriteByte(void) { RTTestSub(g_hTest, "RTFileWrite(byte)"); RTFILE hFile; RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFile, g_szTestFile1, RTFILE_O_WRITE | RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | (0655 << RTFILE_O_CREATE_MODE_SHIFT)), VINF_SUCCESS); static const char s_szContent[] = "0123456789abcdef"; uint32_t offContent = 0; int rc;; RTTESTI_CHECK_RC(rc = RTFileWrite(hFile, &s_szContent[offContent++ % RT_ELEMENTS(s_szContent)], 1, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) { TIME_OP(RTFileWrite(hFile, &s_szContent[offContent++ % RT_ELEMENTS(s_szContent)], 1, NULL), "RTFileWrite(byte)"); } RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); RTTestSubDone(g_hTest); }
/** * ELF function to write 64-bit program header. * * @param hFile The file to write to. * @param Type Type of program header (PT_*). * @param fFlags Flags (access permissions, PF_*). * @param offFileData File offset of contents. * @param cbFileData Size of contents in the file. * @param cbMemData Size of contents in memory. * @param Phys Physical address, pass zero if not applicable. * * @return IPRT status code. */ static int Elf64WriteProgHdr(RTFILE hFile, uint32_t Type, uint32_t fFlags, uint64_t offFileData, uint64_t cbFileData, uint64_t cbMemData, RTGCPHYS Phys) { Elf64_Phdr ProgHdr; RT_ZERO(ProgHdr); ProgHdr.p_type = Type; ProgHdr.p_flags = fFlags; ProgHdr.p_offset = offFileData; ProgHdr.p_filesz = cbFileData; ProgHdr.p_memsz = cbMemData; ProgHdr.p_paddr = Phys; return RTFileWrite(hFile, &ProgHdr, sizeof(ProgHdr), NULL /* all */); }
int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten) { AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf, VERR_INVALID_PARAMETER); /* pcbWritten is optional. */ size_t cbWritten = 0; int rc; switch (m_Type) { case File: { rc = OpenEx(m_strTgtPath, File, Target, /* Use some sensible defaults. */ RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE, 0 /* fFlags */); if (RT_SUCCESS(rc)) { rc = RTFileWrite(u.m_hFile, pvBuf, cbBuf, &cbWritten); if (RT_SUCCESS(rc)) m_cbProcessed += cbWritten; } break; } case Directory: { rc = VINF_SUCCESS; break; } default: rc = VERR_NOT_IMPLEMENTED; break; } if (RT_SUCCESS(rc)) { if (pcbWritten) *pcbWritten = (uint32_t)cbWritten; } LogFlowFunc(("Returning strSourcePath=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbWritten, rc)); return rc; }
RTR3DECL(int) RTTarClose(RTTAR hTar) { if (hTar == NIL_RTTAR) return VINF_SUCCESS; PRTTARINTERNAL pInt = hTar; RTTAR_VALID_RETURN(pInt); int rc = VINF_SUCCESS; /* gtar gives a warning, but the documentation says EOF is indicated by a * zero block. Disabled for now. */ #if 0 { /* Append the EOF record which is filled all by zeros */ RTTARRECORD record; RT_ZERO(record); rc = RTFileWrite(pInt->hTarFile, &record, sizeof(record), NULL); } #endif if (pInt->hVfsFss != NIL_RTVFSFSSTREAM) { uint32_t cRefs = RTVfsFsStrmRelease(pInt->hVfsFss); Assert(cRefs != UINT32_MAX); pInt->hVfsFss = NIL_RTVFSFSSTREAM; } if (pInt->hVfsFile != NIL_RTVFSFILE) { uint32_t cRefs = RTVfsFileRelease(pInt->hVfsFile); Assert(cRefs != UINT32_MAX); pInt->hVfsFile = NIL_RTVFSFILE; } if (pInt->hTarFile != NIL_RTFILE) { rc = RTFileClose(pInt->hTarFile); pInt->hTarFile = NIL_RTFILE; } pInt->u32Magic = RTTAR_MAGIC_DEAD; RTMemFree(pInt); return rc; }
/** * Writes data to an object. Only applies to file objects. * * @return IPRT status code. * @param pvBuf Buffer of data to write. * @param cbBuf Size (in bytes) of data to write. * @param pcbWritten Pointer where to store how many bytes were written. Optional. */ int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten) { AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf, VERR_INVALID_PARAMETER); /* pcbWritten is optional. */ AssertMsgReturn(m_enmView == View_Target, ("Cannot write to an object which is not in target view\n"), VERR_INVALID_STATE); size_t cbWritten = 0; int rc; switch (m_enmType) { case Type_File: { rc = RTFileWrite(u.File.hFile, pvBuf, cbBuf, &cbWritten); if (RT_SUCCESS(rc)) u.File.cbProcessed += cbWritten; break; } case Type_Directory: { rc = VINF_SUCCESS; break; } default: rc = VERR_NOT_IMPLEMENTED; break; } if (RT_SUCCESS(rc)) { if (pcbWritten) *pcbWritten = (uint32_t)cbWritten; } LogFlowThisFunc(("Returning strSourcePathAbs=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPathAbs.c_str(), cbWritten, rc)); 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() { 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; }
static int vbglR3DnDHGProcessURIMessages(uint32_t uClientId, uint32_t *puScreenId, char *pszFormat, uint32_t cbFormat, uint32_t *pcbFormatRecv, void **ppvData, uint32_t cbData, size_t *pcbDataRecv) { /* Make a string list out of the uri data. */ RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); if (uriList.isEmpty()) return VINF_SUCCESS; uint32_t cbTmpData = _1M * 10; void *pvTmpData = RTMemAlloc(cbTmpData); if (!pvTmpData) return VERR_NO_MEMORY; /* Create and query the drop target directory. */ char pszDropDir[RTPATH_MAX]; int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir)); if (RT_FAILURE(rc)) { RTMemFree(pvTmpData); return rc; } /* Patch the old drop data with the new drop directory, so the drop target * can find the files. */ RTCList<RTCString> guestUriList; for (size_t i = 0; i < uriList.size(); ++i) { const RTCString &strUri = uriList.at(i); /* Query the path component of a file URI. If this hasn't a * file scheme, null is returned. */ if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO)) { RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); if (pszNewUri) { guestUriList.append(pszNewUri); RTStrFree(pszNewUri); } } else guestUriList.append(strUri); } /* Cleanup the old data and write the new data back to the event. */ RTMemFree(*ppvData); RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n"; *ppvData = RTStrDupN(newData.c_str(), newData.length()); *pcbDataRecv = newData.length() + 1; /* Lists for holding created files & directories in the case of a * rollback. */ RTCList<RTCString> guestDirList; RTCList<RTCString> guestFileList; char pszPathname[RTPATH_MAX]; uint32_t cbPathname = 0; bool fLoop = true; do { uint32_t uNextMsg; uint32_t cNextParms; rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false); DO(("%Rrc - %d\n", rc , uNextMsg)); if (RT_SUCCESS(rc)) { switch(uNextMsg) { case DragAndDropSvc::HOST_DND_HG_SND_DIR: { uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendDirMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, &fMode); if (RT_SUCCESS(rc)) { DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc)); char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname); rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); if (!guestDirList.contains(pszNewDir)) guestDirList.append(pszNewDir); } break; } case DragAndDropSvc::HOST_DND_HG_SND_FILE: { uint32_t cbDataRecv; uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendFileMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, pvTmpData, cbTmpData, &cbDataRecv, &fMode); if (RT_SUCCESS(rc)) { char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname); DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc)); RTFILE hFile; rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE); if (RT_SUCCESS(rc)) { rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0); /* Valid UNIX mode? */ if ( RT_SUCCESS(rc) && (fMode & RTFS_UNIX_MASK)) rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); } RTFileClose(hFile); if (!guestFileList.contains(pszNewFile)) guestFileList.append(pszNewFile); } } break; } case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: { rc = vbglR3DnDHGProcessCancelMessage(uClientId); if (RT_SUCCESS(rc)) rc = VERR_CANCELLED; /* Break out of the loop. */ } default: fLoop = false; break; } } else { if (rc == VERR_NO_DATA) rc = VINF_SUCCESS; break; } }while(fLoop); RTMemFree(pvTmpData); /* Cleanup on failure or if the user has canceled. */ if (RT_FAILURE(rc)) { /* Remove any stuff created. */ for (size_t i = 0; i < guestFileList.size(); ++i) RTFileDelete(guestFileList.at(i).c_str()); for (size_t i = 0; i < guestDirList.size(); ++i) RTDirRemove(guestDirList.at(i).c_str()); RTDirRemove(pszDropDir); } return rc; }
RTR3DECL(int) RTTarFileOpen(RTTAR hTar, PRTTARFILE phFile, const char *pszFilename, uint32_t fOpen) { /* Write only interface now. */ AssertReturn(fOpen & RTFILE_O_WRITE, VERR_INVALID_PARAMETER); PRTTARINTERNAL pInt = hTar; RTTAR_VALID_RETURN(pInt); if (!pInt->hTarFile) return VERR_INVALID_HANDLE; if (fOpen & RTFILE_O_WRITE) { if (!(pInt->fOpenMode & RTFILE_O_WRITE)) return VERR_WRITE_PROTECT; if (pInt->fFileOpenForWrite) return VERR_TOO_MANY_OPEN_FILES; } int rc = VINF_SUCCESS; if (!(fOpen & RTFILE_O_WRITE)) { /* * Rewind the stream if necessary. */ if (!pInt->fFssAtStart) { if (pInt->hVfsFss != NIL_RTVFSFSSTREAM) { uint32_t cRefs = RTVfsFsStrmRelease(pInt->hVfsFss); Assert(cRefs != UINT32_MAX); pInt->hVfsFss = NIL_RTVFSFSSTREAM; } if (pInt->hVfsFile == NIL_RTVFSFILE) { rc = RTVfsFileFromRTFile(pInt->hTarFile, RTFILE_O_READ, true /*fLeaveOpen*/, &pInt->hVfsFile); if (RT_FAILURE(rc)) return rc; } RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(pInt->hVfsFile); rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0 /*fFlags*/, &pInt->hVfsFss); RTVfsIoStrmRelease(hVfsIos); if (RT_FAILURE(rc)) return rc; } /* * Search the file system stream. */ pInt->fFssAtStart = false; for (;;) { char *pszName; RTVFSOBJTYPE enmType; RTVFSOBJ hVfsObj; rc = RTVfsFsStrmNext(pInt->hVfsFss, &pszName, &enmType, &hVfsObj); if (rc == VERR_EOF) return VERR_FILE_NOT_FOUND; if (RT_FAILURE(rc)) return rc; if (!RTStrCmp(pszName, pszFilename)) { if (enmType == RTVFSOBJTYPE_FILE || enmType == RTVFSOBJTYPE_IO_STREAM) rc = rtTarFileCreateHandleForReadOnly(pszName, RTVfsObjToIoStream(hVfsObj), fOpen, phFile); else { rc = VERR_UNEXPECTED_FS_OBJ_TYPE; RTStrFree(pszName); } RTVfsObjRelease(hVfsObj); break; } RTStrFree(pszName); RTVfsObjRelease(hVfsObj); } /* Search loop. */ } else { PRTTARFILEINTERNAL pFileInt = rtTarFileCreateForWrite(pInt, pszFilename, fOpen); if (!pFileInt) return VERR_NO_MEMORY; pInt->fFileOpenForWrite = true; /* If we are in write mode, we also in append mode. Add an dummy * header at the end of the current file. It will be filled by the * close operation. */ rc = RTFileSeek(pFileInt->pTar->hTarFile, 0, RTFILE_SEEK_END, &pFileInt->offStart); if (RT_SUCCESS(rc)) { RTTARRECORD record; RT_ZERO(record); rc = RTFileWrite(pFileInt->pTar->hTarFile, &record, sizeof(RTTARRECORD), NULL); } if (RT_SUCCESS(rc)) *phFile = (RTTARFILE)pFileInt; else { /* Cleanup on failure */ if (pFileInt->pszFilename) RTStrFree(pFileInt->pszFilename); RTMemFree(pFileInt); } } return rc; }
HRESULT Guest::taskCopyFileFromGuest(GuestTask *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* * Do *not* take a write lock here since we don't (and won't) * touch any class-specific data (of IGuest) here - only the member functions * which get called here can do that. */ HRESULT rc = S_OK; try { ComObjPtr<Guest> pGuest = aTask->pGuest; /* Does our source file exist? */ BOOL fFileExists; rc = pGuest->FileExists(Bstr(aTask->strSource).raw(), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), &fFileExists); if (SUCCEEDED(rc)) { if (!fFileExists) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Source file \"%s\" does not exist, or is not a file"), aTask->strSource.c_str()); } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); /* Query file size to make an estimate for our progress object. */ if (SUCCEEDED(rc)) { LONG64 lFileSize; rc = pGuest->FileQuerySize(Bstr(aTask->strSource).raw(), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), &lFileSize); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; if (SUCCEEDED(rc)) { /* * Prepare tool command line. */ char szSource[RTPATH_MAX]; if (RTStrPrintf(szSource, sizeof(szSource), "%s", aTask->strSource.c_str()) <= sizeof(szSource) - 1) { /* * Normalize path slashes, based on the detected guest. */ Utf8Str osType = mData.mOSTypeId; if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) || osType.contains("Windows", Utf8Str::CaseInsensitive)) { /* We have a Windows guest. */ RTPathChangeToDosSlashes(szSource, true /* Force conversion. */); } else /* ... or something which isn't from Redmond ... */ { RTPathChangeToUnixSlashes(szSource, true /* Force conversion. */); } args.push_back(Bstr(szSource).raw()); /* Tell our cat tool which file to output. */ } else rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error preparing command line")); } ComPtr<IProgress> execProgress; ULONG uPID; if (SUCCEEDED(rc)) { LogRel(("Copying file \"%s\" to host \"%s\" (%u bytes) ...\n", aTask->strSource.c_str(), aTask->strDest.c_str(), lFileSize)); /* * Okay, since we gathered all stuff we need until now to start the * actual copying, start the guest part now. */ rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(), Bstr("Copying file to host").raw(), ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), ExecuteProcessFlag_WaitForProcessStartOnly | ExecuteProcessFlag_WaitForStdOut, NULL, NULL, execProgress.asOutParam(), &uPID); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } if (SUCCEEDED(rc)) { BOOL fCompleted = FALSE; BOOL fCanceled = FALSE; RTFILE hFileDest; int vrc = RTFileOpen(&hFileDest, aTask->strDest.c_str(), RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); if (RT_FAILURE(vrc)) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Unable to create/open destination file \"%s\", rc=%Rrc"), aTask->strDest.c_str(), vrc); else { size_t cbToRead = lFileSize; size_t cbTransfered = 0; while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { SafeArray<BYTE> aOutputData; rc = pGuest->GetProcessOutput(uPID, ProcessOutputFlag_None /* StdOut */, 0 /* No timeout. */, _64K, ComSafeArrayAsOutParam(aOutputData)); if (SUCCEEDED(rc)) { if (aOutputData.size()) { vrc = RTFileWrite(hFileDest, aOutputData.raw(), aOutputData.size(), NULL /* No partial writes */); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error writing to file \"%s\" (%u bytes left), rc=%Rrc"), aTask->strSource.c_str(), cbToRead, vrc); break; } Assert(cbToRead >= aOutputData.size()); cbToRead -= aOutputData.size(); cbTransfered += aOutputData.size(); aTask->pProgress->SetCurrentOperationProgress(cbTransfered / (lFileSize / 100.0)); } /* Nothing read this time; try next round. */ } else { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } } RTFileClose(hFileDest); if (SUCCEEDED(rc)) { if ( cbTransfered && (cbTransfered != lFileSize)) { /* * Only bitch about an unexpected end of a file when there already * was data read from that file. If this was the very first read we can * be (almost) sure that this file is not meant to be read by the specified user. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Unexpected end of file \"%s\" (%u bytes total, %u bytes transferred)"), aTask->strSource.c_str(), lFileSize, cbTransfered); } if (SUCCEEDED(rc)) aTask->pProgress->notifyComplete(S_OK); } } } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
/** * Handles VMMDevCpuEventType_Plug. * * @param idCpuCore The CPU core ID. * @param idCpuPackage The CPU package ID. */ static void VBoxServiceCpuHotPlugHandlePlugEvent(uint32_t idCpuCore, uint32_t idCpuPackage) { #ifdef RT_OS_LINUX /* * The topology directory (containing the physical and core id properties) * is not available until the CPU is online. So we just iterate over all directories * and enable every CPU which is not online already. * Because the directory might not be available immediately we try a few times. * * @todo: Maybe use udev to monitor hot-add events from the kernel */ bool fCpuOnline = false; unsigned cTries = 5; do { PRTDIR pDirDevices = NULL; int rc = RTDirOpen(&pDirDevices, SYSFS_CPU_PATH); if (RT_SUCCESS(rc)) { RTDIRENTRY DirFolderContent; while (RT_SUCCESS(RTDirRead(pDirDevices, &DirFolderContent, NULL))) /* Assumption that szName has always enough space */ { /** @todo r-bird: This code is bringing all CPUs online; the idCpuCore and * idCpuPackage parameters are unused! * aeichner: These files are not available at this point unfortunately. (see comment above) * bird: Yes, but isn't that easily dealt with by doing: * if (matching_topology() || !have_topology_directory()) * bring_cpu_online() * That could save you the cpu0 and cpuidle checks to. */ /* * Check if this is a CPU object. * cpu0 is excluded because it is not possible to change the state * of the first CPU on Linux (it doesn't even have an online file) * and cpuidle is no CPU device. Prevents error messages later. */ if( !strncmp(DirFolderContent.szName, "cpu", 3) && strncmp(DirFolderContent.szName, "cpu0", 4) && strncmp(DirFolderContent.szName, "cpuidle", 7)) { /* Get the sysdev */ RTFILE hFileCpuOnline = NIL_RTFILE; rc = RTFileOpenF(&hFileCpuOnline, RTFILE_O_WRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, "%s/%s/online", SYSFS_CPU_PATH, DirFolderContent.szName); if (RT_SUCCESS(rc)) { /* Write a 1 to online the CPU */ rc = RTFileWrite(hFileCpuOnline, "1", 1, NULL); RTFileClose(hFileCpuOnline); if (RT_SUCCESS(rc)) { VBoxServiceVerbose(1, "CpuHotPlug: CPU %u/%u was brought online\n", idCpuPackage, idCpuCore); fCpuOnline = true; break; } /* Error means CPU not present or online already */ } else VBoxServiceError("CpuHotPlug: Failed to open \"%s/%s/online\" rc=%Rrc\n", SYSFS_CPU_PATH, DirFolderContent.szName, rc); } } } else VBoxServiceError("CpuHotPlug: Failed to open path %s rc=%Rrc\n", SYSFS_CPU_PATH, rc); /* Sleep a bit */ if (!fCpuOnline) RTThreadSleep(10); } while ( !fCpuOnline && cTries-- > 0); #else # error "Port me" #endif }
/** * Worker function for dbgfR3CoreWrite() which does the writing. * * @returns VBox status code * @param pVM Pointer to the VM. * @param hFile The file to write to. Caller closes this. */ static int dbgfR3CoreWriteWorker(PVM pVM, RTFILE hFile) { /* * Collect core information. */ uint32_t const cu32MemRanges = dbgfR3GetRamRangeCount(pVM); uint16_t const cMemRanges = cu32MemRanges < UINT16_MAX - 1 ? cu32MemRanges : UINT16_MAX - 1; /* One PT_NOTE Program header */ uint16_t const cProgHdrs = cMemRanges + 1; DBGFCOREDESCRIPTOR CoreDescriptor; RT_ZERO(CoreDescriptor); CoreDescriptor.u32Magic = DBGFCORE_MAGIC; CoreDescriptor.u32FmtVersion = DBGFCORE_FMT_VERSION; CoreDescriptor.cbSelf = sizeof(CoreDescriptor); CoreDescriptor.u32VBoxVersion = VBOX_FULL_VERSION; CoreDescriptor.u32VBoxRevision = VMMGetSvnRev(); CoreDescriptor.cCpus = pVM->cCpus; Log((DBGFLOG_NAME ": CoreDescriptor Version=%u Revision=%u\n", CoreDescriptor.u32VBoxVersion, CoreDescriptor.u32VBoxRevision)); /* * Compute the file layout (see pg_dbgf_vmcore). */ uint64_t const offElfHdr = RTFileTell(hFile); uint64_t const offNoteSection = offElfHdr + sizeof(Elf64_Ehdr); uint64_t const offLoadSections = offNoteSection + sizeof(Elf64_Phdr); uint64_t const cbLoadSections = cMemRanges * sizeof(Elf64_Phdr); uint64_t const offCoreDescriptor = offLoadSections + cbLoadSections; uint64_t const cbCoreDescriptor = Elf64NoteSectionSize(g_pcszCoreVBoxCore, sizeof(CoreDescriptor)); uint64_t const offCpuDumps = offCoreDescriptor + cbCoreDescriptor; uint64_t const cbCpuDumps = pVM->cCpus * Elf64NoteSectionSize(g_pcszCoreVBoxCpu, sizeof(DBGFCORECPU)); uint64_t const offMemory = offCpuDumps + cbCpuDumps; uint64_t const offNoteSectionData = offCoreDescriptor; uint64_t const cbNoteSectionData = cbCoreDescriptor + cbCpuDumps; /* * Write ELF header. */ int rc = Elf64WriteElfHdr(hFile, cProgHdrs, 0 /* cSecHdrs */); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteElfHdr failed. rc=%Rrc\n", rc)); return rc; } /* * Write PT_NOTE program header. */ Assert(RTFileTell(hFile) == offNoteSection); rc = Elf64WriteProgHdr(hFile, PT_NOTE, PF_R, offNoteSectionData, /* file offset to contents */ cbNoteSectionData, /* size in core file */ cbNoteSectionData, /* size in memory */ 0); /* physical address */ if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WritreProgHdr failed for PT_NOTE. rc=%Rrc\n", rc)); return rc; } /* * Write PT_LOAD program header for each memory range. */ Assert(RTFileTell(hFile) == offLoadSections); uint64_t offMemRange = offMemory; for (uint16_t iRange = 0; iRange < cMemRanges; iRange++) { RTGCPHYS GCPhysStart; RTGCPHYS GCPhysEnd; bool fIsMmio; rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, &fIsMmio); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange failed for iRange(%u) rc=%Rrc\n", iRange, rc)); return rc; } uint64_t cbMemRange = GCPhysEnd - GCPhysStart + 1; uint64_t cbFileRange = fIsMmio ? 0 : cbMemRange; Log((DBGFLOG_NAME ": PGMR3PhysGetRange iRange=%u GCPhysStart=%#x GCPhysEnd=%#x cbMemRange=%u\n", iRange, GCPhysStart, GCPhysEnd, cbMemRange)); rc = Elf64WriteProgHdr(hFile, PT_LOAD, PF_R, offMemRange, /* file offset to contents */ cbFileRange, /* size in core file */ cbMemRange, /* size in memory */ GCPhysStart); /* physical address */ if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteProgHdr failed for memory range(%u) cbFileRange=%u cbMemRange=%u rc=%Rrc\n", iRange, cbFileRange, cbMemRange, rc)); return rc; } offMemRange += cbFileRange; } /* * Write the Core descriptor note header and data. */ Assert(RTFileTell(hFile) == offCoreDescriptor); rc = Elf64WriteNoteHdr(hFile, NT_VBOXCORE, g_pcszCoreVBoxCore, &CoreDescriptor, sizeof(CoreDescriptor)); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr failed for Note '%s' rc=%Rrc\n", g_pcszCoreVBoxCore, rc)); return rc; } /* * Write the CPU context note headers and data. */ Assert(RTFileTell(hFile) == offCpuDumps); PDBGFCORECPU pDbgfCoreCpu = (PDBGFCORECPU)RTMemAlloc(sizeof(*pDbgfCoreCpu)); if (RT_UNLIKELY(!pDbgfCoreCpu)) { LogRel((DBGFLOG_NAME ": failed to alloc %u bytes for DBGFCORECPU\n", sizeof(*pDbgfCoreCpu))); return VERR_NO_MEMORY; } for (uint32_t iCpu = 0; iCpu < pVM->cCpus; iCpu++) { PVMCPU pVCpu = &pVM->aCpus[iCpu]; PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); if (RT_UNLIKELY(!pCtx)) { LogRel((DBGFLOG_NAME ": CPUMQueryGuestCtxPtr failed for vCPU[%u]\n", iCpu)); RTMemFree(pDbgfCoreCpu); return VERR_INVALID_POINTER; } RT_BZERO(pDbgfCoreCpu, sizeof(*pDbgfCoreCpu)); dbgfR3GetCoreCpu(pCtx, pDbgfCoreCpu); rc = Elf64WriteNoteHdr(hFile, NT_VBOXCPU, g_pcszCoreVBoxCpu, pDbgfCoreCpu, sizeof(*pDbgfCoreCpu)); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr failed for vCPU[%u] rc=%Rrc\n", iCpu, rc)); RTMemFree(pDbgfCoreCpu); return rc; } } RTMemFree(pDbgfCoreCpu); pDbgfCoreCpu = NULL; /* * Write memory ranges. */ Assert(RTFileTell(hFile) == offMemory); for (uint16_t iRange = 0; iRange < cMemRanges; iRange++) { RTGCPHYS GCPhysStart; RTGCPHYS GCPhysEnd; bool fIsMmio; rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, &fIsMmio); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange(2) failed for iRange(%u) rc=%Rrc\n", iRange, rc)); return rc; } if (fIsMmio) continue; /* * Write page-by-page of this memory range. * * The read function may fail on MMIO ranges, we write these as zero * pages for now (would be nice to have the VGA bits there though). */ uint64_t cbMemRange = GCPhysEnd - GCPhysStart + 1; uint64_t cPages = cbMemRange >> PAGE_SHIFT; for (uint64_t iPage = 0; iPage < cPages; iPage++) { uint8_t abPage[PAGE_SIZE]; rc = PGMPhysSimpleReadGCPhys(pVM, abPage, GCPhysStart + (iPage << PAGE_SHIFT), sizeof(abPage)); if (RT_FAILURE(rc)) { if (rc != VERR_PGM_PHYS_PAGE_RESERVED) LogRel((DBGFLOG_NAME ": PGMPhysRead failed for iRange=%u iPage=%u. rc=%Rrc. Ignoring...\n", iRange, iPage, rc)); RT_ZERO(abPage); } rc = RTFileWrite(hFile, abPage, sizeof(abPage), NULL /* all */); if (RT_FAILURE(rc)) { LogRel((DBGFLOG_NAME ": RTFileWrite failed. iRange=%u iPage=%u rc=%Rrc\n", iRange, iPage, rc)); return rc; } } } return rc; }
/** * Elf function to write 64-bit note header. * * @param hFile The file to write to. * @param Type Type of this section. * @param pszName Name of this section. * @param pcv Opaque pointer to the data, if NULL only computes size. * @param cbData Size of the data. * * @return IPRT status code. */ static int Elf64WriteNoteHdr(RTFILE hFile, uint16_t Type, const char *pszName, const void *pcvData, uint64_t cbData) { AssertReturn(pcvData, VERR_INVALID_POINTER); AssertReturn(cbData > 0, VERR_NO_DATA); char szNoteName[g_cbNoteName]; RT_ZERO(szNoteName); RTStrCopy(szNoteName, sizeof(szNoteName), pszName); size_t cbName = strlen(szNoteName) + 1; size_t cbNameAlign = RT_ALIGN_Z(cbName, g_NoteAlign); uint64_t cbDataAlign = RT_ALIGN_64(cbData, g_NoteAlign); /* * Yell loudly and bail if we are going to be writing a core file that is not compatible with * both Solaris and the 64-bit ELF spec. which dictates 8-byte alignment. See @bugref{5211} comment #3. */ if (cbNameAlign - cbName > 3) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr pszName=%s cbName=%u cbNameAlign=%u, cbName aligns to 4 not 8-bytes!\n", pszName, cbName, cbNameAlign)); return VERR_INVALID_PARAMETER; } if (cbDataAlign - cbData > 3) { LogRel((DBGFLOG_NAME ": Elf64WriteNoteHdr pszName=%s cbData=%u cbDataAlign=%u, cbData aligns to 4 not 8-bytes!\n", pszName, cbData, cbDataAlign)); return VERR_INVALID_PARAMETER; } static const char s_achPad[7] = { 0, 0, 0, 0, 0, 0, 0 }; AssertCompile(sizeof(s_achPad) >= g_NoteAlign - 1); Elf64_Nhdr ElfNoteHdr; RT_ZERO(ElfNoteHdr); ElfNoteHdr.n_namesz = (Elf64_Word)cbName - 1; /* Again, a discrepancy between ELF-64 and Solaris, we will follow ELF-64, see @bugref{5211} comment #3. */ ElfNoteHdr.n_type = Type; ElfNoteHdr.n_descsz = (Elf64_Word)cbDataAlign; /* * Write note header. */ int rc = RTFileWrite(hFile, &ElfNoteHdr, sizeof(ElfNoteHdr), NULL /* all */); if (RT_SUCCESS(rc)) { /* * Write note name. */ rc = RTFileWrite(hFile, szNoteName, cbName, NULL /* all */); if (RT_SUCCESS(rc)) { /* * Write note name padding if required. */ if (cbNameAlign > cbName) rc = RTFileWrite(hFile, s_achPad, cbNameAlign - cbName, NULL); if (RT_SUCCESS(rc)) { /* * Write note data. */ rc = RTFileWrite(hFile, pcvData, cbData, NULL /* all */); if (RT_SUCCESS(rc)) { /* * Write note data padding if required. */ if (cbDataAlign > cbData) rc = RTFileWrite(hFile, s_achPad, cbDataAlign - cbData, NULL /* all*/); } } } } if (RT_FAILURE(rc)) LogRel((DBGFLOG_NAME ": RTFileWrite failed. rc=%Rrc pszName=%s cbName=%u cbNameAlign=%u cbData=%u cbDataAlign=%u\n", rc, pszName, cbName, cbNameAlign, cbData, cbDataAlign)); return rc; }
/** * Writes the file header. * * @returns IPRT status code, @see RTFileWrite. * * @param File The file handle. * @param StartNanoTS What to subtract from the RTTimeNanoTS output. */ int PcapFileHdr(RTFILE File, uint64_t StartNanoTS) { int rc1 = RTFileWrite(File, &s_Hdr, sizeof(s_Hdr), NULL); int rc2 = PcapFileFrame(File, StartNanoTS, s_szDummyData, 60, sizeof(s_szDummyData)); return RT_SUCCESS(rc1) ? rc2 : rc1; }
/** * 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; }
RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, RTDIGESTTYPE enmDigestType, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_POINTER); RTFILE file; int rc = RTFileOpen(&file, pszManifestFile, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_ALL); if (RT_FAILURE(rc)) return rc; PRTMANIFESTTEST paFiles = 0; void *pvBuf = 0; do { paFiles = (PRTMANIFESTTEST)RTMemAllocZ(sizeof(RTMANIFESTTEST) * cFiles); if (!paFiles) { rc = VERR_NO_MEMORY; break; } RTMANIFESTCALLBACKDATA callback = { pfnProgressCallback, pvUser, cFiles, 0 }; for (size_t i = 0; i < cFiles; ++i) { paFiles[i].pszTestFile = papszFiles[i]; /* Calculate the SHA1 digest of every file */ if (pfnProgressCallback) { callback.cCurrentFile = i; rc = RTSha1DigestFromFile(paFiles[i].pszTestFile, (char**)&paFiles[i].pszTestDigest, rtSHAProgressCallback, &callback); } else rc = RTSha1DigestFromFile(paFiles[i].pszTestFile, (char**)&paFiles[i].pszTestDigest, NULL, NULL); if (RT_FAILURE(rc)) break; } if (RT_SUCCESS(rc)) { size_t cbSize = 0; rc = RTManifestWriteFilesBuf(&pvBuf, &cbSize, enmDigestType, paFiles, cFiles); if (RT_FAILURE(rc)) break; rc = RTFileWrite(file, pvBuf, cbSize, 0); } }while (0); RTFileClose(file); /* Cleanup */ if (pvBuf) RTMemFree(pvBuf); if (paFiles) { for (size_t i = 0; i < cFiles; ++i) if (paFiles[i].pszTestDigest) RTStrFree((char*)paFiles[i].pszTestDigest); RTMemFree(paFiles); } /* Delete the manifest file on failure */ if (RT_FAILURE(rc)) RTFileDelete(pszManifestFile); 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; }
static int ebml_Write(EbmlGlobal *glob, const void *pv, size_t cb) { return RTFileWrite(glob->file, pv, cb, NULL); }