VirtualBox

Changeset 33213 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Oct 18, 2010 4:40:21 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66757
Message:

Storage/vbox-img: implement stdin and stdout support. stdin is tested, and mostly works. stdout definitely will not work, as the VFS callbacks are not completed.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/testcase/vbox-img.cpp

    r33083 r33213  
    3333
    3434const char *g_pszProgName = "";
    35 static void showUsage(void)
    36 {
    37     RTStrmPrintf(g_pStdErr,
     35static void printUsage(PRTSTREAM pStrm)
     36{
     37    RTStrmPrintf(pStrm,
    3838                 "Usage: %s\n"
    3939                 "   setuuid      --filename <filename>\n"
     
    4545                 "   convert      --srcfilename <filename>\n"
    4646                 "                --dstfilename <filename>\n"
     47                 "                [--stdin]|[--stdout]\n"
    4748                 "                [--srcformat VDI|VMDK|VHD|RAW|..]\n"
    4849                 "                [--dstformat VDI|VMDK|VHD|RAW|..]\n"
     
    5556}
    5657
     58void showLogo(PRTSTREAM pStrm)
     59{
     60    static bool s_fShown; /* show only once */
     61
     62    if (!s_fShown)
     63    {
     64        RTStrmPrintf(pStrm, VBOX_PRODUCT " Disk Utility " VBOX_VERSION_STRING "\n"
     65                     "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
     66                     "All rights reserved.\n"
     67                     "\n");
     68        s_fShown = true;
     69    }
     70}
     71
    5772/** command handler argument */
    5873struct HandlerArg
     
    85100{
    86101    va_list args;
    87 
     102    showLogo(g_pStdErr); // show logo even if suppressed
    88103    va_start(args, pszFormat);
    89     RTPrintf("\n"
    90              "Syntax error: %N\n", pszFormat, &args);
     104    RTStrmPrintf(g_pStdErr, "\nSyntax error: %N\n", pszFormat, &args);
    91105    va_end(args);
    92     showUsage();
     106    printUsage(g_pStdErr);
    93107    return 1;
    94108}
     109
    95110int errorRuntime(const char *pszFormat, ...)
    96111{
     
    98113
    99114    va_start(args, pszFormat);
    100     RTPrintf("\n"
    101              "Error: %N\n", pszFormat, &args);
     115    RTMsgErrorV(pszFormat, args);
    102116    va_end(args);
    103117    return 1;
     
    156170            default:
    157171                ch = RTGetOptPrintError(ch, &ValueUnion);
    158                 showUsage();
     172                printUsage(g_pStdErr);
    159173                return ch;
    160174        }
     
    238252
    239253
     254typedef struct FILEIOSTATE
     255{
     256    /** Offset in the file. */
     257    uint64_t off;
     258    /** Offset where the buffer contents start. UINT64_MAX=buffer invalid. */
     259    uint64_t offBuffer;
     260    /** Size of valid data in the buffer. */
     261    uint32_t cbBuffer;
     262    /** Buffer for efficient I/O */
     263    uint8_t abBuffer[16 *_1M];
     264} FILEIOSTATE, *PFILEIOSTATE;
     265
     266static int convInOpen(void *pvUser, const char *pszLocation,
     267                      uint32_t fOpen, PFNVDCOMPLETED pfnCompleted,
     268                      void **ppStorage)
     269{
     270    NOREF(pvUser);
     271    /* Validate input. */
     272    AssertPtrReturn(ppStorage, VERR_INVALID_POINTER);
     273    AssertPtrNullReturn(pfnCompleted, VERR_INVALID_PARAMETER);
     274    AssertReturn((fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ, VERR_INVALID_PARAMETER);
     275
     276    PFILEIOSTATE pFS = (PFILEIOSTATE)RTMemAlloc(sizeof(FILEIOSTATE));
     277    if (!pFS)
     278        return VERR_NO_MEMORY;
     279
     280    pFS->off = 0;
     281    pFS->offBuffer = UINT64_MAX;
     282    pFS->cbBuffer = 0;
     283
     284    *ppStorage = pFS;
     285    return VINF_SUCCESS;
     286}
     287
     288static int convInClose(void *pvUser, void *pStorage)
     289{
     290    NOREF(pvUser);
     291    AssertPtrReturn(pStorage, VERR_INVALID_POINTER);
     292
     293    PFILEIOSTATE pFS = (PFILEIOSTATE)pStorage;
     294
     295    RTMemFree(pFS);
     296
     297    return VINF_SUCCESS;
     298}
     299
     300static int convInDelete(void *pvUser, const char *pcszFilename)
     301{
     302    NOREF(pvUser);
     303    NOREF(pcszFilename);
     304    AssertFailedReturn(VERR_NOT_SUPPORTED);
     305}
     306
     307static int convInMove(void *pvUser, const char *pcszSrc, const char *pcszDst,
     308                      unsigned fMove)
     309{
     310    NOREF(pvUser);
     311    NOREF(pcszSrc);
     312    NOREF(pcszDst);
     313    NOREF(fMove);
     314    AssertFailedReturn(VERR_NOT_SUPPORTED);
     315}
     316
     317static int convInGetFreeSpace(void *pvUser, const char *pcszFilename,
     318                              int64_t *pcbFreeSpace)
     319{
     320    NOREF(pvUser);
     321    NOREF(pcszFilename);
     322    AssertPtrReturn(pcbFreeSpace, VERR_INVALID_POINTER);
     323    *pcbFreeSpace = 0;
     324    return VINF_SUCCESS;
     325}
     326
     327static int convInGetModificationTime(void *pvUser, const char *pcszFilename,
     328                                     PRTTIMESPEC pModificationTime)
     329{
     330    NOREF(pvUser);
     331    NOREF(pcszFilename);
     332    AssertPtrReturn(pModificationTime, VERR_INVALID_POINTER);
     333    AssertFailedReturn(VERR_NOT_SUPPORTED);
     334}
     335
     336static int convInGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
     337{
     338    NOREF(pvUser);
     339    NOREF(pStorage);
     340    AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
     341    AssertFailedReturn(VERR_NOT_SUPPORTED);
     342}
     343
     344static int convInSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
     345{
     346    NOREF(pvUser);
     347    NOREF(pStorage);
     348    NOREF(cbSize);
     349    AssertFailedReturn(VERR_NOT_SUPPORTED);
     350}
     351
     352static int convInRead(void *pvUser, void *pStorage, uint64_t uOffset,
     353                      void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     354{
     355    NOREF(pvUser);
     356    AssertPtrReturn(pStorage, VERR_INVALID_POINTER);
     357    AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
     358    PFILEIOSTATE pFS = (PFILEIOSTATE)pStorage;
     359    AssertReturn(uOffset >= pFS->off, VERR_INVALID_PARAMETER);
     360    int rc;
     361
     362    /* Fill buffer if it is empty. */
     363    if (pFS->offBuffer == UINT64_MAX)
     364    {
     365        size_t cbRead = 0;
     366        rc = RTFileRead(0, &pFS->abBuffer[0], sizeof(pFS->abBuffer),
     367                        &cbRead);
     368        if (RT_FAILURE(rc))
     369            return rc;
     370
     371        pFS->offBuffer = 0;
     372        pFS->cbBuffer = cbRead;
     373    }
     374
     375    /* Read several blocks and assemble the result if necessary */
     376    size_t cbTotalRead = 0;
     377    do
     378    {
     379        /* Skip over areas no one wants to read. */
     380        while (uOffset > pFS->offBuffer + pFS->cbBuffer - 1)
     381        {
     382            if (pFS->cbBuffer < sizeof(pFS->abBuffer))
     383            {
     384                if (pcbRead)
     385                    *pcbRead = cbTotalRead;
     386                return VERR_EOF;
     387            }
     388
     389            size_t cbRead = 0;
     390            rc = RTFileRead(0, &pFS->abBuffer[0], sizeof(pFS->abBuffer),
     391                            &cbRead);
     392            if (RT_FAILURE(rc))
     393            {
     394                if (pcbRead)
     395                    *pcbRead = cbTotalRead;
     396                return rc;
     397            }
     398
     399            pFS->offBuffer += pFS->cbBuffer;
     400            pFS->cbBuffer = cbRead;
     401        }
     402
     403        uint32_t cbThisRead = RT_MIN(cbBuffer,
     404                                     pFS->cbBuffer - uOffset % sizeof(pFS->abBuffer));
     405        memcpy(pvBuffer, &pFS->abBuffer[uOffset % sizeof(pFS->abBuffer)],
     406               cbThisRead);
     407        uOffset += cbThisRead;
     408        pvBuffer = (uint8_t *)pvBuffer + cbThisRead;
     409        cbBuffer -= cbThisRead;
     410        cbTotalRead += cbThisRead;
     411    } while (cbBuffer > 0);
     412
     413    if (pcbRead)
     414        *pcbRead = cbTotalRead;
     415
     416    return VINF_SUCCESS;
     417}
     418
     419static int convInWrite(void *pvUser, void *pStorage, uint64_t uOffset,
     420                       const void *pvBuffer, size_t cbBuffer,
     421                       size_t *pcbWritten)
     422{
     423    NOREF(pvUser);
     424    NOREF(pStorage);
     425    NOREF(uOffset);
     426    NOREF(cbBuffer);
     427    NOREF(pcbWritten);
     428    AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
     429    AssertFailedReturn(VERR_NOT_SUPPORTED);
     430}
     431
     432static int convInFlush(void *pvUser, void *pStorage)
     433{
     434    NOREF(pvUser);
     435    NOREF(pStorage);
     436    return VINF_SUCCESS;
     437}
     438
     439static int convOutOpen(void *pvUser, const char *pszLocation,
     440                       uint32_t fOpen, PFNVDCOMPLETED pfnCompleted,
     441                       void **ppStorage)
     442{
     443    NOREF(pvUser);
     444    /* Validate input. */
     445    AssertPtrReturn(ppStorage, VERR_INVALID_POINTER);
     446    AssertPtrNullReturn(pfnCompleted, VERR_INVALID_PARAMETER);
     447    AssertReturn((fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_WRITE, VERR_INVALID_PARAMETER);
     448
     449    PFILEIOSTATE pFS = (PFILEIOSTATE)RTMemAlloc(sizeof(FILEIOSTATE));
     450    if (!pFS)
     451        return VERR_NO_MEMORY;
     452
     453    pFS->off = 0;
     454    pFS->offBuffer = UINT64_MAX;
     455    pFS->cbBuffer = 0;
     456
     457    *ppStorage = pFS;
     458    return VINF_SUCCESS;
     459}
     460
     461static int convOutClose(void *pvUser, void *pStorage)
     462{
     463    NOREF(pvUser);
     464    AssertPtrReturn(pStorage, VERR_INVALID_POINTER);
     465
     466    PFILEIOSTATE pFS = (PFILEIOSTATE)pStorage;
     467
     468    RTMemFree(pFS);
     469
     470    return VINF_SUCCESS;
     471}
     472
     473static int convOutDelete(void *pvUser, const char *pcszFilename)
     474{
     475    NOREF(pvUser);
     476    NOREF(pcszFilename);
     477    AssertFailedReturn(VERR_NOT_SUPPORTED);
     478}
     479
     480static int convOutMove(void *pvUser, const char *pcszSrc, const char *pcszDst,
     481                       unsigned fMove)
     482{
     483    NOREF(pvUser);
     484    NOREF(pcszSrc);
     485    NOREF(pcszDst);
     486    NOREF(fMove);
     487    AssertFailedReturn(VERR_NOT_SUPPORTED);
     488}
     489
     490static int convOutGetFreeSpace(void *pvUser, const char *pcszFilename,
     491                               int64_t *pcbFreeSpace)
     492{
     493    NOREF(pvUser);
     494    NOREF(pcszFilename);
     495    AssertPtrReturn(pcbFreeSpace, VERR_INVALID_POINTER);
     496    *pcbFreeSpace = INT64_MAX;
     497    return VINF_SUCCESS;
     498}
     499
     500static int convOutGetModificationTime(void *pvUser, const char *pcszFilename,
     501                                      PRTTIMESPEC pModificationTime)
     502{
     503    NOREF(pvUser);
     504    NOREF(pcszFilename);
     505    AssertPtrReturn(pModificationTime, VERR_INVALID_POINTER);
     506    AssertFailedReturn(VERR_NOT_SUPPORTED);
     507}
     508
     509static int convOutGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
     510{
     511    NOREF(pvUser);
     512    NOREF(pStorage);
     513    AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
     514    AssertFailedReturn(VERR_NOT_SUPPORTED);
     515}
     516
     517static int convOutSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
     518{
     519    NOREF(pvUser);
     520    NOREF(pStorage);
     521    NOREF(cbSize);
     522    AssertFailedReturn(VERR_NOT_SUPPORTED);
     523}
     524
     525static int convOutRead(void *pvUser, void *pStorage, uint64_t uOffset,
     526                       void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     527{
     528    NOREF(pvUser);
     529    NOREF(pStorage);
     530    NOREF(uOffset);
     531    NOREF(cbBuffer);
     532    NOREF(pcbRead);
     533    AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
     534    AssertFailedReturn(VERR_NOT_SUPPORTED);
     535}
     536
     537static int convOutWrite(void *pvUser, void *pStorage, uint64_t uOffset,
     538                        const void *pvBuffer, size_t cbBuffer,
     539                        size_t *pcbWritten)
     540{
     541    NOREF(pvUser);
     542    NOREF(pStorage);
     543    NOREF(uOffset);
     544    NOREF(cbBuffer);
     545    NOREF(pcbWritten);
     546    AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
     547    AssertFailedReturn(VERR_NOT_SUPPORTED);
     548}
     549
     550static int convOutFlush(void *pvUser, void *pStorage)
     551{
     552    NOREF(pvUser);
     553    NOREF(pStorage);
     554    return VINF_SUCCESS;
     555}
     556
    240557int handleConvert(HandlerArg *a)
    241558{
    242559    const char *pszSrcFilename = NULL;
    243560    const char *pszDstFilename = NULL;
     561    bool fStdIn = false;
     562    bool fStdOut = false;
    244563    char *pszSrcFormat = NULL;
    245564    const char *pszDstFormat = NULL;
     
    248567    PVBOXHDD pDstDisk = NULL;
    249568    unsigned uImageFlags = VD_IMAGE_FLAGS_NONE;
     569    PVDINTERFACE pIfsImageInput = NULL;
     570    PVDINTERFACE pIfsImageOutput = NULL;
     571    VDINTERFACE IfsInputIO;
     572    VDINTERFACE IfsOutputIO;
     573    VDINTERFACEIO IfsInputIOCb;
     574    VDINTERFACEIO IfsOutputIOCb;
    250575    int rc = VINF_SUCCESS;
    251576
     
    255580        { "--srcfilename", 'i', RTGETOPT_REQ_STRING },
    256581        { "--dstfilename", 'o', RTGETOPT_REQ_STRING },
     582        { "--stdin", 'p', RTGETOPT_REQ_NOTHING },
     583        { "--stdout", 'P', RTGETOPT_REQ_NOTHING },
    257584        { "--srcformat", 's', RTGETOPT_REQ_STRING },
    258585        { "--dstformat", 'd', RTGETOPT_REQ_STRING },
     
    273600                pszDstFilename = ValueUnion.psz;
    274601                break;
     602            case 'p':   // --stdin
     603                fStdIn = true;
     604                break;
     605            case 'P':   // --stdout
     606                fStdOut = true;
     607                break;
    275608            case 's':   // --srcformat
    276609                pszSrcFormat = RTStrDup(ValueUnion.psz);
     
    285618            default:
    286619                ch = RTGetOptPrintError(ch, &ValueUnion);
    287                 showUsage();
     620                printUsage(g_pStdErr);
    288621                return ch;
    289622        }
     
    295628    if (!pszDstFilename)
    296629        return errorSyntax("Mandatory --dstfilename option missing\n");
     630
     631    if (fStdIn)
     632    {
     633        IfsInputIOCb.cbSize                 = sizeof(VDINTERFACEIO);
     634        IfsInputIOCb.enmInterface           = VDINTERFACETYPE_IO;
     635        IfsInputIOCb.pfnOpen                = convInOpen;
     636        IfsInputIOCb.pfnClose               = convInClose;
     637        IfsInputIOCb.pfnDelete              = convInDelete;
     638        IfsInputIOCb.pfnMove                = convInMove;
     639        IfsInputIOCb.pfnGetFreeSpace        = convInGetFreeSpace;
     640        IfsInputIOCb.pfnGetModificationTime = convInGetModificationTime;
     641        IfsInputIOCb.pfnGetSize             = convInGetSize;
     642        IfsInputIOCb.pfnSetSize             = convInSetSize;
     643        IfsInputIOCb.pfnReadSync            = convInRead;
     644        IfsInputIOCb.pfnWriteSync           = convInWrite;
     645        IfsInputIOCb.pfnFlushSync           = convInFlush;
     646        VDInterfaceAdd(&IfsInputIO, "stdin", VDINTERFACETYPE_IO,
     647                       &IfsInputIOCb, NULL, &pIfsImageInput);
     648    }
     649    if (fStdOut)
     650    {
     651        IfsOutputIOCb.cbSize                    = sizeof(VDINTERFACEIO);
     652        IfsOutputIOCb.enmInterface              = VDINTERFACETYPE_IO;
     653        IfsOutputIOCb.pfnOpen                   = convOutOpen;
     654        IfsOutputIOCb.pfnClose                  = convOutClose;
     655        IfsOutputIOCb.pfnDelete                 = convOutDelete;
     656        IfsOutputIOCb.pfnMove                   = convOutMove;
     657        IfsOutputIOCb.pfnGetFreeSpace           = convOutGetFreeSpace;
     658        IfsOutputIOCb.pfnGetModificationTime    = convOutGetModificationTime;
     659        IfsOutputIOCb.pfnGetSize                = convOutGetSize;
     660        IfsOutputIOCb.pfnSetSize                = convOutSetSize;
     661        IfsOutputIOCb.pfnReadSync               = convOutRead;
     662        IfsOutputIOCb.pfnWriteSync              = convOutWrite;
     663        IfsOutputIOCb.pfnFlushSync              = convOutFlush;
     664        VDInterfaceAdd(&IfsOutputIO, "stdout", VDINTERFACETYPE_IO,
     665                       &IfsOutputIOCb, NULL, &pIfsImageOutput);
     666    }
    297667
    298668    /* check the variant parameter */
     
    350720        }
    351721
    352         rc = VDOpen(pSrcDisk, pszSrcFormat, pszSrcFilename, VD_OPEN_FLAGS_READONLY, NULL);
     722        rc = VDOpen(pSrcDisk, pszSrcFormat, pszSrcFilename,
     723                    VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SEQUENTIAL,
     724                    pIfsImageInput);
    353725        if (RT_FAILURE(rc))
    354726        {
     
    369741
    370742        uint64_t cbSize = VDGetSize(pSrcDisk, VD_LAST_IMAGE);
    371         RTPrintf("Converting image \"%s\" with size %RU64 bytes (%RU64MB)...\n", pszSrcFilename, cbSize, (cbSize + _1M - 1) / _1M);
     743        RTStrmPrintf(g_pStdErr, "Converting image \"%s\" with size %RU64 bytes (%RU64MB)...\n", pszSrcFilename, cbSize, (cbSize + _1M - 1) / _1M);
    372744
    373745        /* Create the output image */
    374746        rc = VDCopy(pSrcDisk, VD_LAST_IMAGE, pDstDisk, pszDstFormat,
    375747                    pszDstFilename, false, 0, uImageFlags, NULL,
    376                     VD_OPEN_FLAGS_NORMAL, NULL, NULL, NULL);
     748                    VD_OPEN_FLAGS_NORMAL, NULL, pIfsImageOutput, NULL);
    377749        if (RT_FAILURE(rc))
    378750        {
     
    418790            default:
    419791                ch = RTGetOptPrintError(ch, &ValueUnion);
    420                 showUsage();
     792                printUsage(g_pStdErr);
    421793                return ch;
    422794        }
     
    448820    return rc;
    449821}
     822
    450823
    451824int handleCompact(HandlerArg *a)
     
    474847            default:
    475848                ch = RTGetOptPrintError(ch, &ValueUnion);
    476                 showUsage();
     849                printUsage(g_pStdErr);
    477850                return ch;
    478851        }
     
    508881
    509882
    510 void showLogo()
    511 {
    512     RTPrintf(VBOX_PRODUCT" Disk Utility "
    513              VBOX_VERSION_STRING  "\n"
    514              "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
    515              "All rights reserved.\n"
    516              "\n");
    517 }
    518 
    519 
    520883int main(int argc, char *argv[])
    521884{
     
    525888    g_pszProgName = RTPathFilename(argv[0]);
    526889
    527     bool fShowLogo = true;
     890    bool fShowLogo = false;
    528891    int  iCmd      = 1;
    529892    int  iCmdArg;
     
    539902            ||  !strcmp(argv[i], "--help"))
    540903        {
    541             showLogo();
    542             showUsage();
     904            showLogo(g_pStdOut);
     905            printUsage(g_pStdOut);
    543906            return 0;
    544907        }
     
    571934
    572935    if (fShowLogo)
    573         showLogo();
     936        showLogo(g_pStdOut);
    574937
    575938    /* initialize the VD backend with dummy handlers */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette