Changeset 72949 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Jul 7, 2018 4:22:45 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 123501
- Location:
- trunk/src/VBox/Frontends/VBoxManage
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r70582 r72949 123 123 { "startvm", USAGE_STARTVM, VBMG_CMD_TODO, handleStartVM, 0 }, 124 124 { "controlvm", USAGE_CONTROLVM, VBMG_CMD_TODO, handleControlVM, 0 }, 125 { "unattended", USAGE_UNATTENDED INSTALL, HELP_CMD_UNATTENDED, handleUnattended, 0 },125 { "unattended", USAGE_UNATTENDED, HELP_CMD_UNATTENDED, handleUnattended, 0 }, 126 126 { "discardstate", USAGE_DISCARDSTATE, VBMG_CMD_TODO, handleDiscardState, 0 }, 127 127 { "adoptstate", USAGE_ADOPTSTATE, VBMG_CMD_TODO, handleAdoptState, 0 }, … … 133 133 { "showhdinfo", USAGE_SHOWMEDIUMINFO, VBMG_CMD_TODO, handleShowMediumInfo, 0 }, /* backward compatibility */ 134 134 { "showvdiinfo", USAGE_SHOWMEDIUMINFO, VBMG_CMD_TODO, handleShowMediumInfo, 0 }, /* backward compatibility */ 135 { "mediumio", USAGE_MEDIUMIO, HELP_CMD_MEDIUMIO, handleMediumIO, 0 }, 135 136 { "getextradata", USAGE_GETEXTRADATA, VBMG_CMD_TODO, handleGetExtraData, 0 }, 136 137 { "setextradata", USAGE_SETEXTRADATA, VBMG_CMD_TODO, handleSetExtraData, 0 }, -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
r70582 r72949 75 75 #define USAGE_SHAREDFOLDER_ADD RT_BIT_64(25) 76 76 #define USAGE_SHAREDFOLDER_REMOVE RT_BIT_64(26) 77 #define USAGE_UNATTENDED RT_BIT_64(27) 78 #define USAGE_MEDIUMIO RT_BIT_64(28) 77 79 #define USAGE_LOADSYMS RT_BIT_64(29) 78 80 #define USAGE_LOADMAP RT_BIT_64(30) … … 135 137 #endif 136 138 137 #define USAGE_UNATTENDEDINSTALL RT_BIT(27)138 139 139 140 typedef uint64_t USAGECATEGORY; … … 298 299 RTEXITCODE handleShowMediumInfo(HandlerArg *a); 299 300 RTEXITCODE handleCloseMedium(HandlerArg *a); 301 RTEXITCODE handleMediumIO(HandlerArg *a); 300 302 int parseMediumType(const char *psz, MediumType_T *penmMediumType); 301 303 int parseBool(const char *psz, bool *pb); -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
r72883 r72949 41 41 #include "VBoxManage.h" 42 42 using namespace com; 43 44 /** Medium category. */ 45 typedef enum MEDIUMCATEGORY 46 { 47 MEDIUMCATEGORY_NONE = 0, 48 MEDIUMCATEGORY_DISK, 49 MEDIUMCATEGORY_DVD, 50 MEDIUMCATEGORY_FLOPPY 51 } MEDIUMCATEGORY; 52 43 53 44 54 … … 1942 1952 } 1943 1953 1954 1955 /********************************************************************************************************************************* 1956 * The mediumio command * 1957 *********************************************************************************************************************************/ 1958 1959 /** 1960 * Common MediumIO options. 1961 */ 1962 typedef struct MEDIUMIOCOMMONOPT 1963 { 1964 const char *pszFilenameOrUuid; 1965 DeviceType_T enmDeviceType; 1966 const char *pszPasswordFile; 1967 } MEDIUMIOCOMMONOPT; 1968 typedef MEDIUMIOCOMMONOPT *PMEDIUMIOCOMMONOPT; 1969 typedef 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 */ 2016 static 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 */ 2078 static 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 */ 2123 static 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 2345 RTEXITCODE 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 1944 2387 #endif /* !VBOX_ONLY_DOCS */
Note:
See TracChangeset
for help on using the changeset viewer.