VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp@ 54854

Last change on this file since 54854 was 54854, checked in by vboxsync, 10 years ago

Main: Rearrange and rename parameters of IMedium::ChangeEncryption

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.5 KB
Line 
1/* $Id: VBoxManageDisk.cpp 54854 2015-03-19 19:45:09Z vboxsync $ */
2/** @file
3 * VBoxManage - The disk/medium related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_ONLY_DOCS
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <VBox/com/com.h>
24#include <VBox/com/array.h>
25#include <VBox/com/ErrorInfo.h>
26#include <VBox/com/errorprint.h>
27#include <VBox/com/VirtualBox.h>
28
29#include <iprt/asm.h>
30#include <iprt/file.h>
31#include <iprt/path.h>
32#include <iprt/param.h>
33#include <iprt/stream.h>
34#include <iprt/string.h>
35#include <iprt/ctype.h>
36#include <iprt/getopt.h>
37#include <VBox/log.h>
38#include <VBox/vd.h>
39
40#include "VBoxManage.h"
41using namespace com;
42
43
44// funcs
45///////////////////////////////////////////////////////////////////////////////
46
47
48static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
49{
50 RTMsgErrorV(pszFormat, va);
51 RTMsgError("Error code %Rrc at %s(%u) in function %s", rc, RT_SRC_POS_ARGS);
52}
53
54static int getPassword(const char *pszPrompt, Utf8Str *pPassword)
55{
56 char aszPwdInput[_1K] = { 0 };
57
58 int vrc = RTStrmPutStr(g_pStdOut, pszPrompt);
59 if (RT_SUCCESS(vrc))
60 {
61 bool fEchoOld = false;
62 vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
63 if (RT_SUCCESS(vrc))
64 {
65 vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
66 if (RT_SUCCESS(vrc))
67 {
68 vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
69 if (RT_SUCCESS(vrc))
70 *pPassword = aszPwdInput;
71
72 int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
73 AssertRC(vrc2);
74 }
75 }
76 RTStrmPutStr(g_pStdOut, "\n");
77 }
78
79 return vrc;
80}
81
82static int parseMediumVariant(const char *psz, MediumVariant_T *pMediumVariant)
83{
84 int rc = VINF_SUCCESS;
85 unsigned uMediumVariant = (unsigned)(*pMediumVariant);
86 while (psz && *psz && RT_SUCCESS(rc))
87 {
88 size_t len;
89 const char *pszComma = strchr(psz, ',');
90 if (pszComma)
91 len = pszComma - psz;
92 else
93 len = strlen(psz);
94 if (len > 0)
95 {
96 // Parsing is intentionally inconsistent: "standard" resets the
97 // variant, whereas the other flags are cumulative.
98 if (!RTStrNICmp(psz, "standard", len))
99 uMediumVariant = MediumVariant_Standard;
100 else if ( !RTStrNICmp(psz, "fixed", len)
101 || !RTStrNICmp(psz, "static", len))
102 uMediumVariant |= MediumVariant_Fixed;
103 else if (!RTStrNICmp(psz, "Diff", len))
104 uMediumVariant |= MediumVariant_Diff;
105 else if (!RTStrNICmp(psz, "split2g", len))
106 uMediumVariant |= MediumVariant_VmdkSplit2G;
107 else if ( !RTStrNICmp(psz, "stream", len)
108 || !RTStrNICmp(psz, "streamoptimized", len))
109 uMediumVariant |= MediumVariant_VmdkStreamOptimized;
110 else if (!RTStrNICmp(psz, "esx", len))
111 uMediumVariant |= MediumVariant_VmdkESX;
112 else
113 rc = VERR_PARSE_ERROR;
114 }
115 if (pszComma)
116 psz += len + 1;
117 else
118 psz += len;
119 }
120
121 if (RT_SUCCESS(rc))
122 *pMediumVariant = (MediumVariant_T)uMediumVariant;
123 return rc;
124}
125
126int parseMediumType(const char *psz, MediumType_T *penmMediumType)
127{
128 int rc = VINF_SUCCESS;
129 MediumType_T enmMediumType = MediumType_Normal;
130 if (!RTStrICmp(psz, "normal"))
131 enmMediumType = MediumType_Normal;
132 else if (!RTStrICmp(psz, "immutable"))
133 enmMediumType = MediumType_Immutable;
134 else if (!RTStrICmp(psz, "writethrough"))
135 enmMediumType = MediumType_Writethrough;
136 else if (!RTStrICmp(psz, "shareable"))
137 enmMediumType = MediumType_Shareable;
138 else if (!RTStrICmp(psz, "readonly"))
139 enmMediumType = MediumType_Readonly;
140 else if (!RTStrICmp(psz, "multiattach"))
141 enmMediumType = MediumType_MultiAttach;
142 else
143 rc = VERR_PARSE_ERROR;
144
145 if (RT_SUCCESS(rc))
146 *penmMediumType = enmMediumType;
147 return rc;
148}
149
150/** @todo move this into getopt, as getting bool values is generic */
151int parseBool(const char *psz, bool *pb)
152{
153 int rc = VINF_SUCCESS;
154 if ( !RTStrICmp(psz, "on")
155 || !RTStrICmp(psz, "yes")
156 || !RTStrICmp(psz, "true")
157 || !RTStrICmp(psz, "1")
158 || !RTStrICmp(psz, "enable")
159 || !RTStrICmp(psz, "enabled"))
160 {
161 *pb = true;
162 }
163 else if ( !RTStrICmp(psz, "off")
164 || !RTStrICmp(psz, "no")
165 || !RTStrICmp(psz, "false")
166 || !RTStrICmp(psz, "0")
167 || !RTStrICmp(psz, "disable")
168 || !RTStrICmp(psz, "disabled"))
169 {
170 *pb = false;
171 }
172 else
173 rc = VERR_PARSE_ERROR;
174
175 return rc;
176}
177
178HRESULT openMedium(HandlerArg *a, const char *pszFilenameOrUuid,
179 DeviceType_T enmDevType, AccessMode_T enmAccessMode,
180 ComPtr<IMedium> &pMedium, bool fForceNewUuidOnOpen,
181 bool fSilent)
182{
183 HRESULT rc;
184 Guid id(pszFilenameOrUuid);
185 char szFilenameAbs[RTPATH_MAX] = "";
186
187 /* If it is no UUID, convert the filename to an absolute one. */
188 if (!id.isValid())
189 {
190 int irc = RTPathAbs(pszFilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
191 if (RT_FAILURE(irc))
192 {
193 if (!fSilent)
194 RTMsgError("Cannot convert filename \"%s\" to absolute path", pszFilenameOrUuid);
195 return E_FAIL;
196 }
197 pszFilenameOrUuid = szFilenameAbs;
198 }
199
200 if (!fSilent)
201 CHECK_ERROR(a->virtualBox, OpenMedium(Bstr(pszFilenameOrUuid).raw(),
202 enmDevType,
203 enmAccessMode,
204 fForceNewUuidOnOpen,
205 pMedium.asOutParam()));
206 else
207 rc = a->virtualBox->OpenMedium(Bstr(pszFilenameOrUuid).raw(),
208 enmDevType,
209 enmAccessMode,
210 fForceNewUuidOnOpen,
211 pMedium.asOutParam());
212
213 return rc;
214}
215
216static HRESULT createMedium(HandlerArg *a, const char *pszFormat,
217 const char *pszFilename, DeviceType_T enmDevType,
218 AccessMode_T enmAccessMode, ComPtr<IMedium> &pMedium)
219{
220 HRESULT rc;
221 char szFilenameAbs[RTPATH_MAX] = "";
222
223 /** @todo laziness shortcut. should really check the MediumFormatCapabilities */
224 if (RTStrICmp(pszFormat, "iSCSI"))
225 {
226 int irc = RTPathAbs(pszFilename, szFilenameAbs, sizeof(szFilenameAbs));
227 if (RT_FAILURE(irc))
228 {
229 RTMsgError("Cannot convert filename \"%s\" to absolute path", pszFilename);
230 return E_FAIL;
231 }
232 pszFilename = szFilenameAbs;
233 }
234
235 CHECK_ERROR(a->virtualBox, CreateMedium(Bstr(pszFormat).raw(),
236 Bstr(pszFilename).raw(),
237 enmAccessMode,
238 enmDevType,
239 pMedium.asOutParam()));
240 return rc;
241}
242
243static const RTGETOPTDEF g_aCreateMediumOptions[] =
244{
245 { "disk", 'H', RTGETOPT_REQ_NOTHING },
246 { "dvd", 'D', RTGETOPT_REQ_NOTHING },
247 { "floppy", 'L', RTGETOPT_REQ_NOTHING },
248 { "--filename", 'f', RTGETOPT_REQ_STRING },
249 { "-filename", 'f', RTGETOPT_REQ_STRING }, // deprecated
250 { "--diffparent", 'd', RTGETOPT_REQ_STRING },
251 { "--size", 's', RTGETOPT_REQ_UINT64 },
252 { "-size", 's', RTGETOPT_REQ_UINT64 }, // deprecated
253 { "--sizebyte", 'S', RTGETOPT_REQ_UINT64 },
254 { "--format", 'o', RTGETOPT_REQ_STRING },
255 { "-format", 'o', RTGETOPT_REQ_STRING }, // deprecated
256 { "--static", 'F', RTGETOPT_REQ_NOTHING },
257 { "-static", 'F', RTGETOPT_REQ_NOTHING }, // deprecated
258 { "--variant", 'm', RTGETOPT_REQ_STRING },
259 { "-variant", 'm', RTGETOPT_REQ_STRING }, // deprecated
260};
261
262int handleCreateMedium(HandlerArg *a)
263{
264 HRESULT rc;
265 int vrc;
266 const char *filename = NULL;
267 const char *diffparent = NULL;
268 uint64_t size = 0;
269 enum {
270 CMD_NONE,
271 CMD_DISK,
272 CMD_DVD,
273 CMD_FLOPPY
274 } cmd = CMD_NONE;
275 const char *format = NULL;
276 bool fBase = true;
277 MediumVariant_T enmMediumVariant = MediumVariant_Standard;
278
279 int c;
280 RTGETOPTUNION ValueUnion;
281 RTGETOPTSTATE GetState;
282 // start at 0 because main() has hacked both the argc and argv given to us
283 RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateMediumOptions, RT_ELEMENTS(g_aCreateMediumOptions),
284 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
285 while ((c = RTGetOpt(&GetState, &ValueUnion)))
286 {
287 switch (c)
288 {
289 case 'H': // disk
290 if (cmd != CMD_NONE)
291 return errorSyntax(USAGE_CREATEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
292 cmd = CMD_DISK;
293 break;
294
295 case 'D': // DVD
296 if (cmd != CMD_NONE)
297 return errorSyntax(USAGE_CREATEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
298 cmd = CMD_DVD;
299 break;
300
301 case 'L': // floppy
302 if (cmd != CMD_NONE)
303 return errorSyntax(USAGE_CREATEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
304 cmd = CMD_FLOPPY;
305 break;
306
307 case 'f': // --filename
308 filename = ValueUnion.psz;
309 break;
310
311 case 'd': // --diffparent
312 diffparent = ValueUnion.psz;
313 fBase = false;
314 break;
315
316 case 's': // --size
317 size = ValueUnion.u64 * _1M;
318 break;
319
320 case 'S': // --sizebyte
321 size = ValueUnion.u64;
322 break;
323
324 case 'o': // --format
325 format = ValueUnion.psz;
326 break;
327
328 case 'F': // --static ("fixed"/"flat")
329 {
330 unsigned uMediumVariant = (unsigned)enmMediumVariant;
331 uMediumVariant |= MediumVariant_Fixed;
332 enmMediumVariant = (MediumVariant_T)uMediumVariant;
333 break;
334 }
335
336 case 'm': // --variant
337 vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant);
338 if (RT_FAILURE(vrc))
339 return errorArgument("Invalid medium variant '%s'", ValueUnion.psz);
340 break;
341
342 case VINF_GETOPT_NOT_OPTION:
343 return errorSyntax(USAGE_CREATEMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
344
345 default:
346 if (c > 0)
347 {
348 if (RT_C_IS_PRINT(c))
349 return errorSyntax(USAGE_CREATEMEDIUM, "Invalid option -%c", c);
350 else
351 return errorSyntax(USAGE_CREATEMEDIUM, "Invalid option case %i", c);
352 }
353 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
354 return errorSyntax(USAGE_CREATEMEDIUM, "unknown option: %s\n", ValueUnion.psz);
355 else if (ValueUnion.pDef)
356 return errorSyntax(USAGE_CREATEMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
357 else
358 return errorSyntax(USAGE_CREATEMEDIUM, "error: %Rrs", c);
359 }
360 }
361
362 /* check the outcome */
363 if (cmd == CMD_NONE)
364 cmd = CMD_DISK;
365 ComPtr<IMedium> pParentMedium;
366 if (fBase)
367 {
368 if ( !filename
369 || !*filename
370 || size == 0)
371 return errorSyntax(USAGE_CREATEMEDIUM, "Parameters --filename and --size are required");
372 if (!format || !*format)
373 {
374 if (cmd == CMD_DISK)
375 format = "VDI";
376 else if (cmd == CMD_DVD || cmd == CMD_FLOPPY)
377 {
378 format = "RAW";
379 unsigned uMediumVariant = (unsigned)enmMediumVariant;
380 uMediumVariant |= MediumVariant_Fixed;
381 enmMediumVariant = (MediumVariant_T)uMediumVariant;
382 }
383 }
384 }
385 else
386 {
387 if ( !filename
388 || !*filename)
389 return errorSyntax(USAGE_CREATEMEDIUM, "Parameters --filename is required");
390 size = 0;
391 if (cmd != CMD_DISK)
392 return errorSyntax(USAGE_CREATEMEDIUM, "Creating a differencing medium is only supported for hard disks");
393 enmMediumVariant = MediumVariant_Diff;
394 if (!format || !*format)
395 {
396 const char *pszExt = RTPathSuffix(filename);
397 /* Skip over . if there is an extension. */
398 if (pszExt)
399 pszExt++;
400 if (!pszExt || !*pszExt)
401 format = "VDI";
402 else
403 format = pszExt;
404 }
405 rc = openMedium(a, diffparent, DeviceType_HardDisk,
406 AccessMode_ReadWrite, pParentMedium,
407 false /* fForceNewUuidOnOpen */, false /* fSilent */);
408 if (FAILED(rc))
409 return 1;
410 if (pParentMedium.isNull())
411 {
412 RTMsgError("Invalid parent hard disk reference, avoiding crash");
413 return 1;
414 }
415 MediumState_T state;
416 CHECK_ERROR(pParentMedium, COMGETTER(State)(&state));
417 if (FAILED(rc))
418 return 1;
419 if (state == MediumState_Inaccessible)
420 {
421 CHECK_ERROR(pParentMedium, RefreshState(&state));
422 if (FAILED(rc))
423 return 1;
424 }
425 }
426 /* check for filename extension */
427 /** @todo use IMediumFormat to cover all extensions generically */
428 Utf8Str strName(filename);
429 if (!RTPathHasSuffix(strName.c_str()))
430 {
431 Utf8Str strFormat(format);
432 if (cmd == CMD_DISK)
433 {
434 if (strFormat.compare("vmdk", RTCString::CaseInsensitive) == 0)
435 strName.append(".vmdk");
436 else if (strFormat.compare("vhd", RTCString::CaseInsensitive) == 0)
437 strName.append(".vhd");
438 else
439 strName.append(".vdi");
440 } else if (cmd == CMD_DVD)
441 strName.append(".iso");
442 else if (cmd == CMD_FLOPPY)
443 strName.append(".img");
444 filename = strName.c_str();
445 }
446
447 ComPtr<IMedium> pMedium;
448 if (cmd == CMD_DISK)
449 rc = createMedium(a, format, filename, DeviceType_HardDisk,
450 AccessMode_ReadWrite, pMedium);
451 else if (cmd == CMD_DVD)
452 rc = createMedium(a, format, filename, DeviceType_DVD,
453 AccessMode_ReadOnly, pMedium);
454 else if (cmd == CMD_FLOPPY)
455 rc = createMedium(a, format, filename, DeviceType_Floppy,
456 AccessMode_ReadWrite, pMedium);
457 else
458 rc = E_INVALIDARG; /* cannot happen but make gcc happy */
459
460 if (SUCCEEDED(rc) && pMedium)
461 {
462 ComPtr<IProgress> pProgress;
463 com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8);
464
465 for (ULONG i = 0; i < l_variants.size(); ++i)
466 {
467 ULONG temp = enmMediumVariant;
468 temp &= 1<<i;
469 l_variants [i] = (MediumVariant_T)temp;
470 }
471
472 if (fBase)
473 CHECK_ERROR(pMedium, CreateBaseStorage(size, ComSafeArrayAsInParam(l_variants), pProgress.asOutParam()));
474 else
475 CHECK_ERROR(pParentMedium, CreateDiffStorage(pMedium, ComSafeArrayAsInParam(l_variants), pProgress.asOutParam()));
476 if (SUCCEEDED(rc) && pProgress)
477 {
478 rc = showProgress(pProgress);
479 CHECK_PROGRESS_ERROR(pProgress, ("Failed to create medium"));
480 }
481 }
482
483 if (SUCCEEDED(rc) && pMedium)
484 {
485 Bstr uuid;
486 CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam()));
487 RTPrintf("Medium created. UUID: %s\n", Utf8Str(uuid).c_str());
488
489 //CHECK_ERROR(pMedium, Close());
490 }
491 return SUCCEEDED(rc) ? 0 : 1;
492}
493
494static const RTGETOPTDEF g_aModifyMediumOptions[] =
495{
496 { "disk", 'H', RTGETOPT_REQ_NOTHING },
497 { "dvd", 'D', RTGETOPT_REQ_NOTHING },
498 { "floppy", 'L', RTGETOPT_REQ_NOTHING },
499 { "--type", 't', RTGETOPT_REQ_STRING },
500 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
501 { "settype", 't', RTGETOPT_REQ_STRING }, // deprecated
502 { "--autoreset", 'z', RTGETOPT_REQ_STRING },
503 { "-autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated
504 { "autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated
505 { "--property", 'p', RTGETOPT_REQ_STRING },
506 { "--compact", 'c', RTGETOPT_REQ_NOTHING },
507 { "-compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated
508 { "compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated
509 { "--resize", 'r', RTGETOPT_REQ_UINT64 },
510 { "--resizebyte", 'R', RTGETOPT_REQ_UINT64 }
511};
512
513int handleModifyMedium(HandlerArg *a)
514{
515 HRESULT rc;
516 int vrc;
517 enum {
518 CMD_NONE,
519 CMD_DISK,
520 CMD_DVD,
521 CMD_FLOPPY
522 } cmd = CMD_NONE;
523 ComPtr<IMedium> pMedium;
524 MediumType_T enmMediumType;
525 bool AutoReset = false;
526 SafeArray<BSTR> mediumPropNames;
527 SafeArray<BSTR> mediumPropValues;
528 bool fModifyMediumType = false;
529 bool fModifyAutoReset = false;
530 bool fModifyProperties = false;
531 bool fModifyCompact = false;
532 bool fModifyResize = false;
533 uint64_t cbResize = 0;
534 const char *pszFilenameOrUuid = NULL;
535
536 int c;
537 RTGETOPTUNION ValueUnion;
538 RTGETOPTSTATE GetState;
539 // start at 0 because main() has hacked both the argc and argv given to us
540 RTGetOptInit(&GetState, a->argc, a->argv, g_aModifyMediumOptions, RT_ELEMENTS(g_aModifyMediumOptions),
541 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
542 while ((c = RTGetOpt(&GetState, &ValueUnion)))
543 {
544 switch (c)
545 {
546 case 'H': // disk
547 if (cmd != CMD_NONE)
548 return errorSyntax(USAGE_MODIFYMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
549 cmd = CMD_DISK;
550 break;
551
552 case 'D': // DVD
553 if (cmd != CMD_NONE)
554 return errorSyntax(USAGE_MODIFYMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
555 cmd = CMD_DVD;
556 break;
557
558 case 'L': // floppy
559 if (cmd != CMD_NONE)
560 return errorSyntax(USAGE_MODIFYMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
561 cmd = CMD_FLOPPY;
562 break;
563
564 case 't': // --type
565 vrc = parseMediumType(ValueUnion.psz, &enmMediumType);
566 if (RT_FAILURE(vrc))
567 return errorArgument("Invalid medium type '%s'", ValueUnion.psz);
568 fModifyMediumType = true;
569 break;
570
571 case 'z': // --autoreset
572 vrc = parseBool(ValueUnion.psz, &AutoReset);
573 if (RT_FAILURE(vrc))
574 return errorArgument("Invalid autoreset parameter '%s'", ValueUnion.psz);
575 fModifyAutoReset = true;
576 break;
577
578 case 'p': // --property
579 {
580 /* Parse 'name=value' */
581 char *pszProperty = RTStrDup(ValueUnion.psz);
582 if (pszProperty)
583 {
584 char *pDelimiter = strchr(pszProperty, '=');
585 if (pDelimiter)
586 {
587 *pDelimiter = '\0';
588
589 Bstr bstrName(pszProperty);
590 Bstr bstrValue(&pDelimiter[1]);
591 bstrName.detachTo(mediumPropNames.appendedRaw());
592 bstrValue.detachTo(mediumPropValues.appendedRaw());
593 fModifyProperties = true;
594 }
595 else
596 {
597 errorArgument("Invalid --property argument '%s'", ValueUnion.psz);
598 rc = E_FAIL;
599 }
600 RTStrFree(pszProperty);
601 }
602 else
603 {
604 RTStrmPrintf(g_pStdErr, "Error: Failed to allocate memory for medium property '%s'\n", ValueUnion.psz);
605 rc = E_FAIL;
606 }
607 break;
608 }
609
610 case 'c': // --compact
611 fModifyCompact = true;
612 break;
613
614 case 'r': // --resize
615 cbResize = ValueUnion.u64 * _1M;
616 fModifyResize = true;
617 break;
618
619 case 'R': // --resizebyte
620 cbResize = ValueUnion.u64;
621 fModifyResize = true;
622 break;
623
624 case VINF_GETOPT_NOT_OPTION:
625 if (!pszFilenameOrUuid)
626 pszFilenameOrUuid = ValueUnion.psz;
627 else
628 return errorSyntax(USAGE_MODIFYMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
629 break;
630
631 default:
632 if (c > 0)
633 {
634 if (RT_C_IS_PRINT(c))
635 return errorSyntax(USAGE_MODIFYMEDIUM, "Invalid option -%c", c);
636 else
637 return errorSyntax(USAGE_MODIFYMEDIUM, "Invalid option case %i", c);
638 }
639 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
640 return errorSyntax(USAGE_MODIFYMEDIUM, "unknown option: %s\n", ValueUnion.psz);
641 else if (ValueUnion.pDef)
642 return errorSyntax(USAGE_MODIFYMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
643 else
644 return errorSyntax(USAGE_MODIFYMEDIUM, "error: %Rrs", c);
645 }
646 }
647
648 if (cmd == CMD_NONE)
649 cmd = CMD_DISK;
650
651 if (!pszFilenameOrUuid)
652 return errorSyntax(USAGE_MODIFYMEDIUM, "Medium name or UUID required");
653
654 if (!fModifyMediumType && !fModifyAutoReset && !fModifyProperties && !fModifyCompact && !fModifyResize)
655 return errorSyntax(USAGE_MODIFYMEDIUM, "No operation specified");
656
657 /* Always open the medium if necessary, there is no other way. */
658 if (cmd == CMD_DISK)
659 rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
660 AccessMode_ReadWrite, pMedium,
661 false /* fForceNewUuidOnOpen */, false /* fSilent */);
662 else if (cmd == CMD_DVD)
663 rc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD,
664 AccessMode_ReadOnly, pMedium,
665 false /* fForceNewUuidOnOpen */, false /* fSilent */);
666 else if (cmd == CMD_FLOPPY)
667 rc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy,
668 AccessMode_ReadWrite, pMedium,
669 false /* fForceNewUuidOnOpen */, false /* fSilent */);
670 else
671 rc = E_INVALIDARG; /* cannot happen but make gcc happy */
672 if (FAILED(rc))
673 return 1;
674 if (pMedium.isNull())
675 {
676 RTMsgError("Invalid medium reference, avoiding crash");
677 return 1;
678 }
679
680 if (fModifyMediumType)
681 {
682 MediumType_T enmCurrMediumType;
683 CHECK_ERROR(pMedium, COMGETTER(Type)(&enmCurrMediumType));
684
685 if (enmCurrMediumType != enmMediumType)
686 CHECK_ERROR(pMedium, COMSETTER(Type)(enmMediumType));
687 }
688
689 if (fModifyAutoReset)
690 {
691 CHECK_ERROR(pMedium, COMSETTER(AutoReset)(AutoReset));
692 }
693
694 if (fModifyProperties)
695 {
696 CHECK_ERROR(pMedium, SetProperties(ComSafeArrayAsInParam(mediumPropNames), ComSafeArrayAsInParam(mediumPropValues)));
697 }
698
699 if (fModifyCompact)
700 {
701 ComPtr<IProgress> pProgress;
702 CHECK_ERROR(pMedium, Compact(pProgress.asOutParam()));
703 if (SUCCEEDED(rc))
704 rc = showProgress(pProgress);
705 if (FAILED(rc))
706 {
707 if (rc == E_NOTIMPL)
708 RTMsgError("Compact medium operation is not implemented!");
709 else if (rc == VBOX_E_NOT_SUPPORTED)
710 RTMsgError("Compact medium operation for this format is not implemented yet!");
711 else if (!pProgress.isNull())
712 CHECK_PROGRESS_ERROR(pProgress, ("Failed to compact medium"));
713 else
714 RTMsgError("Failed to compact medium!");
715 }
716 }
717
718 if (fModifyResize)
719 {
720 ComPtr<IProgress> pProgress;
721 CHECK_ERROR(pMedium, Resize(cbResize, pProgress.asOutParam()));
722 if (SUCCEEDED(rc))
723 rc = showProgress(pProgress);
724 if (FAILED(rc))
725 {
726 if (rc == E_NOTIMPL)
727 RTMsgError("Resize medium operation is not implemented!");
728 else if (rc == VBOX_E_NOT_SUPPORTED)
729 RTMsgError("Resize medium operation for this format is not implemented yet!");
730 else
731 CHECK_PROGRESS_ERROR(pProgress, ("Failed to resize medium"));
732 }
733 }
734
735 return SUCCEEDED(rc) ? 0 : 1;
736}
737
738static const RTGETOPTDEF g_aCloneMediumOptions[] =
739{
740 { "disk", 'd', RTGETOPT_REQ_NOTHING },
741 { "dvd", 'D', RTGETOPT_REQ_NOTHING },
742 { "floppy", 'f', RTGETOPT_REQ_NOTHING },
743 { "--format", 'o', RTGETOPT_REQ_STRING },
744 { "-format", 'o', RTGETOPT_REQ_STRING },
745 { "--static", 'F', RTGETOPT_REQ_NOTHING },
746 { "-static", 'F', RTGETOPT_REQ_NOTHING },
747 { "--existing", 'E', RTGETOPT_REQ_NOTHING },
748 { "--variant", 'm', RTGETOPT_REQ_STRING },
749 { "-variant", 'm', RTGETOPT_REQ_STRING },
750};
751
752int handleCloneMedium(HandlerArg *a)
753{
754 HRESULT rc;
755 int vrc;
756 enum {
757 CMD_NONE,
758 CMD_DISK,
759 CMD_DVD,
760 CMD_FLOPPY
761 } cmd = CMD_NONE;
762 const char *pszSrc = NULL;
763 const char *pszDst = NULL;
764 Bstr format;
765 MediumVariant_T enmMediumVariant = MediumVariant_Standard;
766 bool fExisting = false;
767
768 int c;
769 RTGETOPTUNION ValueUnion;
770 RTGETOPTSTATE GetState;
771 // start at 0 because main() has hacked both the argc and argv given to us
772 RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneMediumOptions, RT_ELEMENTS(g_aCloneMediumOptions),
773 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
774 while ((c = RTGetOpt(&GetState, &ValueUnion)))
775 {
776 switch (c)
777 {
778 case 'd': // disk
779 if (cmd != CMD_NONE)
780 return errorSyntax(USAGE_CLONEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
781 cmd = CMD_DISK;
782 break;
783
784 case 'D': // DVD
785 if (cmd != CMD_NONE)
786 return errorSyntax(USAGE_CLONEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
787 cmd = CMD_DVD;
788 break;
789
790 case 'f': // floppy
791 if (cmd != CMD_NONE)
792 return errorSyntax(USAGE_CLONEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
793 cmd = CMD_FLOPPY;
794 break;
795
796 case 'o': // --format
797 format = ValueUnion.psz;
798 break;
799
800 case 'F': // --static
801 {
802 unsigned uMediumVariant = (unsigned)enmMediumVariant;
803 uMediumVariant |= MediumVariant_Fixed;
804 enmMediumVariant = (MediumVariant_T)uMediumVariant;
805 break;
806 }
807
808 case 'E': // --existing
809 fExisting = true;
810 break;
811
812 case 'm': // --variant
813 vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant);
814 if (RT_FAILURE(vrc))
815 return errorArgument("Invalid medium variant '%s'", ValueUnion.psz);
816 break;
817
818 case VINF_GETOPT_NOT_OPTION:
819 if (!pszSrc)
820 pszSrc = ValueUnion.psz;
821 else if (!pszDst)
822 pszDst = ValueUnion.psz;
823 else
824 return errorSyntax(USAGE_CLONEMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
825 break;
826
827 default:
828 if (c > 0)
829 {
830 if (RT_C_IS_GRAPH(c))
831 return errorSyntax(USAGE_CLONEMEDIUM, "unhandled option: -%c", c);
832 else
833 return errorSyntax(USAGE_CLONEMEDIUM, "unhandled option: %i", c);
834 }
835 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
836 return errorSyntax(USAGE_CLONEMEDIUM, "unknown option: %s", ValueUnion.psz);
837 else if (ValueUnion.pDef)
838 return errorSyntax(USAGE_CLONEMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
839 else
840 return errorSyntax(USAGE_CLONEMEDIUM, "error: %Rrs", c);
841 }
842 }
843
844 if (cmd == CMD_NONE)
845 cmd = CMD_DISK;
846 if (!pszSrc)
847 return errorSyntax(USAGE_CLONEMEDIUM, "Mandatory UUID or input file parameter missing");
848 if (!pszDst)
849 return errorSyntax(USAGE_CLONEMEDIUM, "Mandatory output file parameter missing");
850 if (fExisting && (!format.isEmpty() || enmMediumVariant != MediumType_Normal))
851 return errorSyntax(USAGE_CLONEMEDIUM, "Specified options which cannot be used with --existing");
852
853 ComPtr<IMedium> pSrcMedium;
854 ComPtr<IMedium> pDstMedium;
855
856 if (cmd == CMD_DISK)
857 rc = openMedium(a, pszSrc, DeviceType_HardDisk, AccessMode_ReadOnly, pSrcMedium,
858 false /* fForceNewUuidOnOpen */, false /* fSilent */);
859 else if (cmd == CMD_DVD)
860 rc = openMedium(a, pszSrc, DeviceType_DVD, AccessMode_ReadOnly, pSrcMedium,
861 false /* fForceNewUuidOnOpen */, false /* fSilent */);
862 else if (cmd == CMD_FLOPPY)
863 rc = openMedium(a, pszSrc, DeviceType_Floppy, AccessMode_ReadOnly, pSrcMedium,
864 false /* fForceNewUuidOnOpen */, false /* fSilent */);
865 else
866 rc = E_INVALIDARG; /* cannot happen but make gcc happy */
867 if (FAILED(rc))
868 return 1;
869
870 do
871 {
872 /* open/create destination medium */
873 if (fExisting)
874 {
875 if (cmd == CMD_DISK)
876 rc = openMedium(a, pszDst, DeviceType_HardDisk, AccessMode_ReadWrite, pDstMedium,
877 false /* fForceNewUuidOnOpen */, false /* fSilent */);
878 else if (cmd == CMD_DVD)
879 rc = openMedium(a, pszDst, DeviceType_DVD, AccessMode_ReadOnly, pDstMedium,
880 false /* fForceNewUuidOnOpen */, false /* fSilent */);
881 else if (cmd == CMD_FLOPPY)
882 rc = openMedium(a, pszDst, DeviceType_Floppy, AccessMode_ReadWrite, pDstMedium,
883 false /* fForceNewUuidOnOpen */, false /* fSilent */);
884 if (FAILED(rc))
885 break;
886
887 /* Perform accessibility check now. */
888 MediumState_T state;
889 CHECK_ERROR_BREAK(pDstMedium, RefreshState(&state));
890 CHECK_ERROR_BREAK(pDstMedium, COMGETTER(Format)(format.asOutParam()));
891 }
892 else
893 {
894 /* use the format of the source medium if unspecified */
895 if (format.isEmpty())
896 CHECK_ERROR_BREAK(pSrcMedium, COMGETTER(Format)(format.asOutParam()));
897 Utf8Str strFormat(format);
898 if (cmd == CMD_DISK)
899 rc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_HardDisk,
900 AccessMode_ReadWrite, pDstMedium);
901 else if (cmd == CMD_DVD)
902 rc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_DVD,
903 AccessMode_ReadOnly, pDstMedium);
904 else if (cmd == CMD_FLOPPY)
905 rc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_Floppy,
906 AccessMode_ReadWrite, pDstMedium);
907 if (FAILED(rc))
908 break;
909 }
910
911 ComPtr<IProgress> pProgress;
912 com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8);
913
914 for (ULONG i = 0; i < l_variants.size(); ++i)
915 {
916 ULONG temp = enmMediumVariant;
917 temp &= 1<<i;
918 l_variants [i] = (MediumVariant_T)temp;
919 }
920
921 CHECK_ERROR_BREAK(pSrcMedium, CloneTo(pDstMedium, ComSafeArrayAsInParam(l_variants), NULL, pProgress.asOutParam()));
922
923 rc = showProgress(pProgress);
924 CHECK_PROGRESS_ERROR_BREAK(pProgress, ("Failed to clone medium"));
925
926 Bstr uuid;
927 CHECK_ERROR_BREAK(pDstMedium, COMGETTER(Id)(uuid.asOutParam()));
928
929 RTPrintf("Clone medium created in format '%ls'. UUID: %s\n",
930 format.raw(), Utf8Str(uuid).c_str());
931 }
932 while (0);
933
934 return SUCCEEDED(rc) ? 0 : 1;
935}
936
937static const RTGETOPTDEF g_aConvertFromRawHardDiskOptions[] =
938{
939 { "--format", 'o', RTGETOPT_REQ_STRING },
940 { "-format", 'o', RTGETOPT_REQ_STRING },
941 { "--static", 'F', RTGETOPT_REQ_NOTHING },
942 { "-static", 'F', RTGETOPT_REQ_NOTHING },
943 { "--variant", 'm', RTGETOPT_REQ_STRING },
944 { "-variant", 'm', RTGETOPT_REQ_STRING },
945 { "--uuid", 'u', RTGETOPT_REQ_STRING },
946};
947
948RTEXITCODE handleConvertFromRaw(int argc, char *argv[])
949{
950 int rc = VINF_SUCCESS;
951 bool fReadFromStdIn = false;
952 const char *format = "VDI";
953 const char *srcfilename = NULL;
954 const char *dstfilename = NULL;
955 const char *filesize = NULL;
956 unsigned uImageFlags = VD_IMAGE_FLAGS_NONE;
957 void *pvBuf = NULL;
958 RTUUID uuid;
959 PCRTUUID pUuid = NULL;
960
961 int c;
962 RTGETOPTUNION ValueUnion;
963 RTGETOPTSTATE GetState;
964 // start at 0 because main() has hacked both the argc and argv given to us
965 RTGetOptInit(&GetState, argc, argv, g_aConvertFromRawHardDiskOptions, RT_ELEMENTS(g_aConvertFromRawHardDiskOptions),
966 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
967 while ((c = RTGetOpt(&GetState, &ValueUnion)))
968 {
969 switch (c)
970 {
971 case 'u': // --uuid
972 if (RT_FAILURE(RTUuidFromStr(&uuid, ValueUnion.psz)))
973 return errorSyntax(USAGE_CONVERTFROMRAW, "Invalid UUID '%s'", ValueUnion.psz);
974 pUuid = &uuid;
975 break;
976 case 'o': // --format
977 format = ValueUnion.psz;
978 break;
979
980 case 'm': // --variant
981 {
982 MediumVariant_T enmMediumVariant = MediumVariant_Standard;
983 rc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant);
984 if (RT_FAILURE(rc))
985 return errorArgument("Invalid medium variant '%s'", ValueUnion.psz);
986 /// @todo cleaner solution than assuming 1:1 mapping?
987 uImageFlags = (unsigned)enmMediumVariant;
988 break;
989 }
990 case VINF_GETOPT_NOT_OPTION:
991 if (!srcfilename)
992 {
993 srcfilename = ValueUnion.psz;
994 fReadFromStdIn = !strcmp(srcfilename, "stdin");
995 }
996 else if (!dstfilename)
997 dstfilename = ValueUnion.psz;
998 else if (fReadFromStdIn && !filesize)
999 filesize = ValueUnion.psz;
1000 else
1001 return errorSyntax(USAGE_CONVERTFROMRAW, "Invalid parameter '%s'", ValueUnion.psz);
1002 break;
1003
1004 default:
1005 return errorGetOpt(USAGE_CONVERTFROMRAW, c, &ValueUnion);
1006 }
1007 }
1008
1009 if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize))
1010 return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
1011 RTStrmPrintf(g_pStdErr, "Converting from raw image file=\"%s\" to file=\"%s\"...\n",
1012 srcfilename, dstfilename);
1013
1014 PVBOXHDD pDisk = NULL;
1015
1016 PVDINTERFACE pVDIfs = NULL;
1017 VDINTERFACEERROR vdInterfaceError;
1018 vdInterfaceError.pfnError = handleVDError;
1019 vdInterfaceError.pfnMessage = NULL;
1020
1021 rc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
1022 NULL, sizeof(VDINTERFACEERROR), &pVDIfs);
1023 AssertRC(rc);
1024
1025 /* open raw image file. */
1026 RTFILE File;
1027 if (fReadFromStdIn)
1028 rc = RTFileFromNative(&File, RTFILE_NATIVE_STDIN);
1029 else
1030 rc = RTFileOpen(&File, srcfilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
1031 if (RT_FAILURE(rc))
1032 {
1033 RTMsgError("Cannot open file \"%s\": %Rrc", srcfilename, rc);
1034 goto out;
1035 }
1036
1037 uint64_t cbFile;
1038 /* get image size. */
1039 if (fReadFromStdIn)
1040 cbFile = RTStrToUInt64(filesize);
1041 else
1042 rc = RTFileGetSize(File, &cbFile);
1043 if (RT_FAILURE(rc))
1044 {
1045 RTMsgError("Cannot get image size for file \"%s\": %Rrc", srcfilename, rc);
1046 goto out;
1047 }
1048
1049 RTStrmPrintf(g_pStdErr, "Creating %s image with size %RU64 bytes (%RU64MB)...\n",
1050 (uImageFlags & VD_IMAGE_FLAGS_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
1051 char pszComment[256];
1052 RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", srcfilename);
1053 rc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk);
1054 if (RT_FAILURE(rc))
1055 {
1056 RTMsgError("Cannot create the virtual disk container: %Rrc", rc);
1057 goto out;
1058 }
1059
1060 Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
1061 (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
1062 VDGEOMETRY PCHS, LCHS;
1063 PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
1064 PCHS.cHeads = 16;
1065 PCHS.cSectors = 63;
1066 LCHS.cCylinders = 0;
1067 LCHS.cHeads = 0;
1068 LCHS.cSectors = 0;
1069 rc = VDCreateBase(pDisk, format, dstfilename, cbFile,
1070 uImageFlags, pszComment, &PCHS, &LCHS, pUuid,
1071 VD_OPEN_FLAGS_NORMAL, NULL, NULL);
1072 if (RT_FAILURE(rc))
1073 {
1074 RTMsgError("Cannot create the disk image \"%s\": %Rrc", dstfilename, rc);
1075 goto out;
1076 }
1077
1078 size_t cbBuffer;
1079 cbBuffer = _1M;
1080 pvBuf = RTMemAlloc(cbBuffer);
1081 if (!pvBuf)
1082 {
1083 rc = VERR_NO_MEMORY;
1084 RTMsgError("Out of memory allocating buffers for image \"%s\": %Rrc", dstfilename, rc);
1085 goto out;
1086 }
1087
1088 uint64_t offFile;
1089 offFile = 0;
1090 while (offFile < cbFile)
1091 {
1092 size_t cbRead;
1093 size_t cbToRead;
1094 cbRead = 0;
1095 cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ?
1096 cbBuffer : (size_t)(cbFile - offFile);
1097 rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
1098 if (RT_FAILURE(rc) || !cbRead)
1099 break;
1100 rc = VDWrite(pDisk, offFile, pvBuf, cbRead);
1101 if (RT_FAILURE(rc))
1102 {
1103 RTMsgError("Failed to write to disk image \"%s\": %Rrc", dstfilename, rc);
1104 goto out;
1105 }
1106 offFile += cbRead;
1107 }
1108
1109out:
1110 if (pvBuf)
1111 RTMemFree(pvBuf);
1112 if (pDisk)
1113 VDClose(pDisk, RT_FAILURE(rc));
1114 if (File != NIL_RTFILE)
1115 RTFileClose(File);
1116
1117 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1118}
1119
1120HRESULT showMediumInfo(const ComPtr<IVirtualBox> &pVirtualBox,
1121 const ComPtr<IMedium> &pMedium,
1122 const char *pszParentUUID,
1123 bool fOptLong)
1124{
1125 HRESULT rc = S_OK;
1126 do
1127 {
1128 Bstr uuid;
1129 pMedium->COMGETTER(Id)(uuid.asOutParam());
1130 RTPrintf("UUID: %ls\n", uuid.raw());
1131 if (pszParentUUID)
1132 RTPrintf("Parent UUID: %s\n", pszParentUUID);
1133
1134 /* check for accessibility */
1135 MediumState_T enmState;
1136 CHECK_ERROR_BREAK(pMedium, RefreshState(&enmState));
1137 pMedium->RefreshState(&enmState);
1138 const char *pszState = "unknown";
1139 switch (enmState)
1140 {
1141 case MediumState_NotCreated:
1142 pszState = "not created";
1143 break;
1144 case MediumState_Created:
1145 pszState = "created";
1146 break;
1147 case MediumState_LockedRead:
1148 pszState = "locked read";
1149 break;
1150 case MediumState_LockedWrite:
1151 pszState = "locked write";
1152 break;
1153 case MediumState_Inaccessible:
1154 pszState = "inaccessible";
1155 break;
1156 case MediumState_Creating:
1157 pszState = "creating";
1158 break;
1159 case MediumState_Deleting:
1160 pszState = "deleting";
1161 break;
1162 }
1163 RTPrintf("State: %s\n", pszState);
1164
1165 if (fOptLong && enmState == MediumState_Inaccessible)
1166 {
1167 Bstr err;
1168 CHECK_ERROR_BREAK(pMedium, COMGETTER(LastAccessError)(err.asOutParam()));
1169 RTPrintf("Access Error: %ls\n", err.raw());
1170 }
1171
1172 if (fOptLong)
1173 {
1174 Bstr description;
1175 pMedium->COMGETTER(Description)(description.asOutParam());
1176 if (!description.isEmpty())
1177 RTPrintf("Description: %ls\n", description.raw());
1178 }
1179
1180 MediumType_T type;
1181 pMedium->COMGETTER(Type)(&type);
1182 const char *typeStr = "unknown";
1183 switch (type)
1184 {
1185 case MediumType_Normal:
1186 if (pszParentUUID && Guid(pszParentUUID).isValid())
1187 typeStr = "normal (differencing)";
1188 else
1189 typeStr = "normal (base)";
1190 break;
1191 case MediumType_Immutable:
1192 typeStr = "immutable";
1193 break;
1194 case MediumType_Writethrough:
1195 typeStr = "writethrough";
1196 break;
1197 case MediumType_Shareable:
1198 typeStr = "shareable";
1199 break;
1200 case MediumType_Readonly:
1201 typeStr = "readonly";
1202 break;
1203 case MediumType_MultiAttach:
1204 typeStr = "multiattach";
1205 break;
1206 }
1207 RTPrintf("Type: %s\n", typeStr);
1208
1209 /* print out information specific for differencing media */
1210 if (fOptLong && pszParentUUID && Guid(pszParentUUID).isValid())
1211 {
1212 BOOL autoReset = FALSE;
1213 pMedium->COMGETTER(AutoReset)(&autoReset);
1214 RTPrintf("Auto-Reset: %s\n", autoReset ? "on" : "off");
1215 }
1216
1217 Bstr loc;
1218 pMedium->COMGETTER(Location)(loc.asOutParam());
1219 RTPrintf("Location: %ls\n", loc.raw());
1220
1221 Bstr format;
1222 pMedium->COMGETTER(Format)(format.asOutParam());
1223 RTPrintf("Storage format: %ls\n", format.raw());
1224
1225 if (fOptLong)
1226 {
1227 com::SafeArray<MediumVariant_T> safeArray_variant;
1228
1229 pMedium->COMGETTER(Variant)(ComSafeArrayAsOutParam(safeArray_variant));
1230 ULONG variant=0;
1231 for (size_t i = 0; i < safeArray_variant.size(); i++)
1232 variant |= safeArray_variant[i];
1233
1234 const char *variantStr = "unknown";
1235 switch (variant & ~(MediumVariant_Fixed | MediumVariant_Diff))
1236 {
1237 case MediumVariant_VmdkSplit2G:
1238 variantStr = "split2G";
1239 break;
1240 case MediumVariant_VmdkStreamOptimized:
1241 variantStr = "streamOptimized";
1242 break;
1243 case MediumVariant_VmdkESX:
1244 variantStr = "ESX";
1245 break;
1246 case MediumVariant_Standard:
1247 variantStr = "default";
1248 break;
1249 }
1250 const char *variantTypeStr = "dynamic";
1251 if (variant & MediumVariant_Fixed)
1252 variantTypeStr = "fixed";
1253 else if (variant & MediumVariant_Diff)
1254 variantTypeStr = "differencing";
1255 RTPrintf("Format variant: %s %s\n", variantTypeStr, variantStr);
1256 }
1257
1258 LONG64 logicalSize;
1259 pMedium->COMGETTER(LogicalSize)(&logicalSize);
1260 RTPrintf("Capacity: %lld MBytes\n", logicalSize >> 20);
1261 if (fOptLong)
1262 {
1263 LONG64 actualSize;
1264 pMedium->COMGETTER(Size)(&actualSize);
1265 RTPrintf("Size on disk: %lld MBytes\n", actualSize >> 20);
1266 }
1267
1268 Bstr strCipher;
1269 Bstr strPasswordId;
1270 HRESULT rc2 = pMedium->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam());
1271 if (SUCCEEDED(rc2))
1272 {
1273 RTPrintf("Encryption: enabled\n");
1274 if (fOptLong)
1275 {
1276 RTPrintf("Cipher: %ls\n", strCipher.raw());
1277 RTPrintf("Password ID: %ls\n", strPasswordId.raw());
1278 }
1279 }
1280 else
1281 RTPrintf("Encryption: disabled\n");
1282
1283 if (fOptLong)
1284 {
1285 com::SafeArray<BSTR> names;
1286 com::SafeArray<BSTR> values;
1287 pMedium->GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values));
1288 size_t cNames = names.size();
1289 size_t cValues = values.size();
1290 bool fFirst = true;
1291 for (size_t i = 0; i < cNames; i++)
1292 {
1293 Bstr value;
1294 if (i < cValues)
1295 value = values[i];
1296 RTPrintf("%s%ls=%ls\n",
1297 fFirst ? "Property: " : " ",
1298 names[i], value.raw());
1299 }
1300 }
1301
1302 if (fOptLong)
1303 {
1304 bool fFirst = true;
1305 com::SafeArray<BSTR> machineIds;
1306 pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
1307 for (size_t i = 0; i < machineIds.size(); i++)
1308 {
1309 ComPtr<IMachine> pMachine;
1310 CHECK_ERROR(pVirtualBox, FindMachine(machineIds[i], pMachine.asOutParam()));
1311 if (pMachine)
1312 {
1313 Bstr name;
1314 pMachine->COMGETTER(Name)(name.asOutParam());
1315 pMachine->COMGETTER(Id)(uuid.asOutParam());
1316 RTPrintf("%s%ls (UUID: %ls)",
1317 fFirst ? "In use by VMs: " : " ",
1318 name.raw(), machineIds[i]);
1319 fFirst = false;
1320 com::SafeArray<BSTR> snapshotIds;
1321 pMedium->GetSnapshotIds(machineIds[i],
1322 ComSafeArrayAsOutParam(snapshotIds));
1323 for (size_t j = 0; j < snapshotIds.size(); j++)
1324 {
1325 ComPtr<ISnapshot> pSnapshot;
1326 pMachine->FindSnapshot(snapshotIds[j], pSnapshot.asOutParam());
1327 if (pSnapshot)
1328 {
1329 Bstr snapshotName;
1330 pSnapshot->COMGETTER(Name)(snapshotName.asOutParam());
1331 RTPrintf(" [%ls (UUID: %ls)]", snapshotName.raw(), snapshotIds[j]);
1332 }
1333 }
1334 RTPrintf("\n");
1335 }
1336 }
1337 }
1338
1339 if (fOptLong)
1340 {
1341 com::SafeIfaceArray<IMedium> children;
1342 pMedium->COMGETTER(Children)(ComSafeArrayAsOutParam(children));
1343 bool fFirst = true;
1344 for (size_t i = 0; i < children.size(); i++)
1345 {
1346 ComPtr<IMedium> pChild(children[i]);
1347 if (pChild)
1348 {
1349 Bstr childUUID;
1350 pChild->COMGETTER(Id)(childUUID.asOutParam());
1351 RTPrintf("%s%ls\n",
1352 fFirst ? "Child UUIDs: " : " ",
1353 childUUID.raw());
1354 fFirst = false;
1355 }
1356 }
1357 }
1358 }
1359 while (0);
1360
1361 return rc;
1362}
1363
1364static const RTGETOPTDEF g_aShowMediumInfoOptions[] =
1365{
1366 { "disk", 'd', RTGETOPT_REQ_NOTHING },
1367 { "dvd", 'D', RTGETOPT_REQ_NOTHING },
1368 { "floppy", 'f', RTGETOPT_REQ_NOTHING },
1369};
1370
1371int handleShowMediumInfo(HandlerArg *a)
1372{
1373 HRESULT rc;
1374 enum {
1375 CMD_NONE,
1376 CMD_DISK,
1377 CMD_DVD,
1378 CMD_FLOPPY
1379 } cmd = CMD_NONE;
1380 const char *pszFilenameOrUuid = NULL;
1381
1382 int c;
1383 RTGETOPTUNION ValueUnion;
1384 RTGETOPTSTATE GetState;
1385 // start at 0 because main() has hacked both the argc and argv given to us
1386 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowMediumInfoOptions, RT_ELEMENTS(g_aShowMediumInfoOptions),
1387 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
1388 while ((c = RTGetOpt(&GetState, &ValueUnion)))
1389 {
1390 switch (c)
1391 {
1392 case 'd': // disk
1393 if (cmd != CMD_NONE)
1394 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Only one command can be specified: '%s'", ValueUnion.psz);
1395 cmd = CMD_DISK;
1396 break;
1397
1398 case 'D': // DVD
1399 if (cmd != CMD_NONE)
1400 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Only one command can be specified: '%s'", ValueUnion.psz);
1401 cmd = CMD_DVD;
1402 break;
1403
1404 case 'f': // floppy
1405 if (cmd != CMD_NONE)
1406 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Only one command can be specified: '%s'", ValueUnion.psz);
1407 cmd = CMD_FLOPPY;
1408 break;
1409
1410 case VINF_GETOPT_NOT_OPTION:
1411 if (!pszFilenameOrUuid)
1412 pszFilenameOrUuid = ValueUnion.psz;
1413 else
1414 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Invalid parameter '%s'", ValueUnion.psz);
1415 break;
1416
1417 default:
1418 if (c > 0)
1419 {
1420 if (RT_C_IS_PRINT(c))
1421 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Invalid option -%c", c);
1422 else
1423 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Invalid option case %i", c);
1424 }
1425 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
1426 return errorSyntax(USAGE_SHOWMEDIUMINFO, "unknown option: %s\n", ValueUnion.psz);
1427 else if (ValueUnion.pDef)
1428 return errorSyntax(USAGE_SHOWMEDIUMINFO, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
1429 else
1430 return errorSyntax(USAGE_SHOWMEDIUMINFO, "error: %Rrs", c);
1431 }
1432 }
1433
1434 if (cmd == CMD_NONE)
1435 cmd = CMD_DISK;
1436
1437 /* check for required options */
1438 if (!pszFilenameOrUuid)
1439 return errorSyntax(USAGE_SHOWMEDIUMINFO, "Medium name or UUID required");
1440
1441 ComPtr<IMedium> pMedium;
1442 if (cmd == CMD_DISK)
1443 rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
1444 AccessMode_ReadOnly, pMedium,
1445 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1446 else if (cmd == CMD_DVD)
1447 rc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD,
1448 AccessMode_ReadOnly, pMedium,
1449 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1450 else if (cmd == CMD_FLOPPY)
1451 rc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy,
1452 AccessMode_ReadOnly, pMedium,
1453 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1454 if (FAILED(rc))
1455 return 1;
1456
1457 Utf8Str strParentUUID("base");
1458 ComPtr<IMedium> pParent;
1459 pMedium->COMGETTER(Parent)(pParent.asOutParam());
1460 if (!pParent.isNull())
1461 {
1462 Bstr bstrParentUUID;
1463 pParent->COMGETTER(Id)(bstrParentUUID.asOutParam());
1464 strParentUUID = bstrParentUUID;
1465 }
1466
1467 rc = showMediumInfo(a->virtualBox, pMedium, strParentUUID.c_str(), true);
1468
1469 return SUCCEEDED(rc) ? 0 : 1;
1470}
1471
1472static const RTGETOPTDEF g_aCloseMediumOptions[] =
1473{
1474 { "disk", 'd', RTGETOPT_REQ_NOTHING },
1475 { "dvd", 'D', RTGETOPT_REQ_NOTHING },
1476 { "floppy", 'f', RTGETOPT_REQ_NOTHING },
1477 { "--delete", 'r', RTGETOPT_REQ_NOTHING },
1478};
1479
1480int handleCloseMedium(HandlerArg *a)
1481{
1482 HRESULT rc = S_OK;
1483 enum {
1484 CMD_NONE,
1485 CMD_DISK,
1486 CMD_DVD,
1487 CMD_FLOPPY
1488 } cmd = CMD_NONE;
1489 const char *pszFilenameOrUuid = NULL;
1490 bool fDelete = false;
1491
1492 int c;
1493 RTGETOPTUNION ValueUnion;
1494 RTGETOPTSTATE GetState;
1495 // start at 0 because main() has hacked both the argc and argv given to us
1496 RTGetOptInit(&GetState, a->argc, a->argv, g_aCloseMediumOptions, RT_ELEMENTS(g_aCloseMediumOptions),
1497 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
1498 while ((c = RTGetOpt(&GetState, &ValueUnion)))
1499 {
1500 switch (c)
1501 {
1502 case 'd': // disk
1503 if (cmd != CMD_NONE)
1504 return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1505 cmd = CMD_DISK;
1506 break;
1507
1508 case 'D': // DVD
1509 if (cmd != CMD_NONE)
1510 return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1511 cmd = CMD_DVD;
1512 break;
1513
1514 case 'f': // floppy
1515 if (cmd != CMD_NONE)
1516 return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1517 cmd = CMD_FLOPPY;
1518 break;
1519
1520 case 'r': // --delete
1521 fDelete = true;
1522 break;
1523
1524 case VINF_GETOPT_NOT_OPTION:
1525 if (!pszFilenameOrUuid)
1526 pszFilenameOrUuid = ValueUnion.psz;
1527 else
1528 return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
1529 break;
1530
1531 default:
1532 if (c > 0)
1533 {
1534 if (RT_C_IS_PRINT(c))
1535 return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid option -%c", c);
1536 else
1537 return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid option case %i", c);
1538 }
1539 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
1540 return errorSyntax(USAGE_CLOSEMEDIUM, "unknown option: %s\n", ValueUnion.psz);
1541 else if (ValueUnion.pDef)
1542 return errorSyntax(USAGE_CLOSEMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
1543 else
1544 return errorSyntax(USAGE_CLOSEMEDIUM, "error: %Rrs", c);
1545 }
1546 }
1547
1548 /* check for required options */
1549 if (cmd == CMD_NONE)
1550 cmd = CMD_DISK;
1551 if (!pszFilenameOrUuid)
1552 return errorSyntax(USAGE_CLOSEMEDIUM, "Medium name or UUID required");
1553
1554 ComPtr<IMedium> pMedium;
1555 if (cmd == CMD_DISK)
1556 rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
1557 AccessMode_ReadWrite, pMedium,
1558 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1559 else if (cmd == CMD_DVD)
1560 rc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD,
1561 AccessMode_ReadOnly, pMedium,
1562 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1563 else if (cmd == CMD_FLOPPY)
1564 rc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy,
1565 AccessMode_ReadWrite, pMedium,
1566 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1567
1568 if (SUCCEEDED(rc) && pMedium)
1569 {
1570 if (fDelete)
1571 {
1572 ComPtr<IProgress> pProgress;
1573 CHECK_ERROR(pMedium, DeleteStorage(pProgress.asOutParam()));
1574 if (SUCCEEDED(rc))
1575 {
1576 rc = showProgress(pProgress);
1577 CHECK_PROGRESS_ERROR(pProgress, ("Failed to delete medium"));
1578 }
1579 else
1580 RTMsgError("Failed to delete medium. Error code %Rrc", rc);
1581 }
1582 CHECK_ERROR(pMedium, Close());
1583 }
1584
1585 return SUCCEEDED(rc) ? 0 : 1;
1586}
1587
1588int handleMediumProperty(HandlerArg *a)
1589{
1590 HRESULT rc = S_OK;
1591 const char *pszCmd = NULL;
1592 enum {
1593 CMD_NONE,
1594 CMD_DISK,
1595 CMD_DVD,
1596 CMD_FLOPPY
1597 } cmd = CMD_NONE;
1598 const char *pszAction = NULL;
1599 const char *pszFilenameOrUuid = NULL;
1600 const char *pszProperty = NULL;
1601 ComPtr<IMedium> pMedium;
1602
1603 pszCmd = (a->argc > 0) ? a->argv[0] : "";
1604 if ( !RTStrICmp(pszCmd, "disk")
1605 || !RTStrICmp(pszCmd, "dvd")
1606 || !RTStrICmp(pszCmd, "floppy"))
1607 {
1608 if (!RTStrICmp(pszCmd, "disk"))
1609 cmd = CMD_DISK;
1610 else if (!RTStrICmp(pszCmd, "dvd"))
1611 cmd = CMD_DVD;
1612 else if (!RTStrICmp(pszCmd, "floppy"))
1613 cmd = CMD_FLOPPY;
1614 else
1615 {
1616 AssertMsgFailed(("unexpected parameter %s\n", pszCmd));
1617 cmd = CMD_DISK;
1618 }
1619 a->argv++;
1620 a->argc--;
1621 }
1622 else
1623 {
1624 pszCmd = NULL;
1625 cmd = CMD_DISK;
1626 }
1627
1628 if (a->argc == 0)
1629 return errorSyntax(USAGE_MEDIUMPROPERTY, "Missing action");
1630
1631 pszAction = a->argv[0];
1632 if ( RTStrICmp(pszAction, "set")
1633 && RTStrICmp(pszAction, "get")
1634 && RTStrICmp(pszAction, "delete"))
1635 return errorSyntax(USAGE_MEDIUMPROPERTY, "Invalid action given: %s", pszAction);
1636
1637 if ( ( !RTStrICmp(pszAction, "set")
1638 && a->argc != 4)
1639 || ( RTStrICmp(pszAction, "set")
1640 && a->argc != 3))
1641 return errorSyntax(USAGE_MEDIUMPROPERTY, "Invalid number of arguments given for action: %s", pszAction);
1642
1643 pszFilenameOrUuid = a->argv[1];
1644 pszProperty = a->argv[2];
1645
1646 if (cmd == CMD_DISK)
1647 rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
1648 AccessMode_ReadWrite, pMedium,
1649 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1650 else if (cmd == CMD_DVD)
1651 rc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD,
1652 AccessMode_ReadOnly, pMedium,
1653 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1654 else if (cmd == CMD_FLOPPY)
1655 rc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy,
1656 AccessMode_ReadWrite, pMedium,
1657 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1658 if (SUCCEEDED(rc) && !pMedium.isNull())
1659 {
1660 if (!RTStrICmp(pszAction, "set"))
1661 {
1662 const char *pszValue = a->argv[3];
1663 CHECK_ERROR(pMedium, SetProperty(Bstr(pszProperty).raw(), Bstr(pszValue).raw()));
1664 }
1665 else if (!RTStrICmp(pszAction, "get"))
1666 {
1667 Bstr strVal;
1668 CHECK_ERROR(pMedium, GetProperty(Bstr(pszProperty).raw(), strVal.asOutParam()));
1669 if (SUCCEEDED(rc))
1670 RTPrintf("%s=%ls\n", pszProperty, strVal.raw());
1671 }
1672 else if (!RTStrICmp(pszAction, "delete"))
1673 {
1674 const char *pszValue = a->argv[3];
1675 CHECK_ERROR(pMedium, SetProperty(Bstr(pszProperty).raw(), Bstr().raw()));
1676 /** @todo */
1677 }
1678 }
1679
1680 return SUCCEEDED(rc) ? 0 : 1;
1681}
1682
1683static const RTGETOPTDEF g_aEncryptMediumOptions[] =
1684{
1685 { "--newpassword", 'n', RTGETOPT_REQ_STRING },
1686 { "--oldpassword", 'o', RTGETOPT_REQ_STRING },
1687 { "--cipher", 'c', RTGETOPT_REQ_STRING },
1688 { "--newpasswordid", 'i', RTGETOPT_REQ_STRING }
1689};
1690
1691int handleEncryptMedium(HandlerArg *a)
1692{
1693 HRESULT rc;
1694 int vrc;
1695 ComPtr<IMedium> hardDisk;
1696 const char *pszPasswordNew = NULL;
1697 const char *pszPasswordOld = NULL;
1698 const char *pszCipher = NULL;
1699 const char *pszFilenameOrUuid = NULL;
1700 const char *pszNewPasswordId = NULL;
1701 Utf8Str strPasswordNew;
1702 Utf8Str strPasswordOld;
1703
1704 int c;
1705 RTGETOPTUNION ValueUnion;
1706 RTGETOPTSTATE GetState;
1707 // start at 0 because main() has hacked both the argc and argv given to us
1708 RTGetOptInit(&GetState, a->argc, a->argv, g_aEncryptMediumOptions, RT_ELEMENTS(g_aEncryptMediumOptions),
1709 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
1710 while ((c = RTGetOpt(&GetState, &ValueUnion)))
1711 {
1712 switch (c)
1713 {
1714 case 'n': // --newpassword
1715 pszPasswordNew = ValueUnion.psz;
1716 break;
1717
1718 case 'o': // --oldpassword
1719 pszPasswordOld = ValueUnion.psz;
1720 break;
1721
1722 case 'c': // --cipher
1723 pszCipher = ValueUnion.psz;
1724 break;
1725
1726 case 'i': // --newpasswordid
1727 pszNewPasswordId = ValueUnion.psz;
1728 break;
1729
1730 case VINF_GETOPT_NOT_OPTION:
1731 if (!pszFilenameOrUuid)
1732 pszFilenameOrUuid = ValueUnion.psz;
1733 else
1734 return errorSyntax(USAGE_ENCRYPTMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
1735 break;
1736
1737 default:
1738 if (c > 0)
1739 {
1740 if (RT_C_IS_PRINT(c))
1741 return errorSyntax(USAGE_ENCRYPTMEDIUM, "Invalid option -%c", c);
1742 else
1743 return errorSyntax(USAGE_ENCRYPTMEDIUM, "Invalid option case %i", c);
1744 }
1745 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
1746 return errorSyntax(USAGE_ENCRYPTMEDIUM, "unknown option: %s\n", ValueUnion.psz);
1747 else if (ValueUnion.pDef)
1748 return errorSyntax(USAGE_ENCRYPTMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
1749 else
1750 return errorSyntax(USAGE_ENCRYPTMEDIUM, "error: %Rrs", c);
1751 }
1752 }
1753
1754 if (!pszFilenameOrUuid)
1755 return errorSyntax(USAGE_ENCRYPTMEDIUM, "Disk name or UUID required");
1756
1757 if (!pszPasswordNew && !pszPasswordOld)
1758 return errorSyntax(USAGE_ENCRYPTMEDIUM, "No password specified");
1759
1760 if ( (pszPasswordNew && !pszNewPasswordId)
1761 || (!pszPasswordNew && pszNewPasswordId))
1762 return errorSyntax(USAGE_ENCRYPTMEDIUM, "A new password must always have a valid identifier set at the same time");
1763
1764 if (pszPasswordNew)
1765 {
1766 if (!RTStrCmp(pszPasswordNew, "-"))
1767 {
1768 /* Get password from console. */
1769 vrc = getPassword("Enter new password:", &strPasswordNew);
1770 if (RT_FAILURE(vrc))
1771 {
1772 RTMsgError("Failed to read new password from standard input");
1773 return 1;
1774 }
1775 }
1776 else
1777 {
1778 RTEXITCODE rcExit = readPasswordFile(pszPasswordNew, &strPasswordNew);
1779 if (rcExit == RTEXITCODE_FAILURE)
1780 {
1781 RTMsgError("Failed to read new password from file");
1782 return rcExit;
1783 }
1784 }
1785 }
1786
1787 if (pszPasswordOld)
1788 {
1789 if (!RTStrCmp(pszPasswordOld, "-"))
1790 {
1791 /* Get password from console. */
1792 vrc = getPassword("Enter old password:", &strPasswordOld);
1793 if (RT_FAILURE(vrc))
1794 {
1795 RTMsgError("Failed to read old password from standard input");
1796 return 1;
1797 }
1798 }
1799 else
1800 {
1801 RTEXITCODE rcExit = readPasswordFile(pszPasswordOld, &strPasswordOld);
1802 if (rcExit == RTEXITCODE_FAILURE)
1803 {
1804 RTMsgError("Failed to read old password from file");
1805 return rcExit;
1806 }
1807 }
1808 }
1809
1810 /* Always open the medium if necessary, there is no other way. */
1811 rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
1812 AccessMode_ReadWrite, hardDisk,
1813 false /* fForceNewUuidOnOpen */, false /* fSilent */);
1814 if (FAILED(rc))
1815 return 1;
1816 if (hardDisk.isNull())
1817 {
1818 RTMsgError("Invalid hard disk reference, avoiding crash");
1819 return 1;
1820 }
1821
1822 ComPtr<IProgress> progress;
1823 CHECK_ERROR(hardDisk, ChangeEncryption(Bstr(strPasswordOld).raw(), Bstr(pszCipher).raw(),
1824 Bstr(strPasswordNew).raw(), Bstr(pszNewPasswordId).raw(),
1825 progress.asOutParam()));
1826 if (SUCCEEDED(rc))
1827 rc = showProgress(progress);
1828 if (FAILED(rc))
1829 {
1830 if (rc == E_NOTIMPL)
1831 RTMsgError("Encrypt hard disk operation is not implemented!");
1832 else if (rc == VBOX_E_NOT_SUPPORTED)
1833 RTMsgError("Encrypt hard disk operation for this cipher is not implemented yet!");
1834 else if (!progress.isNull())
1835 CHECK_PROGRESS_ERROR(progress, ("Failed to encrypt hard disk"));
1836 else
1837 RTMsgError("Failed to encrypt hard disk!");
1838 }
1839
1840 return SUCCEEDED(rc) ? 0 : 1;
1841}
1842
1843#endif /* !VBOX_ONLY_DOCS */
Note: See TracBrowser for help on using the repository browser.

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