/** @copydoc KRDROPS::pfnRead */ static int krdrRTFileRead(PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off) { PKRDRFILE pRdrFile = (PKRDRFILE)pRdr; int rc; /* * Do a seek if needed. */ if (pRdrFile->off != off) { rc = RTFileSeek(pRdrFile->File, off, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { pRdrFile->off = -1; return rc; } } /* * Do the read. */ rc = RTFileRead(pRdrFile->File, pvBuf, cb, NULL); if (RT_FAILURE(rc)) { pRdrFile->off = -1; return rc; } pRdrFile->off = off + cb; return 0; }
static size_t rtS3ReadFileCallback(void *pvBuf, size_t cSize, size_t cBSize, void *pvUser) { size_t cRead; RTFileRead(*(RTFILE*)pvUser, pvBuf, cSize * cBSize, &cRead); return cRead; }
/** * Read bytes from 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 read. * @param pvBuf Where to put the bytes we read. * @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) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead) { int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) rc = RTFileRead(File, pvBuf, cbToRead, pcbRead); return rc; }
int File::read(char *aBuf, int aLen) { size_t len = aLen; int vrc = RTFileRead(m->handle, aBuf, len, &len); if (RT_SUCCESS(vrc)) return (int)len; throw EIPRTFailure(vrc, "Runtime error reading from file '%s'", m->strFileName.c_str()); }
/** * Search for a USB test device and return the device path. * * @returns Path to the USB test device or NULL if none was found. */ static char *usbTestFindDevice(void) { /* * Very crude and quick way to search for the correct test device. * Assumption is that the path looks like /dev/bus/usb/%3d/%3d. */ uint8_t uBus = 1; bool fBusExists = false; char aszDevPath[64]; RT_ZERO(aszDevPath); do { RTStrPrintf(aszDevPath, sizeof(aszDevPath), "/dev/bus/usb/%03d", uBus); fBusExists = RTPathExists(aszDevPath); if (fBusExists) { /* Check every device. */ bool fDevExists = false; uint8_t uDev = 1; do { RTStrPrintf(aszDevPath, sizeof(aszDevPath), "/dev/bus/usb/%03d/%03d", uBus, uDev); fDevExists = RTPathExists(aszDevPath); if (fDevExists) { RTFILE hFileDev; int rc = RTFileOpen(&hFileDev, aszDevPath, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { USBDEVDESC DevDesc; rc = RTFileRead(hFileDev, &DevDesc, sizeof(DevDesc), NULL); RTFileClose(hFileDev); if ( RT_SUCCESS(rc) && DevDesc.idVendor == 0x0525 && DevDesc.idProduct == 0xa4a0) return RTStrDup(aszDevPath); } } uDev++; } while (fDevExists); } uBus++; } while (fBusExists); return NULL; }
int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead) { AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf, VERR_INVALID_PARAMETER); /* pcbRead is optional. */ size_t cbRead = 0; int rc; switch (m_Type) { case File: { rc = OpenEx(m_strSrcPath, File, Source, /* Use some sensible defaults. */ RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */); if (RT_SUCCESS(rc)) { rc = RTFileRead(u.m_hFile, pvBuf, cbBuf, &cbRead); if (RT_SUCCESS(rc)) { m_cbProcessed += cbRead; Assert(m_cbProcessed <= m_cbSize); /* End of file reached or error occurred? */ if ( m_cbSize && m_cbProcessed == m_cbSize) { rc = VINF_EOF; } } } break; } case Directory: { rc = VINF_SUCCESS; break; } default: rc = VERR_NOT_IMPLEMENTED; break; } if (RT_SUCCESS(rc)) { if (pcbRead) *pcbRead = (uint32_t)cbRead; } LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbRead, rc)); return rc; }
static DECLCALLBACK(int) loadMem(PVM pVM, RTFILE File, uint64_t *poff) { uint64_t off = *poff; RTPrintf("info: loading memory...\n"); int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { RTGCPHYS GCPhys = 0; for (;;) { if (!(GCPhys % (PAGE_SIZE * 0x1000))) RTPrintf("info: %RGp...\n", GCPhys); /* read a page from the file */ size_t cbRead = 0; uint8_t au8Page[PAGE_SIZE * 16]; rc = RTFileRead(File, &au8Page, sizeof(au8Page), &cbRead); if (RT_SUCCESS(rc) && !cbRead) rc = RTFileRead(File, &au8Page, sizeof(au8Page), &cbRead); if (RT_SUCCESS(rc) && !cbRead) rc = VERR_EOF; if (RT_FAILURE(rc) || rc == VINF_EOF) { if (rc == VERR_EOF) rc = VINF_SUCCESS; else RTPrintf("error: Read error %Rrc while reading the raw memory file.\n", rc); break; } /* Write that page to the guest - skip known rom areas for now. */ if (GCPhys < 0xa0000 || GCPhys >= 0x10000) /* ASSUME size of a8Page is a power of 2. */ PGMPhysWrite(pVM, GCPhys, &au8Page, cbRead); GCPhys += cbRead; } } else RTPrintf("error: Failed to seek to 0x%llx in the raw memory file. rc=%Rrc\n", off, rc); return rc; }
/** * Adds a debug file to the cache. * * @returns IPRT status code * @param pszPath The path to the debug file in question. * @param pCfg The configuration. */ static int rtDbgSymCacheAddDebugFile(const char *pszPath, PCRTDBGSYMCACHEADDCFG pCfg) { /* * Need to extract an identifier of sorts here in order to put them in * the right place in the cache. Currently only implemnted for Mach-O * files since these use executable containers. * * We take a look at the file header in hope to figure out what to do * with the file. */ RTFILE hFile; int rc = RTFileOpen(&hFile, pszPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "Error opening '%s': %Rrc", pszPath, rc); union { uint64_t au64[16]; uint32_t au32[16]; uint16_t au16[32]; uint8_t ab[64]; } uBuf; rc = RTFileRead(hFile, &uBuf, sizeof(uBuf), NULL); if (RT_SUCCESS(rc)) { /* * Look for magics and call workers. */ if (!memcmp(uBuf.ab, RT_STR_TUPLE("Microsoft C/C++ MSF 7.00"))) rc = rtDbgSymCacheAddDebugPdb(pszPath, pCfg, hFile); else if ( uBuf.au32[0] == IMAGE_FAT_SIGNATURE || uBuf.au32[0] == IMAGE_FAT_SIGNATURE_OE || uBuf.au32[0] == IMAGE_MACHO32_SIGNATURE || uBuf.au32[0] == IMAGE_MACHO64_SIGNATURE || uBuf.au32[0] == IMAGE_MACHO32_SIGNATURE_OE || uBuf.au32[0] == IMAGE_MACHO64_SIGNATURE_OE) rc = rtDbgSymCacheAddDebugMachO(pszPath, pCfg); else rc = RTMsgErrorRc(VERR_INVALID_MAGIC, "Unsupported debug file '%s' magic: %#010x", pszPath, uBuf.au32[0]); } else rc = RTMsgErrorRc(rc, "Error reading '%s': %Rrc", pszPath, rc); /* close the file. */ int rc2 = RTFileClose(hFile); if (RT_FAILURE(rc2)) { RTMsgError("Error closing '%s': %Rrc", pszPath, rc2); if (RT_SUCCESS(rc)) rc = rc2; } return rc; }
DECLINLINE(int) tftpReadDataBlock(PNATState pData, PTFTPSESSION pcTftpSession, uint8_t *pu8Data, int *pcbReadData) { RTFILE hSessionFile; int rc = VINF_SUCCESS; uint16_t u16BlkSize = 0; AssertPtrReturn(pData, VERR_INVALID_PARAMETER); AssertPtrReturn(pcTftpSession, VERR_INVALID_PARAMETER); AssertPtrReturn(pu8Data, VERR_INVALID_PARAMETER); AssertPtrReturn(pcbReadData, VERR_INVALID_PARAMETER); AssertReturn(pcTftpSession->OptionBlkSize.u64Value < UINT16_MAX, VERR_INVALID_PARAMETER); LogFlowFunc(("pcTftpSession:%p, pu8Data:%p, pcbReadData:%p\n", pcTftpSession, pu8Data, pcbReadData)); u16BlkSize = (uint16_t)pcTftpSession->OptionBlkSize.u64Value; rc = pftpSessionOpenFile(pData, pcTftpSession, &hSessionFile); if (RT_FAILURE(rc)) { LogFlowFuncLeaveRC(rc); return rc; } if (pcbReadData) { rc = RTFileSeek(hSessionFile, pcTftpSession->cbTransfered, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { RTFileClose(hSessionFile); LogFlowFuncLeaveRC(rc); return rc; } rc = RTFileRead(hSessionFile, pu8Data, u16BlkSize, (size_t *)pcbReadData); if (RT_FAILURE(rc)) { RTFileClose(hSessionFile); LogFlowFuncLeaveRC(rc); return rc; } } rc = RTFileClose(hSessionFile); LogFlowFuncLeaveRC(rc); return rc; }
/** * Reads data from the object. Only applies to files objects. * * @return IPRT status code. * @param pvBuf Buffer where to store the read data. * @param cbBuf Size (in bytes) of the buffer. * @param pcbRead Pointer where to store how many bytes were read. Optional. */ int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead) { AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf, VERR_INVALID_PARAMETER); /* pcbRead is optional. */ AssertMsgReturn(m_enmView == View_Source, ("Cannot write to an object which is not in target view\n"), VERR_INVALID_STATE); size_t cbRead = 0; int rc; switch (m_enmType) { case Type_File: { rc = RTFileRead(u.File.hFile, pvBuf, cbBuf, &cbRead); if (RT_SUCCESS(rc)) { u.File.cbProcessed += cbRead; Assert(u.File.cbProcessed <= u.File.cbToProcess); /* End of file reached or error occurred? */ if ( u.File.cbToProcess && u.File.cbProcessed == u.File.cbToProcess) { rc = VINF_EOF; } } break; } case Type_Directory: { rc = VINF_SUCCESS; break; } default: rc = VERR_NOT_IMPLEMENTED; break; } if (RT_SUCCESS(rc)) { if (pcbRead) *pcbRead = (uint32_t)cbRead; } LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPathAbs.c_str(), cbRead, rc)); return rc; }
int DnDHGSendFilePrivate::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextMsg) return VERR_NO_DATA; int rc = m_pNextMsg->getData(uMsg, cParms, paParms); clearNextMsg(); if (RT_FAILURE(rc)) return rc; if (!m_hCurFile) { rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_ALL); if (RT_FAILURE(rc)) return rc; } /* How big is the pointer provided by the guest? */ uint32_t cbToRead = paParms[2].u.pointer.size; size_t cbRead; rc = RTFileRead(m_hCurFile, paParms[2].u.pointer.addr, cbToRead, &cbRead); if (RT_FAILURE(rc)) { /* On error, immediately close the file. */ RTFileClose(m_hCurFile); m_hCurFile = 0; return rc; } m_cbDone += cbRead; /* Tell the guest the actual size. */ paParms[3].setUInt32(cbRead); /* Check if we are done. */ if (m_cbSize == m_cbDone) { RTFileClose(m_hCurFile); m_hCurFile = 0; } else { /* More data! Prepare the next message. */ m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms); } /* Advance progress info */ if ( RT_SUCCESS(rc) && m_pfnProgressCallback) rc = m_pfnProgressCallback(cbRead, m_pvProgressUser); return rc; }
static int MyReadFile(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead, uint64_t *pcbMaxLeft) { int rc = VINF_SUCCESS; if (*pcbMaxLeft > 0) { if (cbToRead > *pcbMaxLeft) cbToRead = (size_t)*pcbMaxLeft; rc = RTFileRead(hFile, pvBuf, cbToRead, pcbRead); if (RT_SUCCESS(rc)) *pcbMaxLeft -= *pcbRead; } else *pcbRead = 0; return rc; }
RTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed) { /* Validate input */ AssertPtrReturn(pszManifestFile, VERR_INVALID_POINTER); /* Open the manifest file */ RTFILE file; int rc = RTFileOpen(&file, pszManifestFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return rc; void *pvBuf = 0; do { uint64_t cbSize; rc = RTFileGetSize(file, &cbSize); if (RT_FAILURE(rc)) break; /* Cast down for the case size_t < uint64_t. This isn't really correct, but we consider manifest files bigger than size_t as not supported by now. */ size_t cbToRead = (size_t)cbSize; pvBuf = RTMemAlloc(cbToRead); if (!pvBuf) { rc = VERR_NO_MEMORY; break; } size_t cbRead = 0; rc = RTFileRead(file, pvBuf, cbToRead, &cbRead); if (RT_FAILURE(rc)) break; rc = RTManifestVerifyFilesBuf(pvBuf, cbRead, paTests, cTests, piFailed); }while (0); /* Cleanup */ if (pvBuf) RTMemFree(pvBuf); RTFileClose(file); return rc; }
VBOXDDU_DECL(int) VDDbgIoLogOpen(PVDIOLOGGER phIoLogger, const char *pszFilename) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = NULL; AssertPtrReturn(phIoLogger, VERR_INVALID_POINTER); AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); rc = vddbgIoLoggerCreate(&pIoLogger); if (RT_SUCCESS(rc)) { /* open existing log. */ rc = RTFileOpen(&pIoLogger->hFile, pszFilename, RTFILE_O_DENY_NONE | RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_READ); if (RT_SUCCESS(rc)) { IoLogHeader Hdr; uint64_t cbLog; rc = RTFileGetSize(pIoLogger->hFile, &cbLog); /* Read the header. */ if (RT_SUCCESS(rc)) rc = RTFileRead(pIoLogger->hFile, &Hdr, sizeof(Hdr), NULL); if ( RT_SUCCESS(rc) && !memcmp(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic))) { pIoLogger->fFlags = RT_LE2H_U32(Hdr.fFlags); pIoLogger->offWriteNext = cbLog; pIoLogger->offReadNext = sizeof(Hdr); pIoLogger->idNext = RT_LE2H_U64(Hdr.u64Id); *phIoLogger = pIoLogger; } else if (RT_SUCCESS(rc)) rc = VERR_INVALID_PARAMETER; } } return rc; }
int main(int argc, char **argv) { RTR3InitExe(argc, &argv, 0); enum { kDigestType_NotSpecified, kDigestType_CRC32, kDigestType_CRC64, kDigestType_MD5, kDigestType_SHA1, kDigestType_SHA256, kDigestType_SHA512 } enmDigestType = kDigestType_NotSpecified; enum { kMethod_Full, kMethod_Block, kMethod_File } enmMethod = kMethod_Block; static const RTGETOPTDEF s_aOptions[] = { { "--type", 't', RTGETOPT_REQ_STRING }, { "--method", 'm', RTGETOPT_REQ_STRING }, { "--help", 'h', RTGETOPT_REQ_NOTHING }, }; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 't': if (!RTStrICmp(ValueUnion.psz, "crc32")) enmDigestType = kDigestType_CRC32; else if (!RTStrICmp(ValueUnion.psz, "crc64")) enmDigestType = kDigestType_CRC64; else if (!RTStrICmp(ValueUnion.psz, "md5")) enmDigestType = kDigestType_MD5; else if (!RTStrICmp(ValueUnion.psz, "sha1")) enmDigestType = kDigestType_SHA1; else if (!RTStrICmp(ValueUnion.psz, "sha256")) enmDigestType = kDigestType_SHA256; else if (!RTStrICmp(ValueUnion.psz, "sha512")) enmDigestType = kDigestType_SHA512; else { Error("Invalid digest type: %s\n", ValueUnion.psz); return 1; } break; case 'm': if (!RTStrICmp(ValueUnion.psz, "full")) enmMethod = kMethod_Full; else if (!RTStrICmp(ValueUnion.psz, "block")) enmMethod = kMethod_Block; else if (!RTStrICmp(ValueUnion.psz, "file")) enmMethod = kMethod_File; else { Error("Invalid digest method: %s\n", ValueUnion.psz); return 1; } break; case 'h': RTPrintf("syntax: tstRTDigest -t <digest-type> file [file2 [..]]\n"); return 1; case VINF_GETOPT_NOT_OPTION: { if (enmDigestType == kDigestType_NotSpecified) return Error("No digest type was specified\n"); switch (enmMethod) { case kMethod_Full: return Error("Full file method is not implemented\n"); case kMethod_File: switch (enmDigestType) { case kDigestType_SHA1: { char *pszDigest; int rc = RTSha1DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha1Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } case kDigestType_SHA256: { char *pszDigest; int rc = RTSha256DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha256Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } default: return Error("The file method isn't implemented for this digest\n"); } break; case kMethod_Block: { RTFILE hFile; int rc = RTFileOpen(&hFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return Error("RTFileOpen(,%s,) -> %Rrc\n", ValueUnion.psz, rc); size_t cbRead; uint8_t abBuf[_64K]; char *pszDigest = (char *)&abBuf[0]; switch (enmDigestType) { case kDigestType_CRC32: { uint32_t uCRC32 = RTCrc32Start(); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; uCRC32 = RTCrc32Process(uCRC32, abBuf, cbRead); } uCRC32 = RTCrc32Finish(uCRC32); RTStrPrintf(pszDigest, sizeof(abBuf), "%08RX32", uCRC32); break; } case kDigestType_CRC64: { uint64_t uCRC64 = RTCrc64Start(); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; uCRC64 = RTCrc64Process(uCRC64, abBuf, cbRead); } uCRC64 = RTCrc64Finish(uCRC64); RTStrPrintf(pszDigest, sizeof(abBuf), "%016RX64", uCRC64); break; } case kDigestType_MD5: { RTMD5CONTEXT Ctx; RTMd5Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTMd5Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD5HASHSIZE]; RTMd5Final(abDigest, &Ctx); RTMd5ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA1: { RTSHA1CONTEXT Ctx; RTSha1Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha1Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA1_HASH_SIZE]; RTSha1Final(&Ctx, abDigest); RTSha1ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA256: { RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abDigest); RTSha256ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA512: { RTSHA512CONTEXT Ctx; RTSha512Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha512Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA512_HASH_SIZE]; RTSha512Final(&Ctx, abDigest); RTSha512ToString(abDigest, pszDigest, sizeof(abBuf)); break; } default: return Error("Internal error #1\n"); } RTFileClose(hFile); if (RT_FAILURE(rc) && rc != VERR_EOF) { RTPrintf("Partial: %s %s\n", pszDigest, ValueUnion.psz); return Error("RTFileRead(%s) -> %Rrc\n", ValueUnion.psz, rc); } RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); break; } default: return Error("Internal error #2\n"); } break; } default: return RTGetOptPrintError(ch, &ValueUnion); } } return 0; }
HRESULT Guest::taskUpdateGuestAdditions(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; BOOL fCompleted; BOOL fCanceled; try { ComObjPtr<Guest> pGuest = aTask->pGuest; aTask->pProgress->SetCurrentOperationProgress(10); /* * Determine guest OS type and the required installer image. * At the moment only Windows guests are supported. */ Utf8Str installerImage; Bstr osTypeId; if ( SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam()))) && !osTypeId.isEmpty()) { Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */ if ( osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive) || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive)) { if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive)) installerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE"; else installerImage = "VBOXWINDOWSADDITIONS_X86.EXE"; /* Since the installers are located in the root directory, * no further path processing needs to be done (yet). */ } else /* Everything else is not supported (yet). */ throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"), osTypeIdUtf8.c_str()); } else throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Could not detected guest OS type/version, please update manually")); Assert(!installerImage.isEmpty()); /* * Try to open the .ISO file and locate the specified installer. */ RTISOFSFILE iso; int vrc = RTIsoFsOpen(&iso, aTask->strSource.c_str()); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_FILE_ERROR, aTask->pProgress, Guest::tr("Invalid installation medium detected: \"%s\""), aTask->strSource.c_str()); } else { uint32_t cbOffset; size_t cbLength; vrc = RTIsoFsGetFileInfo(&iso, installerImage.c_str(), &cbOffset, &cbLength); if ( RT_SUCCESS(vrc) && cbOffset && cbLength) { vrc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(vrc)) rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not seek to setup file on installation medium \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); } else { switch (vrc) { case VERR_FILE_NOT_FOUND: rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Setup file was not found on installation medium \"%s\""), aTask->strSource.c_str()); break; default: rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("An unknown error (%Rrc) occured while retrieving information of setup file on installation medium \"%s\""), vrc, aTask->strSource.c_str()); break; } } /* Specify the ouput path on the guest side. */ Utf8Str strInstallerPath = "%TEMP%\\VBoxWindowsAdditions.exe"; if (RT_SUCCESS(vrc)) { /* Okay, we're ready to start our copy routine on the guest! */ aTask->pProgress->SetCurrentOperationProgress(15); /* Prepare command line args. */ com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; args.push_back(Bstr("--output").raw()); /* We want to write a file ... */ args.push_back(Bstr(strInstallerPath.c_str()).raw()); /* ... with this path. */ if (SUCCEEDED(rc)) { ComPtr<IProgress> progressCat; ULONG uPID; /* * Start built-in "vbox_cat" tool (inside VBoxService) to * copy over/pipe the data into a file on the guest (with * system rights, no username/password specified). */ rc = pGuest->executeProcessInternal(Bstr(VBOXSERVICE_TOOL_CAT).raw(), ExecuteProcessFlag_Hidden | ExecuteProcessFlag_WaitForProcessStartOnly, ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr("").raw() /* Username. */, Bstr("").raw() /* Password */, 5 * 1000 /* Wait 5s for getting the process started. */, &uPID, progressCat.asOutParam(), &vrc); if (FAILED(rc)) { /* Errors which return VBOX_E_NOT_SUPPORTED can be safely skipped by the caller * to silently fall back to "normal" (old) .ISO mounting. */ /* Due to a very limited COM error range we use vrc for a more detailed error * lookup to figure out what went wrong. */ switch (vrc) { /* Guest execution service is not (yet) ready. This basically means that either VBoxService * is not running (yet) or that the Guest Additions are too old (because VBoxService does not * support the guest execution feature in this version). */ case VERR_NOT_FOUND: LogRel(("Guest Additions seem not to be installed yet\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Guest Additions seem not to be installed or are not ready to update yet")); break; /* Getting back a VERR_INVALID_PARAMETER indicates that the installed Guest Additions are supporting the guest * execution but not the built-in "vbox_cat" tool of VBoxService (< 4.0). */ case VERR_INVALID_PARAMETER: LogRel(("Guest Additions are installed but don't supported automatic updating\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress, Guest::tr("Installed Guest Additions do not support automatic updating")); break; case VERR_TIMEOUT: LogRel(("Guest was unable to start copying the Guest Additions setup within time\n")); rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress, Guest::tr("Guest was unable to start copying the Guest Additions setup within time")); break; default: rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress, Guest::tr("Error copying Guest Additions setup file to guest path \"%s\" (%Rrc)"), strInstallerPath.c_str(), vrc); break; } } else { LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", aTask->strSource.c_str())); LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n", installerImage.c_str(), strInstallerPath.c_str())); aTask->pProgress->SetCurrentOperationProgress(20); /* Wait for process to exit ... */ SafeArray<BYTE> aInputData(_64K); while ( SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted))) && !fCompleted) { size_t cbRead; /* cbLength contains remaining bytes of our installer file * opened above to read. */ size_t cbToRead = RT_MIN(cbLength, _64K); if (cbToRead) { vrc = RTFileRead(iso.file, (uint8_t*)aInputData.raw(), cbToRead, &cbRead); if ( cbRead && RT_SUCCESS(vrc)) { /* Resize buffer to reflect amount we just have read. */ if (cbRead > 0) aInputData.resize(cbRead); /* Did we reach the end of the content we want to transfer (last chunk)? */ ULONG uFlags = ProcessInputFlag_None; if ( (cbRead < _64K) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { uFlags |= ProcessInputFlag_EndOfFile; } /* Transfer the current chunk ... */ #ifdef DEBUG_andy LogRel(("Copying Guest Additions (%u bytes left) ...\n", cbLength)); #endif ULONG uBytesWritten; rc = pGuest->SetProcessInput(uPID, uFlags, 10 * 1000 /* Wait 10s for getting the input data transfered. */, ComSafeArrayAsInParam(aInputData), &uBytesWritten); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } /* If task was canceled above also cancel the process execution. */ if (fCanceled) progressCat->Cancel(); #ifdef DEBUG_andy LogRel(("Copying Guest Additions (%u bytes written) ...\n", uBytesWritten)); #endif Assert(cbLength >= uBytesWritten); cbLength -= uBytesWritten; } else if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error while reading setup file \"%s\" (To read: %u, Size: %u) from installation medium (%Rrc)"), installerImage.c_str(), cbToRead, cbLength, vrc); } } /* Internal progress canceled? */ if ( SUCCEEDED(progressCat->COMGETTER(Canceled(&fCanceled))) && fCanceled) { aTask->pProgress->Cancel(); break; } } } } } RTIsoFsClose(&iso); if ( SUCCEEDED(rc) && ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && !fCanceled ) ) { /* * Installer was transferred successfully, so let's start it * (with system rights). */ LogRel(("Preparing to execute Guest Additions update ...\n")); aTask->pProgress->SetCurrentOperationProgress(66); /* Prepare command line args for installer. */ com::SafeArray<IN_BSTR> installerArgs; com::SafeArray<IN_BSTR> installerEnv; /** @todo Only Windows! */ installerArgs.push_back(Bstr(strInstallerPath).raw()); /* The actual (internal) installer image (as argv[0]). */ /* Note that starting at Windows Vista the lovely session 0 separation applies: * This means that if we run an application with the profile/security context * of VBoxService (system rights!) we're not able to show any UI. */ installerArgs.push_back(Bstr("/S").raw()); /* We want to install in silent mode. */ installerArgs.push_back(Bstr("/l").raw()); /* ... and logging enabled. */ /* Don't quit VBoxService during upgrade because it still is used for this * piece of code we're in right now (that is, here!) ... */ installerArgs.push_back(Bstr("/no_vboxservice_exit").raw()); /* Tell the installer to report its current installation status * using a running VBoxTray instance via balloon messages in the * Windows taskbar. */ installerArgs.push_back(Bstr("/post_installstatus").raw()); /* * Start the just copied over installer with system rights * in silent mode on the guest. Don't use the hidden flag since there * may be pop ups the user has to process. */ ComPtr<IProgress> progressInstaller; ULONG uPID; rc = pGuest->executeProcessInternal(Bstr(strInstallerPath).raw(), ExecuteProcessFlag_WaitForProcessStartOnly, ComSafeArrayAsInParam(installerArgs), ComSafeArrayAsInParam(installerEnv), Bstr("").raw() /* Username */, Bstr("").raw() /* Password */, 10 * 1000 /* Wait 10s for getting the process started */, &uPID, progressInstaller.asOutParam(), &vrc); if (SUCCEEDED(rc)) { LogRel(("Guest Additions update is running ...\n")); /* If the caller does not want to wait for out guest update process to end, * complete the progress object now so that the caller can do other work. */ if (aTask->uFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly) aTask->pProgress->notifyComplete(S_OK); else aTask->pProgress->SetCurrentOperationProgress(70); /* Wait until the Guest Additions installer finishes ... */ while ( SUCCEEDED(progressInstaller->COMGETTER(Completed(&fCompleted))) && !fCompleted) { if ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) { progressInstaller->Cancel(); break; } /* Progress canceled by Main API? */ if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled))) && fCanceled) { break; } RTThreadSleep(100); } ExecuteProcessStatus_T retStatus; ULONG uRetExitCode, uRetFlags; rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus); if (SUCCEEDED(rc)) { if (fCompleted) { if (uRetExitCode == 0) { LogRel(("Guest Additions update successful!\n")); if ( SUCCEEDED(aTask->pProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) aTask->pProgress->notifyComplete(S_OK); } else { LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n", uRetExitCode, retStatus, uRetFlags)); rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"), uRetExitCode, retStatus, uRetFlags); } } else if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled))) && fCanceled) { LogRel(("Guest Additions update was canceled\n")); rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"), uRetExitCode, retStatus, uRetFlags); } else { LogRel(("Guest Additions update was canceled by the user\n")); } } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } else rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
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; }
int SessionTaskCopyTo::Run(void) { LogFlowThisFuncEnter(); ComObjPtr<GuestSession> pSession = mSession; Assert(!pSession.isNull()); AutoCaller autoCaller(pSession); if (FAILED(autoCaller.rc())) return autoCaller.rc(); if (mCopyFileFlags) { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"), mCopyFileFlags)); return VERR_INVALID_PARAMETER; } int rc; RTFILE fileLocal; PRTFILE pFile = &fileLocal; if (!mSourceFile) { /* Does our source file exist? */ if (!RTFileExists(mSource.c_str())) { rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Source file \"%s\" does not exist or is not a file"), mSource.c_str())); } else { rc = RTFileOpen(pFile, mSource.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) { rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading: %Rrc"), mSource.c_str(), rc)); } else { rc = RTFileGetSize(*pFile, &mSourceSize); if (RT_FAILURE(rc)) { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Could not query file size of \"%s\": %Rrc"), mSource.c_str(), rc)); } } } } else { pFile = mSourceFile; /* Size + offset are optional. */ } GuestProcessStartupInfo procInfo; procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"), mSource.c_str(), mDest.c_str(), mSourceSize); procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT); procInfo.mFlags = ProcessCreateFlag_Hidden; /* Set arguments.*/ procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */ /* Startup process. */ ComObjPtr<GuestProcess> pProcess; rc = pSession->processCreateExInteral(procInfo, pProcess); if (RT_SUCCESS(rc)) rc = pProcess->startProcess(); if (RT_FAILURE(rc)) { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc)); } else { GuestProcessWaitResult waitRes; BYTE byBuf[_64K]; BOOL fCanceled = FALSE; uint64_t cbWrittenTotal = 0; uint64_t cbToRead = mSourceSize; for (;;) { rc = pProcess->waitFor(ProcessWaitForFlag_StdIn, 30 * 1000 /* Timeout */, waitRes); if ( RT_FAILURE(rc) || ( waitRes.mResult != ProcessWaitResult_StdIn && waitRes.mResult != ProcessWaitResult_WaitFlagNotSupported)) { break; } /* If the guest does not support waiting for stdin, we now yield in * order to reduce the CPU load due to busy waiting. */ if (waitRes.mResult == ProcessWaitResult_WaitFlagNotSupported) RTThreadYield(); /* Optional, don't check rc. */ size_t cbRead = 0; if (mSourceSize) /* If we have nothing to write, take a shortcut. */ { /** @todo Not very efficient, but works for now. */ rc = RTFileSeek(*pFile, mSourceOffset + cbWrittenTotal, RTFILE_SEEK_BEGIN, NULL /* poffActual */); if (RT_SUCCESS(rc)) { rc = RTFileRead(*pFile, (uint8_t*)byBuf, RT_MIN(cbToRead, sizeof(byBuf)), &cbRead); /* * Some other error occured? There might be a chance that RTFileRead * could not resolve/map the native error code to an IPRT code, so just * print a generic error. */ if (RT_FAILURE(rc)) { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"), mSource.c_str(), rc)); break; } } else { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"), mSource.c_str(), cbWrittenTotal, rc)); break; } } uint32_t fFlags = ProcessInputFlag_None; /* Did we reach the end of the content we want to transfer (last chunk)? */ if ( (cbRead < sizeof(byBuf)) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { fFlags |= ProcessInputFlag_EndOfFile; } uint32_t cbWritten; Assert(sizeof(byBuf) >= cbRead); rc = pProcess->writeData(0 /* StdIn */, fFlags, byBuf, cbRead, 30 * 1000 /* Timeout */, &cbWritten); if (RT_FAILURE(rc)) { setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"), mDest.c_str(), cbWrittenTotal, rc)); break; } LogFlowThisFunc(("cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n", cbWritten, cbToRead - cbWritten, cbWrittenTotal + cbWritten, mSourceSize)); /* Only subtract bytes reported written by the guest. */ Assert(cbToRead >= cbWritten); cbToRead -= cbWritten; /* Update total bytes written to the guest. */ cbWrittenTotal += cbWritten; Assert(cbWrittenTotal <= mSourceSize); /* Did the user cancel the operation above? */ if (fCanceled) break; /* Update the progress. * Watch out for division by zero. */ mSourceSize > 0 ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / mSourceSize)) : rc = setProgress(100); if (RT_FAILURE(rc)) break; /* End of file reached? */ if (!cbToRead) break; } /* for */ if ( !fCanceled || RT_SUCCESS(rc)) { /* * Even if we succeeded until here make sure to check whether we really transfered * everything. */ if ( mSourceSize > 0 && cbWrittenTotal == 0) { /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write * to the destination -> access denied. */ rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""), mSource.c_str(), mDest.c_str())); } else if (cbWrittenTotal < mSourceSize) { /* If we did not copy all let the user know. */ rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"), mSource.c_str(), cbWrittenTotal, mSourceSize)); } else { rc = pProcess->waitFor(ProcessWaitForFlag_Terminate, 30 * 1000 /* Timeout */, waitRes); if ( RT_FAILURE(rc) || waitRes.mResult != ProcessWaitResult_Terminate) { if (RT_FAILURE(rc)) rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"), mSource.c_str(), rc)); else rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed with wait result %ld"), mSource.c_str(), waitRes.mResult)); } if (RT_SUCCESS(rc)) { ProcessStatus_T procStatus; LONG exitCode; if ( ( SUCCEEDED(pProcess->COMGETTER(Status(&procStatus))) && procStatus != ProcessStatus_TerminatedNormally) || ( SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode))) && exitCode != 0) ) { rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %ld"), mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */ } } if (RT_SUCCESS(rc)) rc = setProgressSuccess(); } } if (!pProcess.isNull()) pProcess->uninit(); } /* processCreateExInteral */ if (!mSourceFile) /* Only close locally opened files. */ RTFileClose(*pFile); LogFlowFuncLeaveRC(rc); return rc; }
RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser) { /* * Validate input. */ AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE); AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE); AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER); AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); /* * Compare the file sizes first. */ uint64_t cbFile1; int rc = RTFileGetSize(hFile1, &cbFile1); if (RT_FAILURE(rc)) return rc; uint64_t cbFile2; rc = RTFileGetSize(hFile1, &cbFile2); if (RT_FAILURE(rc)) return rc; if (cbFile1 != cbFile2) return VERR_NOT_EQUAL; /* * Allocate buffer. */ size_t cbBuf; uint8_t *pbBuf1Free = NULL; uint8_t *pbBuf1; uint8_t *pbBuf2Free = NULL; uint8_t *pbBuf2; if (cbFile1 < _512K) { cbBuf = 8*_1K; pbBuf1 = (uint8_t *)alloca(cbBuf); pbBuf2 = (uint8_t *)alloca(cbBuf); } else { cbBuf = _128K; pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf); pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf); } if (pbBuf1 && pbBuf2) { /* * Seek to the start of each file * and set the size of the destination file. */ rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc) && pfnProgress) rc = pfnProgress(0, pvUser); if (RT_SUCCESS(rc)) { /* * Compare loop. */ unsigned uPercentage = 0; RTFOFF off = 0; RTFOFF cbPercent = cbFile1 / 100; RTFOFF offNextPercent = cbPercent; while (off < (RTFOFF)cbFile1) { /* read the blocks */ RTFOFF cbLeft = cbFile1 - off; size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft; rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL); if (RT_FAILURE(rc)) break; rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL); if (RT_FAILURE(rc)) break; /* compare */ if (memcmp(pbBuf1, pbBuf2, cbBlock)) { rc = VERR_NOT_EQUAL; 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 /* * Compare OS specific data (EAs and stuff). */ if (RT_SUCCESS(rc)) rc = rtFileCompareOSStuff(hFile1, hFile2); #endif /* 100% */ if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc)) rc = pfnProgress(100, pvUser); } } } else rc = VERR_NO_MEMORY; RTMemTmpFree(pbBuf2Free); RTMemTmpFree(pbBuf1Free); return rc; }
/** * 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; }
void tstFileAppend1(RTTEST hTest) { /* * Open it write only and do some appending. * Checking that read fails and that the file position changes after the write. */ RTTestSub(hTest, "Basic 1"); RTFileDelete("tstFileAppend-1.tst"); RTFILE hFile = NIL_RTFILE; int rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_NONE | (0644 << RTFILE_O_CREATE_MODE_SHIFT) ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); uint64_t offActual = 42; uint64_t off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTESTI_CHECK_RC(RTFileWrite(hFile, "0123456789", 10, NULL), VINF_SUCCESS); offActual = 99; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 10 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after first write\n", offActual); size_t cb = 4; char szBuf[256]; rc = RTFileRead(hFile, szBuf, 1, &cb); RTTESTI_CHECK_MSG(rc == VERR_ACCESS_DENIED || rc == VERR_INVALID_HANDLE, ("rc=%Rrc\n", rc)); offActual = 999; off = 5; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_BEGIN, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 5 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it write only and do some more appending. * Checking the initial position and that it changes after the write. */ RTTestSub(hTest, "Basic 2"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); offActual = 99; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 2nd open\n", offActual); RTTESTI_CHECK_RC(rc = RTFileWrite(hFile, "abcdefghij", 10, &cb), VINF_SUCCESS); offActual = 999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 20 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 2nd write\n", offActual); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it read/write. * Check the initial position and read stuff. Then append some more and * check the new position and see that read returns 0/EOF. Finally, * do some seeking and read from a new position. */ RTTestSub(hTest, "Basic 3"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_READWRITE | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE ); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); offActual = 9; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 0 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 3rd open\n", offActual); cb = 99; RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 10, &cb), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || cb == 10); RTTESTI_CHECK_MSG(RT_FAILURE(rc) || !memcmp(szBuf, "0123456789", 10), ("read the wrong stuff: %.10s - expected 0123456789\n", szBuf)); offActual = 999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 10 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu on 1st open\n", offActual); RTTESTI_CHECK_RC(RTFileWrite(hFile, "klmnopqrst", 10, NULL), VINF_SUCCESS); offActual = 9999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 30 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 3rd write\n", offActual); RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 1, NULL), VERR_EOF); cb = 99; RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 1, &cb), VINF_SUCCESS); RTTESTI_CHECK(cb == 0); offActual = 99999; off = 15; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_BEGIN, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 15 || RT_FAILURE(rc), ("offActual=%llu", offActual)); if (RT_SUCCESS(rc) && offActual == 15) { RTTESTI_CHECK_RC(rc = RTFileRead(hFile, szBuf, 10, NULL), VINF_SUCCESS); RTTESTI_CHECK_MSG(RT_FAILURE(rc) || !memcmp(szBuf, "fghijklmno", 10), ("read the wrong stuff: %.10s - expected fghijklmno\n", szBuf)); offActual = 9999999; off = 0; RTTESTI_CHECK_RC(rc = RTFileSeek(hFile, off, RTFILE_SEEK_CURRENT, &offActual), VINF_SUCCESS); RTTESTI_CHECK_MSG(offActual == 25 || RT_FAILURE(rc), ("offActual=%llu", offActual)); RTTestIPrintf(RTTESTLVL_INFO, "off=%llu after 2nd read\n", offActual); } RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); /* * Open it read only + append and check that we cannot write to it. */ RTTestSub(hTest, "Basic 4"); rc = RTFileOpen(&hFile, "tstFileAppend-1.tst", RTFILE_O_READ | RTFILE_O_APPEND | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); rc = RTFileWrite(hFile, "pqrstuvwx", 10, &cb); RTTESTI_CHECK_MSG(rc == VERR_ACCESS_DENIED || rc == VERR_INVALID_HANDLE, ("rc=%Rrc\n", rc)); RTTESTI_CHECK_RC(RTFileClose(hFile), VINF_SUCCESS); RTTESTI_CHECK_RC(RTFileDelete("tstFileAppend-1.tst"), VINF_SUCCESS); }
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; }
RTR3DECL(int) RTSha256DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pszFile, VERR_INVALID_POINTER); AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER); *ppszDigest = NULL; /* Initialize the hash context. */ RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); /* Open the file to calculate a SHA256 sum of */ RTFILE hFile; int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return rc; /* Fetch the file size. Only needed if there is a progress callback. */ double rdMulti = 0; if (pfnProgressCallback) { uint64_t cbFile; rc = RTFileGetSize(hFile, &cbFile); if (RT_FAILURE(rc)) { RTFileClose(hFile); return rc; } rdMulti = 100.0 / (cbFile ? cbFile : 1); } /* Allocate a reasonably large buffer, fall back on a tiny one. */ void *pvBufFree; size_t cbBuf = _1M; void *pvBuf = pvBufFree = RTMemTmpAlloc(cbBuf); if (!pvBuf) { cbBuf = 0x1000; pvBuf = alloca(cbBuf); } /* Read that file in blocks */ size_t cbReadTotal = 0; for (;;) { size_t cbRead; rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, pvBuf, cbRead); cbReadTotal += cbRead; /* Call the progress callback if one is defined */ if (pfnProgressCallback) { rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser); if (RT_FAILURE(rc)) break; /* canceled */ } } RTMemTmpFree(pvBufFree); RTFileClose(hFile); if (RT_FAILURE(rc)) return rc; /* Finally calculate & format the SHA256 sum */ uint8_t abHash[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abHash); char *pszDigest; rc = RTStrAllocEx(&pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) { rc = RTSha256ToString(abHash, pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) *ppszDigest = pszDigest; else RTStrFree(pszDigest); } 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 DECLCALLBACK(int) scriptRun(PVM pVM, RTFILE File) { RTPrintf("info: running script...\n"); uint64_t cb; int rc = RTFileGetSize(File, &cb); if (RT_SUCCESS(rc)) { if (cb == 0) return VINF_SUCCESS; if (cb < _1M) { char *pszBuf = (char *)RTMemAllocZ(cb + 1); if (pszBuf) { rc = RTFileRead(File, pszBuf, cb, NULL); if (RT_SUCCESS(rc)) { pszBuf[cb] = '\0'; /* * Now process what's in the buffer. */ char *psz = pszBuf; while (psz && *psz) { /* skip blanks. */ while (RT_C_IS_SPACE(*psz)) psz++; if (!*psz) break; /* end of line */ char *pszNext; char *pszEnd = strchr(psz, '\n'); if (!pszEnd) pszEnd = strchr(psz, '\r'); if (!pszEnd) pszNext = pszEnd = strchr(psz, '\0'); else pszNext = pszEnd + 1; if (*psz != ';' && *psz != '#' && *psz != '/') { /* strip end */ *pszEnd = '\0'; while (pszEnd > psz && RT_C_IS_SPACE(pszEnd[-1])) *--pszEnd = '\0'; /* process the line */ RTPrintf("debug: executing script line '%s'\n", psz); rc = scriptCommand(pVM, psz, pszEnd - psz); if (RT_FAILURE(rc)) { RTPrintf("error: '%s' failed: %Rrc\n", psz, rc); break; } } /* else comment line */ /* next */ psz = pszNext; } } else RTPrintf("error: failed to read script file: %Rrc\n", rc); RTMemFree(pszBuf); } else { RTPrintf("error: Out of memory. (%d bytes)\n", cb + 1); rc = VERR_NO_MEMORY; } } else RTPrintf("error: script file is too large (0x%llx bytes)\n", cb); } else RTPrintf("error: couldn't get size of script file: %Rrc\n", rc); return rc; }
int DnDURIObject::Read(void *pvBuf, uint32_t cbToRead, uint32_t *pcbRead) { AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertReturn(cbToRead, VERR_INVALID_PARAMETER); /* pcbRead is optional. */ int rc; switch (m_Type) { case File: { if (!u.m_hFile) { /* Open files on the source with RTFILE_O_DENY_WRITE to prevent races * where the OS writes to the file while the destination side transfers * it over. */ rc = RTFileOpen(&u.m_hFile, m_strSrcPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); } else rc = VINF_SUCCESS; bool fDone = false; if (RT_SUCCESS(rc)) { size_t cbRead; rc = RTFileRead(u.m_hFile, pvBuf, cbToRead, &cbRead); if (RT_SUCCESS(rc)) { if (pcbRead) *pcbRead = (uint32_t)cbRead; m_cbProcessed += cbRead; Assert(m_cbProcessed <= m_cbSize); /* End of file reached or error occurred? */ if ( m_cbProcessed == m_cbSize || RT_FAILURE(rc)) { closeInternal(); } } } break; } case Directory: { rc = VINF_SUCCESS; break; } default: rc = VERR_NOT_IMPLEMENTED; break; } LogFlowFunc(("Returning strSourcePath=%s, rc=%Rrc\n", m_strSrcPath.c_str(), rc)); return rc; }
HRESULT Guest::taskCopyFileToGuest(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? */ if (!RTFileExists(aTask->strSource.c_str())) { 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 { RTFILE fileSource; int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"), aTask->strSource.c_str(), vrc); } else { uint64_t cbSize; vrc = RTFileGetSize(fileSource, &cbSize); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not query file size of \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); } else { com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; /* * Prepare tool command line. */ char szOutput[RTPATH_MAX]; if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 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(szOutput, true /* Force conversion. */); } else /* ... or something which isn't from Redmond ... */ { RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */); } args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */ } 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 guest \"%s\" (%u bytes) ...\n", aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize)); /* * 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 guest").raw(), ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), ExecuteProcessFlag_WaitForProcessStartOnly, NULL, NULL, execProgress.asOutParam(), &uPID); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } if (SUCCEEDED(rc)) { BOOL fCompleted = FALSE; BOOL fCanceled = FALSE; uint64_t cbTransferedTotal = 0; SafeArray<BYTE> aInputData(_64K); while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { size_t cbToRead = cbSize; size_t cbRead = 0; if (cbSize) /* If we have nothing to read, take a shortcut. */ { /** @todo Not very efficient, but works for now. */ vrc = RTFileSeek(fileSource, cbTransferedTotal, RTFILE_SEEK_BEGIN, NULL /* poffActual */); if (RT_SUCCESS(vrc)) { vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), RT_MIN(cbToRead, _64K), &cbRead); /* * Some other error occured? There might be a chance that RTFileRead * could not resolve/map the native error code to an IPRT code, so just * print a generic error. */ if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not read from file \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); break; } } else { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Seeking file \"%s\" failed; offset = %RU64 (%Rrc)"), aTask->strSource.c_str(), cbTransferedTotal, vrc); break; } } /* Resize buffer to reflect amount we just have read. * Size 0 is allowed! */ aInputData.resize(cbRead); ULONG uFlags = ProcessInputFlag_None; /* Did we reach the end of the content we want to transfer (last chunk)? */ if ( (cbRead < _64K) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { uFlags |= ProcessInputFlag_EndOfFile; } ULONG uBytesWritten = 0; rc = pGuest->SetProcessInput(uPID, uFlags, 0 /* Infinite timeout */, ComSafeArrayAsInParam(aInputData), &uBytesWritten); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } Assert(cbRead <= cbToRead); Assert(cbToRead >= cbRead); cbToRead -= cbRead; cbTransferedTotal += uBytesWritten; Assert(cbTransferedTotal <= cbSize); aTask->pProgress->SetCurrentOperationProgress(cbTransferedTotal / (cbSize / 100.0)); /* End of file reached? */ if (cbToRead == 0) break; /* Did the user cancel the operation above? */ if (fCanceled) break; /* Progress canceled by Main API? */ if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copy operation of file \"%s\" was canceled on guest side"), aTask->strSource.c_str()); break; } } if (SUCCEEDED(rc)) { /* * If we got here this means the started process either was completed, * canceled or we simply got all stuff transferred. */ ExecuteProcessStatus_T retStatus; ULONG uRetExitCode; rc = executeWaitForExit(uPID, execProgress, 0 /* No timeout */, &retStatus, &uRetExitCode); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } else { if ( uRetExitCode != 0 || retStatus != ExecuteProcessStatus_TerminatedNormally) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest process reported error %u (status: %u) while copying file \"%s\" to \"%s\""), uRetExitCode, retStatus, aTask->strSource.c_str(), aTask->strDest.c_str()); } } } if (SUCCEEDED(rc)) { if (fCanceled) { /* * In order to make the progress object to behave nicely, we also have to * notify the object with a complete event when it's canceled. */ aTask->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest), Guest::getStaticComponentName(), Guest::tr("Copying file \"%s\" canceled"), aTask->strSource.c_str()); } else { /* * Even if we succeeded until here make sure to check whether we really transfered * everything. */ if ( cbSize > 0 && cbTransferedTotal == 0) { /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write * to the destination -> access denied. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Access denied when copying file \"%s\" to \"%s\""), aTask->strSource.c_str(), aTask->strDest.c_str()); } else if (cbTransferedTotal < cbSize) { /* If we did not copy all let the user know. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"), aTask->strSource.c_str(), cbTransferedTotal, cbSize); } else /* Yay, all went fine! */ aTask->pProgress->notifyComplete(S_OK); } } } } RTFileClose(fileSource); } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
/** Print the 'true' if nested paging is supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = -1; #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) if (enmHwVirt == HWVIRTTYPE_AMDV) { uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a) { ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */) fSupported = 1; else fSupported = 0; } } # if defined(RT_OS_LINUX) else if (enmHwVirt == HWVIRTTYPE_VTX) { /* * For Intel there is no generic way to query EPT support but on * Linux we can resort to checking for the EPT flag in /proc/cpuinfo */ RTFILE hFileCpu; int rc = RTFileOpen(&hFileCpu, "/proc/cpuinfo", RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Read enough to fit the first CPU entry in, we only check the first * CPU as all the others should have the same features. */ char szBuf[_4K]; size_t cbRead = 0; RT_ZERO(szBuf); /* Ensure proper termination. */ rc = RTFileRead(hFileCpu, &szBuf[0], sizeof(szBuf) - 1, &cbRead); if (RT_SUCCESS(rc)) { /* Look for the start of the flags section. */ char *pszStrFlags = RTStrStr(&szBuf[0], "flags"); if (pszStrFlags) { /* Look for the end as indicated by new line. */ char *pszEnd = pszStrFlags; while ( *pszEnd != '\0' && *pszEnd != '\n') pszEnd++; *pszEnd = '\0'; /* Cut off everything after the flags section. */ /* * Search for the ept flag indicating support and the absence meaning * not supported. */ if (RTStrStr(pszStrFlags, "ept")) fSupported = 1; else fSupported = 0; } } RTFileClose(hFileCpu); } } # endif #endif int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
RTDECL(int) RTFileReadAllByHandleEx(RTFILE File, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile) { AssertReturn(!(fFlags & ~RTFILE_RDALL_VALID_MASK), VERR_INVALID_PARAMETER); /* * Save the current offset first. */ RTFOFF offOrg; int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offOrg); if (RT_SUCCESS(rc)) { /* * Get the file size, adjust it and check that it might fit into memory. */ RTFOFF cbFile; rc = RTFileSeek(File, 0,RTFILE_SEEK_END, (uint64_t *)&cbFile); if (RT_SUCCESS(rc)) { RTFOFF cbAllocFile = cbFile > off ? cbFile - off : 0; if (cbAllocFile > cbMax) cbAllocFile = cbMax; size_t cbAllocMem = (size_t)cbAllocFile; if ((RTFOFF)cbAllocMem == cbAllocFile) { /* * Try allocate the required memory and initialize the header (hardcoded fun). */ void *pvHdr = RTMemAlloc(cbAllocMem + 32); if (pvHdr) { memset(pvHdr, 0xff, 32); *(size_t *)pvHdr = cbAllocMem; /* * Seek and read. */ rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { void *pvFile = (uint8_t *)pvHdr + 32; rc = RTFileRead(File, pvFile, cbAllocMem, NULL); if (RT_SUCCESS(rc)) { /* * Success - fill in the return values. */ *ppvFile = pvFile; *pcbFile = cbAllocMem; } } if (RT_FAILURE(rc)) RTMemFree(pvHdr); } else rc = VERR_NO_MEMORY; } else rc = VERR_TOO_MUCH_DATA; } /* restore the position. */ RTFileSeek(File, offOrg, RTFILE_SEEK_BEGIN, NULL); } return rc; }