VirtualBox

Ignore:
Timestamp:
Jul 7, 2018 4:22:45 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123501
Message:

VBoxManage,manual: Added a new command called 'mediumio' to VBoxManage for making use of the IMediumIO interface.

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r70582 r72949  
    123123    { "startvm",            USAGE_STARTVM,          VBMG_CMD_TODO, handleStartVM,              0 },
    124124    { "controlvm",          USAGE_CONTROLVM,        VBMG_CMD_TODO, handleControlVM,            0 },
    125     { "unattended",         USAGE_UNATTENDEDINSTALL, HELP_CMD_UNATTENDED, handleUnattended,    0 },
     125    { "unattended",         USAGE_UNATTENDED, HELP_CMD_UNATTENDED, handleUnattended,    0 },
    126126    { "discardstate",       USAGE_DISCARDSTATE,     VBMG_CMD_TODO, handleDiscardState,         0 },
    127127    { "adoptstate",         USAGE_ADOPTSTATE,       VBMG_CMD_TODO, handleAdoptState,           0 },
     
    133133    { "showhdinfo",         USAGE_SHOWMEDIUMINFO,   VBMG_CMD_TODO, handleShowMediumInfo,       0 }, /* backward compatibility */
    134134    { "showvdiinfo",        USAGE_SHOWMEDIUMINFO,   VBMG_CMD_TODO, handleShowMediumInfo,       0 }, /* backward compatibility */
     135    { "mediumio",           USAGE_MEDIUMIO,     HELP_CMD_MEDIUMIO, handleMediumIO,             0 },
    135136    { "getextradata",       USAGE_GETEXTRADATA,     VBMG_CMD_TODO, handleGetExtraData,         0 },
    136137    { "setextradata",       USAGE_SETEXTRADATA,     VBMG_CMD_TODO, handleSetExtraData,         0 },
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r70582 r72949  
    7575#define USAGE_SHAREDFOLDER_ADD      RT_BIT_64(25)
    7676#define USAGE_SHAREDFOLDER_REMOVE   RT_BIT_64(26)
     77#define USAGE_UNATTENDED            RT_BIT_64(27)
     78#define USAGE_MEDIUMIO              RT_BIT_64(28)
    7779#define USAGE_LOADSYMS              RT_BIT_64(29)
    7880#define USAGE_LOADMAP               RT_BIT_64(30)
     
    135137#endif
    136138
    137 #define USAGE_UNATTENDEDINSTALL     RT_BIT(27)
    138139
    139140typedef uint64_t USAGECATEGORY;
     
    298299RTEXITCODE handleShowMediumInfo(HandlerArg *a);
    299300RTEXITCODE handleCloseMedium(HandlerArg *a);
     301RTEXITCODE handleMediumIO(HandlerArg *a);
    300302int parseMediumType(const char *psz, MediumType_T *penmMediumType);
    301303int parseBool(const char *psz, bool *pb);
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

    r72883 r72949  
    4141#include "VBoxManage.h"
    4242using namespace com;
     43
     44/** Medium category. */
     45typedef enum MEDIUMCATEGORY
     46{
     47    MEDIUMCATEGORY_NONE = 0,
     48    MEDIUMCATEGORY_DISK,
     49    MEDIUMCATEGORY_DVD,
     50    MEDIUMCATEGORY_FLOPPY
     51} MEDIUMCATEGORY;
     52
    4353
    4454
     
    19421952}
    19431953
     1954
     1955/*********************************************************************************************************************************
     1956*   The mediumio command                                                                                                         *
     1957*********************************************************************************************************************************/
     1958
     1959/**
     1960 * Common MediumIO options.
     1961 */
     1962typedef struct MEDIUMIOCOMMONOPT
     1963{
     1964    const char     *pszFilenameOrUuid;
     1965    DeviceType_T    enmDeviceType;
     1966    const char     *pszPasswordFile;
     1967} MEDIUMIOCOMMONOPT;
     1968typedef MEDIUMIOCOMMONOPT *PMEDIUMIOCOMMONOPT;
     1969typedef MEDIUMIOCOMMONOPT const *PCMEDIUMIOCOMMONOPT;
     1970
     1971/* For RTGETOPTDEF array initializer. */
     1972#define MEDIUMIOCOMMONOPT_DEFS() \
     1973    { "--disk",          'd', RTGETOPT_REQ_STRING }, \
     1974    { "--harddisk",      'd', RTGETOPT_REQ_STRING }, \
     1975    { "disk",            'd', RTGETOPT_REQ_STRING }, \
     1976    { "harddisk",        'd', RTGETOPT_REQ_STRING }, \
     1977    { "--dvd",           'D', RTGETOPT_REQ_STRING }, \
     1978    { "--iso",           'D', RTGETOPT_REQ_STRING }, \
     1979    { "dvd",             'D', RTGETOPT_REQ_STRING }, \
     1980    { "iso",             'D', RTGETOPT_REQ_STRING }, \
     1981    { "--floppy",        'f', RTGETOPT_REQ_STRING }, \
     1982    { "floppy",          'f', RTGETOPT_REQ_STRING }, \
     1983    { "--password-file", 'P', RTGETOPT_REQ_STRING }
     1984
     1985/* For option switch. */
     1986#define MEDIUMIOCOMMONOPT_CASES(a_pCommonOpts) \
     1987    case 'd': \
     1988        (a_pCommonOpts)->enmDeviceType     = DeviceType_HardDisk; \
     1989        (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \
     1990        break; \
     1991    case 'D': \
     1992        (a_pCommonOpts)->enmDeviceType     = DeviceType_DVD; \
     1993        (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \
     1994        break; \
     1995    case 'f': \
     1996        (a_pCommonOpts)->enmDeviceType     = DeviceType_Floppy; \
     1997        (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \
     1998        break; \
     1999    case 'P': \
     2000        (a_pCommonOpts)->pszPasswordFile = ValueUnion.psz; \
     2001        break
     2002
     2003
     2004/**
     2005 * Worker for mediumio operations that returns a IMediumIO for the specified
     2006 * medium.
     2007 *
     2008 * @returns Exit code.
     2009 * @param   pHandler        The handler state structure (for IVirtualBox).
     2010 * @param   pCommonOpts     Common mediumio options.
     2011 * @param   fWritable       Whether to open writable (true) or read only
     2012 *                          (false).
     2013 * @param   rPtrMediumIO    Where to return the IMediumIO pointer.
     2014 * @param   pcbMedium       Where to return the meidum size. Optional.
     2015 */
     2016static RTEXITCODE mediumIOOpenMediumForIO(HandlerArg *pHandler, PCMEDIUMIOCOMMONOPT pCommonOpts, bool fWritable,
     2017                                          ComPtr<IMediumIO> &rPtrMediumIO, uint64_t *pcbMedium = NULL)
     2018{
     2019    /* Clear returns. */
     2020    if (pcbMedium)
     2021        *pcbMedium = 0;
     2022    rPtrMediumIO.setNull();
     2023
     2024    /*
     2025     * Make sure a medium was specified already.
     2026     */
     2027    if (pCommonOpts->enmDeviceType == MEDIUMCATEGORY_NONE)
     2028        return errorSyntax("No medium specified!");
     2029
     2030    /*
     2031     * Read the password.
     2032     */
     2033    Bstr bstrPassword;
     2034    if (pCommonOpts->pszPasswordFile)
     2035    {
     2036        Utf8Str strPassword;
     2037        RTEXITCODE rcExit;
     2038        if (pCommonOpts->pszPasswordFile[0] == '-' && pCommonOpts->pszPasswordFile[1] == '\0')
     2039            rcExit = readPasswordFromConsole(&strPassword, "Enter encryption password:");
     2040        else
     2041            rcExit = readPasswordFile(pCommonOpts->pszPasswordFile, &strPassword);
     2042        if (rcExit != RTEXITCODE_SUCCESS)
     2043            return rcExit;
     2044        bstrPassword = strPassword;
     2045        strPassword.assign(strPassword.length(), '*');
     2046    }
     2047
     2048    /*
     2049     * Open the medium and then get I/O access to it.
     2050     */
     2051    ComPtr<IMedium> ptrMedium;
     2052    HRESULT hrc = openMedium(pHandler, pCommonOpts->pszFilenameOrUuid, pCommonOpts->enmDeviceType,
     2053                             fWritable ? AccessMode_ReadWrite : AccessMode_ReadOnly,
     2054                             ptrMedium, false /* fForceNewUuidOnOpen */, false /* fSilent */);
     2055    if (SUCCEEDED(hrc))
     2056        CHECK_ERROR2I_STMT(ptrMedium, OpenForIO(fWritable, bstrPassword.raw(), rPtrMediumIO.asOutParam()), hrc = hrcCheck);
     2057
     2058    /*
     2059     * If the size is requested get it after we've opened it.
     2060     */
     2061    if (pcbMedium && SUCCEEDED(hrc))
     2062    {
     2063        LONG64 cbLogical = 0;
     2064        CHECK_ERROR2I_STMT(ptrMedium, COMGETTER(LogicalSize)(&cbLogical), hrc = hrcCheck);
     2065        *pcbMedium = cbLogical;
     2066        if (!SUCCEEDED(hrc))
     2067            rPtrMediumIO.setNull();
     2068    }
     2069
     2070    memset(bstrPassword.mutableRaw(), '*', bstrPassword.length() * sizeof(RTUTF16));
     2071    return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
     2072}
     2073
     2074
     2075/**
     2076 * mediumio formatfat
     2077 */
     2078static RTEXITCODE handleMediumIOFormatFat(HandlerArg *a, int iFirst, PMEDIUMIOCOMMONOPT pCommonOpts)
     2079{
     2080    /*
     2081     * Parse the options.
     2082     */
     2083    bool fQuick = false;
     2084    static const RTGETOPTDEF s_aOptions[] =
     2085    {
     2086        MEDIUMIOCOMMONOPT_DEFS(),
     2087        { "--quick",  'q', RTGETOPT_REQ_NOTHING },
     2088    };
     2089
     2090    RTGETOPTSTATE GetState;
     2091    int rc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
     2092    AssertRC(rc);
     2093    RTGETOPTUNION ValueUnion;
     2094    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
     2095    {
     2096        switch (rc)
     2097        {
     2098            MEDIUMIOCOMMONOPT_CASES(pCommonOpts);
     2099
     2100            case 'q':
     2101                fQuick = true;
     2102                break;
     2103
     2104            default:
     2105                return errorGetOpt(rc, &ValueUnion);
     2106        }
     2107    }
     2108
     2109    /*
     2110     * Open the medium for I/O and format it.
     2111     */
     2112    ComPtr<IMediumIO> ptrMediumIO;
     2113    RTEXITCODE rcExit = mediumIOOpenMediumForIO(a, pCommonOpts, true /*fWritable*/, ptrMediumIO);
     2114    if (rcExit != RTEXITCODE_SUCCESS)
     2115        return rcExit;
     2116    CHECK_ERROR2I_RET(ptrMediumIO, FormatFAT(fQuick), RTEXITCODE_FAILURE);
     2117    return RTEXITCODE_SUCCESS;
     2118}
     2119
     2120/**
     2121 * mediumio cat
     2122 */
     2123static RTEXITCODE handleMediumIOCat(HandlerArg *a, int iFirst, PMEDIUMIOCOMMONOPT pCommonOpts)
     2124{
     2125    /*
     2126     * Parse the options.
     2127     */
     2128    static const RTGETOPTDEF s_aOptions[] =
     2129    {
     2130        MEDIUMIOCOMMONOPT_DEFS(),
     2131        { "--hex",      'H', RTGETOPT_REQ_NOTHING },
     2132        { "--offset",   'o', RTGETOPT_REQ_UINT64  },
     2133        { "--output",   'O', RTGETOPT_REQ_UINT64  },
     2134        { "--size",     's', RTGETOPT_REQ_UINT64  },
     2135    };
     2136    bool        fHex      = false;
     2137    uint64_t    off       = 0;
     2138    const char *pszOutput = NULL;
     2139    uint64_t    cb        = UINT64_MAX;
     2140
     2141    RTGETOPTSTATE GetState;
     2142    int rc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
     2143    AssertRC(rc);
     2144    RTGETOPTUNION ValueUnion;
     2145    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
     2146    {
     2147        switch (rc)
     2148        {
     2149            MEDIUMIOCOMMONOPT_CASES(pCommonOpts);
     2150
     2151            case 'H':
     2152                fHex = true;
     2153                break;
     2154
     2155            case 'o':
     2156                off = ValueUnion.u64;
     2157                break;
     2158
     2159            case 'O':
     2160                pszOutput = ValueUnion.psz;
     2161                break;
     2162
     2163            case 's':
     2164                cb = ValueUnion.u64;
     2165                break;
     2166
     2167            default:
     2168                return errorGetOpt(rc, &ValueUnion);
     2169        }
     2170    }
     2171
     2172    /*
     2173     * Open the medium for I/O.
     2174     */
     2175    ComPtr<IMediumIO>   ptrMediumIO;
     2176    uint64_t            cbMedium;
     2177    RTEXITCODE rcExit = mediumIOOpenMediumForIO(a, pCommonOpts, false /*fWritable*/, ptrMediumIO, &cbMedium);
     2178    if (rcExit == RTEXITCODE_SUCCESS)
     2179    {
     2180        /*
     2181         * Do we have an output file or do we write to stdout?
     2182         */
     2183        PRTSTREAM pOut = NULL;
     2184        if (pszOutput && (pszOutput[0] != '-' || pszOutput[1] != '\0'))
     2185        {
     2186            int vrc = RTStrmOpen(pszOutput, fHex ? "wt" : "wb", &pOut);
     2187            if (RT_FAILURE(vrc))
     2188                rcExit = RTMsgErrorExitFailure("Error opening '%s' for writing: %Rrc", pszOutput, vrc);
     2189        }
     2190        else
     2191        {
     2192            pOut = g_pStdOut;
     2193            if (!fHex)
     2194                RTStrmSetMode(pOut, true, -1);
     2195        }
     2196
     2197        if (rcExit == RTEXITCODE_SUCCESS)
     2198        {
     2199            /*
     2200             * Adjust 'cb' now that we've got the medium size.
     2201             */
     2202            if (off >= cbMedium)
     2203            {
     2204                RTMsgWarning("Specified offset (%#RX64) is beyond the end of the medium (%#RX64)", off, cbMedium);
     2205                cb = 0;
     2206            }
     2207            else if (   cb > cbMedium
     2208                     || cb + off > cbMedium)
     2209                cb = cbMedium - off;
     2210
     2211            /*
     2212             * Hex dump preps.  (The duplication detection is making ASSUMPTIONS about
     2213             * all the reads being a multiple of cchWidth, except for the final one.)
     2214             */
     2215            char           abHexBuf[16]   = { 0 };
     2216            size_t         cbHexBuf       = 0;
     2217            unsigned const cchWidth       = RT_ELEMENTS(abHexBuf);
     2218            uint64_t const offEndDupCheck = cb - cchWidth;
     2219            uint64_t       cDuplicates    = 0;
     2220
     2221            /*
     2222             * Do the reading.
     2223             */
     2224            while (cb > 0)
     2225            {
     2226                char szLine[32 + cchWidth * 4 + 32];
     2227
     2228                /* Do the reading. */
     2229                uint32_t const  cbToRead = (uint32_t)RT_MIN(cb, _128K);
     2230                SafeArray<BYTE> SafeArrayBuf;
     2231                HRESULT hrc = ptrMediumIO->Read(off, cbToRead, ComSafeArrayAsOutParam(SafeArrayBuf));
     2232                if (FAILED(hrc))
     2233                {
     2234                    RTStrPrintf(szLine, sizeof(szLine), "Read(%zu bytes at %#RX64)", cbToRead, off);
     2235                    com::GlueHandleComError(ptrMediumIO, szLine, hrc, __FILE__, __LINE__);
     2236                    break;
     2237                }
     2238
     2239                /* Output the data. */
     2240                size_t const cbReturned = SafeArrayBuf.size();
     2241                if (cbReturned)
     2242                {
     2243                    BYTE const *pbBuf = SafeArrayBuf.raw();
     2244                    int vrc;
     2245                    if (!fHex)
     2246                        vrc = RTStrmWrite(pOut, pbBuf, cbReturned);
     2247                    else
     2248                    {
     2249                        /* hexdump -C */
     2250                        uint64_t        offHex    = off;
     2251                        uint64_t const  offHexEnd = off + cb;
     2252                        while (offHex < offHexEnd)
     2253                        {
     2254                            if (   offHex >= offEndDupCheck
     2255                                || cbHexBuf == 0
     2256                                || memcmp(pbBuf, abHexBuf, cchWidth) != 0
     2257                                || (   cDuplicates == 0
     2258                                    && (   offHex + cchWidth >= offEndDupCheck
     2259                                        || memcmp(pbBuf + cchWidth, pbBuf, cchWidth) != 0)) )
     2260                            {
     2261                                if (cDuplicates > 0)
     2262                                {
     2263                                    RTStrmPrintf(pOut, "**********  <ditto x %RU64>\n", cDuplicates);
     2264                                    cDuplicates = 0;
     2265                                }
     2266
     2267                                size_t   cch = RTStrPrintf(szLine, sizeof(szLine), "%012RX64:", offHex);
     2268                                unsigned i;
     2269                                for (i = 0; i < cchWidth && offHex + i < offHexEnd; i++)
     2270                                {
     2271                                    static const char s_szHexDigits[17] = "0123456789abcdef";
     2272                                    szLine[cch++] = (i & 7) || i == 0 ? ' ' : '-';
     2273                                    uint8_t const u8 = pbBuf[i];
     2274                                    szLine[cch++] = s_szHexDigits[u8 >> 4];
     2275                                    szLine[cch++] = s_szHexDigits[u8 & 0xf];
     2276                                }
     2277                                while (i++ < cchWidth)
     2278                                {
     2279                                    szLine[cch++] = ' ';
     2280                                    szLine[cch++] = ' ';
     2281                                    szLine[cch++] = ' ';
     2282                                }
     2283                                szLine[cch++] = ' ';
     2284
     2285                                for (i = 0; i < cchWidth && offHex + i < offHexEnd; i++)
     2286                                {
     2287                                    uint8_t const u8 = pbBuf[i];
     2288                                    szLine[cch++] = u8 < 127 && u8 >= 32 ? u8 : '.';
     2289                                }
     2290                                szLine[cch++] = '\n';
     2291                                szLine[cch]   = '\0';
     2292
     2293                                vrc = RTStrmWrite(pOut, szLine, cch);
     2294                                if (RT_FAILURE(vrc))
     2295                                    break;
     2296
     2297
     2298                                /* copy bytes over to the duplication detection buffer. */
     2299                                cbHexBuf = (size_t)RT_MIN(cchWidth, offHexEnd - offHex);
     2300                                memcpy(abHexBuf, pbBuf, cbHexBuf);
     2301                            }
     2302                            else
     2303                                cDuplicates++;
     2304
     2305                            /* Advance to next line. */
     2306                            pbBuf  += cchWidth;
     2307                            offHex += cchWidth;
     2308                        }
     2309                    }
     2310                    if (RT_FAILURE(vrc))
     2311                    {
     2312                        rcExit = RTMsgErrorExitFailure("Error writing to '%s': %Rrc", pszOutput, vrc);
     2313                        break;
     2314                    }
     2315                }
     2316
     2317                /* Advance. */
     2318                if (cbReturned != cbToRead)
     2319                {
     2320                    rcExit = RTMsgErrorExitFailure("Expected read() at offset %RU64 (%#RX64) to return %#zx bytes, only got %#zx!\n",
     2321                                                   off, off, cbReturned, cbToRead);
     2322                    break;
     2323                }
     2324                off += cbReturned;
     2325                cb  -= cbReturned;
     2326            }
     2327
     2328            /*
     2329             * Close output.
     2330             */
     2331            if (pOut != g_pStdOut)
     2332            {
     2333                int vrc = RTStrmClose(pOut);
     2334                if (RT_FAILURE(vrc))
     2335                    rcExit = RTMsgErrorExitFailure("Error closing '%s': %Rrc", pszOutput, vrc);
     2336            }
     2337            else if (!fHex)
     2338                RTStrmSetMode(pOut, false, -1);
     2339        }
     2340    }
     2341    return rcExit;
     2342}
     2343
     2344
     2345RTEXITCODE handleMediumIO(HandlerArg *a)
     2346{
     2347    /*
     2348     * Parse image-option and sub-command.
     2349     */
     2350    static const RTGETOPTDEF s_aOptions[] =
     2351    {
     2352        MEDIUMIOCOMMONOPT_DEFS(),
     2353        /* sub-commands */
     2354        { "formatfat",  1000, RTGETOPT_REQ_NOTHING },
     2355        { "cat",        1001, RTGETOPT_REQ_NOTHING },
     2356    };
     2357    MEDIUMIOCOMMONOPT   CommonOpts = { NULL, DeviceType_Null, NULL };
     2358
     2359    RTGETOPTSTATE       GetState;
     2360    int rc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
     2361    AssertRC(rc);
     2362    RTGETOPTUNION       ValueUnion;
     2363    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
     2364    {
     2365        switch (rc)
     2366        {
     2367            MEDIUMIOCOMMONOPT_CASES(&CommonOpts);
     2368
     2369            /* Sub-commands: */
     2370            case 1000:
     2371                setCurrentSubcommand(HELP_SCOPE_MEDIUMIO_FORMATFAT);
     2372                return handleMediumIOFormatFat(a, GetState.iNext, &CommonOpts);
     2373            case 1001:
     2374                setCurrentSubcommand(HELP_SCOPE_MEDIUMIO_CAT);
     2375                return handleMediumIOCat(a, GetState.iNext, &CommonOpts);
     2376
     2377            case VINF_GETOPT_NOT_OPTION:
     2378                return errorUnknownSubcommand(ValueUnion.psz);
     2379
     2380            default:
     2381                return errorGetOpt(rc, &ValueUnion);
     2382        }
     2383    }
     2384    return errorNoSubcommand();
     2385}
     2386
    19442387#endif /* !VBOX_ONLY_DOCS */
Note: See TracChangeset for help on using the changeset viewer.

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