Esempio n. 1
0
static void test1(const char *pszSubTest, const char *pszFilename)
{
    int rc;
    RTTestISub(pszSubTest);

    RTFILE hFile;
    rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN);
    if (RT_FAILURE(rc))
    {
        if (   rc == VERR_ACCESS_DENIED
            || rc == VERR_PERMISSION_DENIED
            || rc == VERR_FILE_NOT_FOUND)
        {
            RTTestIPrintf(RTTESTLVL_ALWAYS, "Cannot access '%s', skipping.", pszFilename);
            return;
        }
        RTTESTI_CHECK_RC_RETV(RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN), VINF_SUCCESS);
    }

    uint64_t    cbFile = UINT64_MAX - 42;
    RTTESTI_CHECK_RC(rc = RTFileGetSize(hFile, &cbFile), VINF_SUCCESS);
    if (RT_SUCCESS(rc))
    {
        RTTESTI_CHECK(cbFile != UINT64_MAX - 42);
        RTTestIValue(pszSubTest, cbFile, RTTESTUNIT_BYTES);
    }

    RTFileClose(hFile);
    RTTestISubDone();
}
Esempio n. 2
0
File: tftp.c Progetto: ryenus/vbox
DECLINLINE(int) tftpSessionEvaluateOptions(PNATState pData, PTFTPSESSION pTftpSession)
{
    int rc = VINF_SUCCESS;
    RTFILE hSessionFile;
    uint64_t cbSessionFile = 0;
    LogFlowFunc(("pTftpSession:%p\n", pTftpSession));

    rc = pftpSessionOpenFile(pData, pTftpSession, &hSessionFile);
    if (RT_FAILURE(rc))
    {
        LogFlowFuncLeave();
        return rc;
    }

    rc = RTFileGetSize(hSessionFile, &cbSessionFile);
    RTFileClose(hSessionFile);
    if (RT_FAILURE(rc))
    {
        LogFlowFuncLeave();
        return rc;
    }

    if (pTftpSession->OptionTSize.fRequested)
    {
       pTftpSession->OptionTSize.u64Value = cbSessionFile;
    }
    if (   !pTftpSession->OptionBlkSize.u64Value
        && !pTftpSession->OptionBlkSize.fRequested)
    {
        pTftpSession->OptionBlkSize.u64Value = 1428;
    }
    LogFlowFuncLeaveRC(rc);
    return rc;
}
Esempio n. 3
0
static int fileGetSizeCallback(void * /* pvUser */, void *pvStorage, uint64_t *pcbSize)
{
    /* Validate input. */
    AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);

    PFILESTORAGEINTERNAL pInt = (PFILESTORAGEINTERNAL)pvStorage;

    DEBUG_PRINT_FLOW();

    return RTFileGetSize(pInt->file, pcbSize);
}
Esempio n. 4
0
/** @copydoc KRDROPS::pfnCreate */
static int krdrRTFileCreate(PPKRDR ppRdr, const char *pszFilename)
{
    KSIZE       cchFilename;
    PKRDRFILE   pRdrFile;
    RTFILE      File;
    uint64_t    cb;
    int         rc;
    char        szFilename[RTPATH_MAX];

    /*
     * Open the file, determin its size and correct filename.
     */
    rc = RTFileOpen(&File, pszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
    if (RT_FAILURE(rc))
        return rc;

    rc = RTFileGetSize(File, &cb);
    if (RT_SUCCESS(rc))
    {
        rc = RTPathReal(pszFilename, szFilename, sizeof(szFilename));
        if (RT_SUCCESS(rc))
        {
            /*
             * Allocate the reader instance.
             */
            cchFilename = strlen(szFilename);
            pRdrFile = (PKRDRFILE)RTMemAlloc(sizeof(*pRdrFile) + cchFilename);
            if (pRdrFile)
            {
                /*
                 * Initialize it and return successfully.
                 */
                pRdrFile->Core.u32Magic = KRDR_MAGIC;
                pRdrFile->Core.pOps = &g_kRdrFileOps;
                pRdrFile->File = File;
                pRdrFile->cb = cb;
                pRdrFile->off = 0;
                pRdrFile->cMappings = 0;
                pRdrFile->cPreps = 0;
                memcpy(&pRdrFile->szFilename[0], szFilename, cchFilename + 1);

                *ppRdr = &pRdrFile->Core;
                return 0;
            }

            rc = KERR_NO_MEMORY;
        }
    }

    RTFileClose(File);
    return rc;
}
int main(int argc, char **argv)
{
    /*
     * Initialize IPRT and create the test.
     */
    RTTEST hTest;
    int rc = RTTestInitAndCreate("tstRTDvm", &hTest);
    if (rc)
        return rc;
    RTTestBanner(hTest);

    /*
     * If no args, display usage.
     */
    if (argc < 2)
    {
        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Syntax: %s <image>\n", argv[0]);
        return RTTestSkipAndDestroy(hTest, "Missing required arguments\n");
    }

    /* Open image. */
    RTFILE hFile;
    uint64_t cb = 0;
    rc = RTFileOpen(&hFile, argv[1], RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE);
    if (RT_FAILURE(rc))
    {
        RTTestIFailed("RTFileOpen -> %Rrc", rc);
        return RTTestSummaryAndDestroy(hTest);
    }

    rc = RTFileGetSize(hFile, &cb);
    if (   RT_FAILURE(rc)
        || cb % 512 != 0) /* Assume 512 byte sector size. */
    {
        RTTestIFailed("RTFileGetSize -> %Rrc", rc);
        return RTTestSummaryAndDestroy(hTest);
    }

    TSTRTDVMDISK Disk;

    Disk.fUseImage = true;
    Disk.hImage    = hFile;
    rc = tstRTDvmVolume(hTest, &Disk, cb, 0);

    RTTESTI_CHECK(rc == VINF_SUCCESS);

    /*
     * Summary
     */
    return RTTestSummaryAndDestroy(hTest);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
int main(int argc, char **argv)
{
    int rcRet = 1;
    int rc;
    RTR3InitAndSUPLib();

    /*
     * Parse input.
     */
    if (argc <= 1)
    {
        syntax();
        return 1;
    }

    bool        fPowerOn = false;
    uint32_t    u32WarpDrive = 100; /* % */
    uint64_t    cbMem = ~0ULL;
    const char *pszSavedState = NULL;
    const char *pszRawMem = NULL;
    uint64_t    offRawMem = 0;
    const char *pszScript = NULL;
    for (int i = 1; i < argc; i++)
    {
        if (argv[i][0] == '-')
        {
            /* check that it's on short form */
            if (argv[i][2])
            {
                if (    strcmp(argv[i], "--help")
                    &&  strcmp(argv[i], "-help"))
                    RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]);
                else
                    syntax();
                return 1;
            }

            /* check for 2nd argument */
            switch (argv[i][1])
            {
                case 'r':
                case 'o':
                case 'c':
                case 'm':
                case 'w':
                case 'z':
                    if (i + 1 < argc)
                        break;
                    RTPrintf("tstAnimate: Syntax error: '%s' takes a 2nd argument.\n", argv[i]);
                    return 1;
            }

            /* process argument */
            switch (argv[i][1])
            {
                case 'r':
                    pszRawMem = argv[++i];
                    break;

                case 'z':
                    pszSavedState = argv[++i];
                    break;

                case 'o':
                {
                    rc = RTStrToUInt64Ex(argv[++i], NULL, 0, &offRawMem);
                    if (RT_FAILURE(rc))
                    {
                        RTPrintf("tstAnimate: Syntax error: Invalid offset given to -o.\n");
                        return 1;
                    }
                    break;
                }

                case 'm':
                {
                    char *pszNext;
                    rc = RTStrToUInt64Ex(argv[++i], &pszNext, 0, &cbMem);
                    if (RT_FAILURE(rc))
                    {
                        RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
                        return 1;
                    }
                    switch (*pszNext)
                    {
                        case 'G':   cbMem *= _1G; pszNext++; break;
                        case 'M':   cbMem *= _1M; pszNext++; break;
                        case 'K':   cbMem *= _1K; pszNext++; break;
                        case '\0':  break;
                        default:
                            RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
                            return 1;
                    }
                    if (*pszNext)
                    {
                        RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
                        return 1;
                    }
                    break;
                }

                case 's':
                    pszScript = argv[++i];
                    break;

                case 'p':
                    fPowerOn = true;
                    break;

                case 'w':
                {
                    rc = RTStrToUInt32Ex(argv[++i], NULL, 0, &u32WarpDrive);
                    if (RT_FAILURE(rc))
                    {
                        RTPrintf("tstAnimate: Syntax error: Invalid number given to -w.\n");
                        return 1;
                    }
                    break;
                }

                case 'h':
                case 'H':
                case '?':
                    syntax();
                    return 1;

                default:
                    RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]);
                    return 1;
            }
        }
        else
        {
            RTPrintf("tstAnimate: Syntax error at arg no. %d '%s'.\n", i, argv[i]);
            syntax();
            return 1;
        }
    }

    /*
     * Check that the basic requirements are met.
     */
    if (pszRawMem && pszSavedState)
    {
        RTPrintf("tstAnimate: Syntax error: Either -z or -r, not both.\n");
        return 1;
    }
    if (!pszRawMem && !pszSavedState)
    {
        RTPrintf("tstAnimate: Syntax error: The -r argument is compulsory.\n");
        return 1;
    }

    /*
     * Open the files.
     */
    RTFILE FileRawMem = NIL_RTFILE;
    if (pszRawMem)
    {
        rc = RTFileOpen(&FileRawMem, pszRawMem, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszRawMem, rc);
            return 1;
        }
    }
    RTFILE FileScript = NIL_RTFILE;
    if (pszScript)
    {
        rc = RTFileOpen(&FileScript, pszScript, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszScript, rc);
            return 1;
        }
    }

    /*
     * Figure the memsize if not specified.
     */
    if (cbMem == ~0ULL)
    {
        if (FileRawMem != NIL_RTFILE)
        {
            rc = RTFileGetSize(FileRawMem, &cbMem);
            AssertReleaseRC(rc);
            cbMem -= offRawMem;
            cbMem &= ~(PAGE_SIZE - 1);
        }
        else
        {
            RTPrintf("tstAnimate: error: too lazy to figure out the memsize in a saved state.\n");
            return 1;
        }
    }
    RTPrintf("tstAnimate: info: cbMem=0x%llx bytes\n", cbMem);

    /*
     * Open a release log.
     */
    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
    PRTLOGGER pRelLogger;
    rc = RTLogCreate(&pRelLogger, RTLOGFLAGS_PREFIX_TIME_PROG, "all", "VBOX_RELEASE_LOG",
                     RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_FILE, "./tstAnimate.log");
    if (RT_SUCCESS(rc))
        RTLogRelSetDefaultInstance(pRelLogger);
    else
        RTPrintf("tstAnimate: rtLogCreateEx failed - %Rrc\n", rc);

    /*
     * Create empty VM.
     */
    PVM pVM;
    rc = VMR3Create(1, NULL, NULL, NULL, cfgmR3CreateDefault, &cbMem, &pVM);
    if (RT_SUCCESS(rc))
    {
        /*
         * Load memory.
         */
        if (FileRawMem != NIL_RTFILE)
            rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)loadMem, 3, pVM, FileRawMem, &offRawMem);
        else
            rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)SSMR3Load,
                                 7, pVM, pszSavedState, (uintptr_t)NULL /*pStreamOps*/, (uintptr_t)NULL /*pvUser*/,
                                 SSMAFTER_DEBUG_IT, (uintptr_t)NULL /*pfnProgress*/, (uintptr_t)NULL /*pvProgressUser*/);
        if (RT_SUCCESS(rc))
        {
            /*
             * Load register script.
             */
            if (FileScript != NIL_RTFILE)
                rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)scriptRun, 2, pVM, FileScript);
            if (RT_SUCCESS(rc))
            {
                if (fPowerOn)
                {
                    /*
                     * Adjust warpspeed?
                     */
                    if (u32WarpDrive != 100)
                    {
                        rc = TMR3SetWarpDrive(pVM, u32WarpDrive);
                        if (RT_FAILURE(rc))
                            RTPrintf("warning: TMVirtualSetWarpDrive(,%u) -> %Rrc\n", u32WarpDrive, rc);
                    }

                    /*
                     * Start the thing with single stepping and stuff enabled.
                     * (Try make sure we don't execute anything in raw mode.)
                     */
                    RTPrintf("info: powering on the VM...\n");
                    RTLogGroupSettings(NULL, "+REM_DISAS.e.l.f");
                    rc = REMR3DisasEnableStepping(pVM, true);
                    if (RT_SUCCESS(rc))
                    {
                        rc = EMR3SetExecutionPolicy(pVM, EMEXECPOLICY_RECOMPILE_RING0, true); AssertReleaseRC(rc);
                        rc = EMR3SetExecutionPolicy(pVM, EMEXECPOLICY_RECOMPILE_RING3, true); AssertReleaseRC(rc);
                        DBGFR3Info(pVM, "cpumguest", "verbose", NULL);
                        if (fPowerOn)
                            rc = VMR3PowerOn(pVM);
                        if (RT_SUCCESS(rc))
                        {
                            RTPrintf("info: VM is running\n");
                            signal(SIGINT, SigInterrupt);
                            while (!g_fSignaled)
                                RTThreadSleep(1000);
                        }
                        else
                            RTPrintf("error: Failed to power on the VM: %Rrc\n", rc);
                    }
                    else
                        RTPrintf("error: Failed to enabled singlestepping: %Rrc\n", rc);
                }
                else
                {
                    /*
                     * Don't start it, just enter the debugger.
                     */
                    RTPrintf("info: entering debugger...\n");
                    DBGFR3Info(pVM, "cpumguest", "verbose", NULL);
                    signal(SIGINT, SigInterrupt);
                    while (!g_fSignaled)
                        RTThreadSleep(1000);
                }
                RTPrintf("info: shutting down the VM...\n");
            }
            /* execScript complains */
        }
        else if (FileRawMem == NIL_RTFILE) /* loadMem complains, SSMR3Load doesn't */
            RTPrintf("tstAnimate: error: SSMR3Load failed: rc=%Rrc\n", rc);
        rcRet = RT_SUCCESS(rc) ? 0 : 1;

        /*
         * Cleanup.
         */
        rc = VMR3Destroy(pVM);
        if (!RT_SUCCESS(rc))
        {
            RTPrintf("tstAnimate: error: failed to destroy vm! rc=%Rrc\n", rc);
            rcRet++;
        }
    }
    else
    {
        RTPrintf("tstAnimate: fatal error: failed to create vm! rc=%Rrc\n", rc);
        rcRet++;
    }

    return rcRet;
}
/**
 * Get the size of the given file.
 * Works for block devices too.
 *
 * @returns VBox status code.
 * @param   hFile    The file handle.
 * @param   pcbSize  Where to store the size of the file on success.
 */
static int pdmacFileEpNativeGetSize(RTFILE hFile, uint64_t *pcbSize)
{
    int rc = VINF_SUCCESS;
    uint64_t cbSize = 0;

    rc = RTFileGetSize(hFile, &cbSize);
    if (RT_SUCCESS(rc) && (cbSize != 0))
        *pcbSize = cbSize;
    else
    {
#ifdef RT_OS_WINDOWS
        DISK_GEOMETRY DriveGeo;
        DWORD cbDriveGeo;
        if (DeviceIoControl((HANDLE)RTFileToNative(hFile),
                            IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
                            &DriveGeo, sizeof(DriveGeo), &cbDriveGeo, NULL))
        {
            if (   DriveGeo.MediaType == FixedMedia
                || DriveGeo.MediaType == RemovableMedia)
            {
                cbSize =     DriveGeo.Cylinders.QuadPart
                         *   DriveGeo.TracksPerCylinder
                         *   DriveGeo.SectorsPerTrack
                         *   DriveGeo.BytesPerSector;

                GET_LENGTH_INFORMATION DiskLenInfo;
                DWORD junk;
                if (DeviceIoControl((HANDLE)RTFileToNative(hFile),
                                    IOCTL_DISK_GET_LENGTH_INFO, NULL, 0,
                                    &DiskLenInfo, sizeof(DiskLenInfo), &junk, (LPOVERLAPPED)NULL))
                {
                    /* IOCTL_DISK_GET_LENGTH_INFO is supported -- override cbSize. */
                    cbSize = DiskLenInfo.Length.QuadPart;
                }

                rc = VINF_SUCCESS;
            }
            else
            {
                rc = VERR_INVALID_PARAMETER;
            }
        }
        else
            rc = RTErrConvertFromWin32(GetLastError());

#elif defined(RT_OS_DARWIN)
        struct stat DevStat;
        if (!fstat(RTFileToNative(hFile), &DevStat) && S_ISBLK(DevStat.st_mode))
        {
            uint64_t cBlocks;
            uint32_t cbBlock;
            if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKCOUNT, &cBlocks))
            {
                if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKSIZE, &cbBlock))
                    cbSize = cBlocks * cbBlock;
                else
                    rc = RTErrConvertFromErrno(errno);
            }
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;

#elif defined(RT_OS_SOLARIS)
        struct stat DevStat;
        if (   !fstat(RTFileToNative(hFile), &DevStat)
            && (   S_ISBLK(DevStat.st_mode)
                || S_ISCHR(DevStat.st_mode)))
        {
            struct dk_minfo mediainfo;
            if (!ioctl(RTFileToNative(hFile), DKIOCGMEDIAINFO, &mediainfo))
                cbSize = mediainfo.dki_capacity * mediainfo.dki_lbsize;
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;

#elif defined(RT_OS_FREEBSD)
        struct stat DevStat;
        if (!fstat(RTFileToNative(hFile), &DevStat) && S_ISCHR(DevStat.st_mode))
        {
            off_t cbMedia = 0;
            if (!ioctl(RTFileToNative(hFile), DIOCGMEDIASIZE, &cbMedia))
            {
                cbSize = cbMedia;
            }
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;
#else
        /* Could be a block device */
        rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, &cbSize);
#endif

        if (RT_SUCCESS(rc) && (cbSize != 0))
            *pcbSize = cbSize;
        else if (RT_SUCCESS(rc))
            rc = VERR_NOT_SUPPORTED;
    }

    return rc;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
static int pdmacFileEpInitialize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
                                 const char *pszUri, uint32_t fFlags)
{
    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;
    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->pEpClass;
    PDMACEPFILEMGRTYPE enmMgrType = pEpClassFile->enmMgrTypeOverride;
    PDMACFILEEPBACKEND enmEpBackend = pEpClassFile->enmEpBackendDefault;

    AssertMsgReturn((fFlags & ~(PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_DONT_LOCK | PDMACEP_FILE_FLAGS_HOST_CACHE_ENABLED)) == 0,
                    ("PDMAsyncCompletion: Invalid flag specified\n"), VERR_INVALID_PARAMETER);

    unsigned fFileFlags = RTFILE_O_OPEN;

    /*
     * Revert to the simple manager and the buffered backend if
     * the host cache should be enabled.
     */
    if (fFlags & PDMACEP_FILE_FLAGS_HOST_CACHE_ENABLED)
    {
        enmMgrType   = PDMACEPFILEMGRTYPE_SIMPLE;
        enmEpBackend = PDMACFILEEPBACKEND_BUFFERED;
    }

    if (fFlags & PDMACEP_FILE_FLAGS_READ_ONLY)
        fFileFlags |= RTFILE_O_READ | RTFILE_O_DENY_NONE;
    else
    {
        fFileFlags |= RTFILE_O_READWRITE;

        /*
         * Opened in read/write mode. Check whether the caller wants to
         * avoid the lock. Return an error in case caching is enabled
         * because this can lead to data corruption.
         */
        if (fFlags & PDMACEP_FILE_FLAGS_DONT_LOCK)
            fFileFlags |= RTFILE_O_DENY_NONE;
        else
            fFileFlags |= RTFILE_O_DENY_WRITE;
    }

    if (enmMgrType == PDMACEPFILEMGRTYPE_ASYNC)
        fFileFlags |= RTFILE_O_ASYNC_IO;

    int rc;
    if (enmEpBackend == PDMACFILEEPBACKEND_NON_BUFFERED)
    {
        /*
         * We only disable the cache if the size of the file is a multiple of 512.
         * Certain hosts like Windows, Linux and Solaris require that transfer sizes
         * are aligned to the volume sector size.
         * If not we just make sure that the data is written to disk with RTFILE_O_WRITE_THROUGH
         * which will trash the host cache but ensures that the host cache will not
         * contain dirty buffers.
         */
        RTFILE hFile;
        rc = RTFileOpen(&hFile, pszUri, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
        if (RT_SUCCESS(rc))
        {
            uint64_t cbSize;

            rc = RTFileGetSize(hFile, &cbSize);

            if (RT_SUCCESS(rc) && ((cbSize % 512) == 0))
                fFileFlags |= RTFILE_O_NO_CACHE;
            else
            {
                /* Downgrade to the buffered backend */
                enmEpBackend = PDMACFILEEPBACKEND_BUFFERED;

#ifdef RT_OS_LINUX
                fFileFlags &= ~RTFILE_O_ASYNC_IO;
                enmMgrType   = PDMACEPFILEMGRTYPE_SIMPLE;
#endif
            }
            RTFileClose(hFile);
        }
    }

    /* Open with final flags. */
    rc = RTFileOpen(&pEpFile->hFile, pszUri, fFileFlags);
    if (   rc == VERR_INVALID_FUNCTION
        || rc == VERR_INVALID_PARAMETER)
    {
        LogRel(("pdmacFileEpInitialize: RTFileOpen %s / %08x failed with %Rrc\n",
               pszUri, fFileFlags, rc));
        /*
         * Solaris doesn't support directio on ZFS so far. :-\
         * Trying to enable it returns VERR_INVALID_FUNCTION
         * (ENOTTY). Remove it and hope for the best.
         * ZFS supports write throttling in case applications
         * write more data than can be synced to the disk
         * without blocking the whole application.
         *
         * On Linux we have the same problem with cifs.
         * Have to disable async I/O here too because it requires O_DIRECT.
         */
        fFileFlags &= ~RTFILE_O_NO_CACHE;
        enmEpBackend = PDMACFILEEPBACKEND_BUFFERED;

#ifdef RT_OS_LINUX
        fFileFlags &= ~RTFILE_O_ASYNC_IO;
        enmMgrType   = PDMACEPFILEMGRTYPE_SIMPLE;
#endif

        /* Open again. */
        rc = RTFileOpen(&pEpFile->hFile, pszUri, fFileFlags);

        if (RT_FAILURE(rc))
        {
            LogRel(("pdmacFileEpInitialize: RTFileOpen %s / %08x failed AGAIN(!) with %Rrc\n",
                        pszUri, fFileFlags, rc));
        }
    }

    if (RT_SUCCESS(rc))
    {
        pEpFile->fFlags = fFileFlags;

        rc = RTFileGetSize(pEpFile->hFile, (uint64_t *)&pEpFile->cbFile);
        if (RT_SUCCESS(rc))
        {
            /* Initialize the segment cache */
            rc = MMR3HeapAllocZEx(pEpClassFile->Core.pVM, MM_TAG_PDM_ASYNC_COMPLETION,
                                  sizeof(PDMACTASKFILE),
                                  (void **)&pEpFile->pTasksFreeHead);
            if (RT_SUCCESS(rc))
            {
                PPDMACEPFILEMGR pAioMgr = NULL;

                pEpFile->pTasksFreeTail = pEpFile->pTasksFreeHead;
                pEpFile->cTasksCached   = 0;
                pEpFile->enmBackendType = enmEpBackend;
                /*
                 * Disable async flushes on Solaris for now.
                 * They cause weird hangs which needs more investigations.
                 */
#ifndef RT_OS_SOLARIS
                pEpFile->fAsyncFlushSupported = true;
#else
                pEpFile->fAsyncFlushSupported = false;
#endif

                if (enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE)
                {
                    /* Simple mode. Every file has its own async I/O manager. */
                    rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, PDMACEPFILEMGRTYPE_SIMPLE);
                }
                else
                {
                    pAioMgr = pEpClassFile->pAioMgrHead;

                    /* Check for an idling manager of the same type */
                    while (pAioMgr)
                    {
                        if (pAioMgr->enmMgrType == enmMgrType)
                            break;
                        pAioMgr = pAioMgr->pNext;
                    }

                    if (!pAioMgr)
                        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, enmMgrType);
                }

                if (RT_SUCCESS(rc))
                {
                    pEpFile->AioMgr.pTreeRangesLocked = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
                    if (!pEpFile->AioMgr.pTreeRangesLocked)
                        rc = VERR_NO_MEMORY;
                    else
                    {
                        pEpFile->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE;

                        /* Assign the endpoint to the thread. */
                        rc = pdmacFileAioMgrAddEndpoint(pAioMgr, pEpFile);
                        if (RT_FAILURE(rc))
                        {
                            RTMemFree(pEpFile->AioMgr.pTreeRangesLocked);
                            MMR3HeapFree(pEpFile->pTasksFreeHead);
                        }
                    }
                }
                else if (rc == VERR_FILE_AIO_INSUFFICIENT_EVENTS)
                {
                    PUVM pUVM = VMR3GetUVM(pEpClassFile->Core.pVM);
#if defined(RT_OS_LINUX)
                    rc = VMR3SetError(pUVM, rc, RT_SRC_POS,
                                      N_("Failed to create I/O manager for VM due to insufficient resources on the host. "
                                         "Either increase the amount of allowed events in /proc/sys/fs/aio-max-nr or enable "
                                         "the host I/O cache"));
#else
                    rc = VMR3SetError(pUVM, rc, RT_SRC_POS,
                                      N_("Failed to create I/O manager for VM due to insufficient resources on the host. "
                                         "Enable the host I/O cache"));
#endif
                }
                else
                {
                    PUVM pUVM = VMR3GetUVM(pEpClassFile->Core.pVM);
                    rc = VMR3SetError(pUVM, rc, RT_SRC_POS,
                                      N_("Failed to create I/O manager for VM due to an unknown error"));
                }
            }
        }

        if (RT_FAILURE(rc))
            RTFileClose(pEpFile->hFile);
    }

#ifdef VBOX_WITH_STATISTICS
    if (RT_SUCCESS(rc))
    {
        STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatRead,
                       STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS,
                       STAMUNIT_TICKS_PER_CALL, "Time taken to read from the endpoint",
                       "/PDM/AsyncCompletion/File/%s/Read", RTPathFilename(pEpFile->Core.pszUri));

        STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatWrite,
                       STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS,
                       STAMUNIT_TICKS_PER_CALL, "Time taken to write to the endpoint",
                       "/PDM/AsyncCompletion/File/%s/Write", RTPathFilename(pEpFile->Core.pszUri));
    }
#endif

    if (RT_SUCCESS(rc))
        LogRel(("AIOMgr: Endpoint for file '%s' (flags %08x) created successfully\n", pszUri, pEpFile->fFlags));

    return rc;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
File: s3.cpp Progetto: mcenirm/vbox
RTR3DECL(int) RTS3PutKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename)
{
    PRTS3INTERNAL pS3Int = hS3;
    RTS3_VALID_RETURN(pS3Int);

    /* Reset the CURL object to an defined state */
    rtS3ReinitCurl(pS3Int);

    /* Open the file */
    RTFILE hFile;
    int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
    if (RT_FAILURE(rc))
        return rc;

    uint64_t cbFileSize;
    rc = RTFileGetSize(hFile, &cbFileSize);
    if (RT_FAILURE(rc))
    {
        RTFileClose(hFile);
        return rc;
    }

    char* pszUrl = rtS3Host(pszBucketName, pszKeyName, pS3Int->pszBaseUrl);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_URL, pszUrl);
    RTStrFree(pszUrl);

    char* pszContentLength;
    RTStrAPrintf(&pszContentLength, "Content-Length: %lu", cbFileSize);
    /* Create the three basic header entries */
    char *apszHead[5] =
    {
        /* todo: For now we use octet-stream for all types. Later we should try
         * to set the right one (libmagic from the file packet could be a
         * candidate for finding the right type). */
        RTStrDup("Content-Type: octet-stream"),            /* Content type entry */
        pszContentLength,                                  /* Content length entry */
        rtS3HostHeader(pszBucketName, pS3Int->pszBaseUrl), /* Host entry */
        rtS3DateHeader(),                                  /* Date entry */
        NULL                                               /* Authorization entry */
    };
    /* Create the authorization header entry */
    apszHead[RT_ELEMENTS(apszHead)-1] = rtS3CreateAuthHeader(pS3Int, "PUT", pszBucketName, pszKeyName, apszHead, RT_ELEMENTS(apszHead));

    /* Add all headers to curl */
    struct curl_slist* pHeaders = NULL; /* Init to NULL is important */
    for(size_t i=0; i < RT_ELEMENTS(apszHead); ++i)
        pHeaders = curl_slist_append(pHeaders, apszHead[i]);

    /* Pass our list of custom made headers */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_HTTPHEADER, pHeaders);

    /* Set CURL in upload mode */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_PUT, 1);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_UPLOAD, 1);

    /* Set the size of the file we like to transfer */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_INFILESIZE_LARGE, cbFileSize);

    /* Set the callback which send the content */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_READFUNCTION, rtS3ReadFileCallback);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_READDATA, &hFile);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1);

    /* Start the request */
    rc = rtS3Perform(pS3Int);

    /* Regardless of the result, free all used resources first*/
    curl_slist_free_all(pHeaders);
    for(size_t i=0; i < RT_ELEMENTS(apszHead); ++i)
        RTStrFree(apszHead[i]);

    /* Close the open file */
    RTFileClose(hFile);

    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;
}
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;
}
Esempio n. 19
0
int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
                         uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */, uint32_t fFlags /* = 0 */)
{
    int rc = VINF_SUCCESS;

    switch (enmDest)
    {
        case Source:
            m_strSrcPath = strPath;
            break;

        case Target:
            m_strTgtPath = strPath;
            break;

        default:
            rc = VERR_NOT_IMPLEMENTED;
            break;
    }

    if (   RT_SUCCESS(rc)
        && fOpen) /* Opening mode specified? */
    {
        switch (enmType)
        {
            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, strPath.c_str(), fOpen);
                    LogFlowThisFunc(("strPath=%s, fOpen=0x%x, enmType=%RU32, enmDest=%RU32, rc=%Rrc\n",
                                     strPath.c_str(), fOpen, enmType, enmDest, rc));
                    if (RT_SUCCESS(rc))
                        rc = RTFileGetSize(u.m_hFile, &m_cbSize);

                    if (RT_SUCCESS(rc))
                    {
                        if (   (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */
                            &&  fMode                   /* Some file mode to set specified? */)
                        {
                            rc = RTFileSetMode(u.m_hFile, fMode);
                            if (RT_SUCCESS(rc))
                                m_fMode = fMode;
                        }
                        else if (fOpen & RTFILE_O_READ)
                        {
#if 0 /** @todo Enable this as soon as RTFileGetMode is implemented. */
                            rc = RTFileGetMode(u.m_hFile, &m_fMode);
#else
                            RTFSOBJINFO ObjInfo;
                            rc = RTFileQueryInfo(u.m_hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
                            if (RT_SUCCESS(rc))
                                m_fMode = ObjInfo.Attr.fMode;
#endif
                        }
                    }

                    if (RT_SUCCESS(rc))
                    {
                        LogFlowThisFunc(("cbSize=%RU64, fMode=0x%x\n", m_cbSize, m_fMode));
                        m_cbProcessed = 0;
                    }
                }
                else
                    rc = VINF_SUCCESS;

                break;
            }

            case Directory:
                rc = VINF_SUCCESS;
                break;

            default:
                rc = VERR_NOT_IMPLEMENTED;
                break;
        }
    }

    if (RT_SUCCESS(rc))
        m_Type = enmType;

    LogFlowFuncLeaveRC(rc);
    return rc;
}