~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: VBoxManageDisk.cpp $ */
 
1
/* $Id: VBoxManageDisk.cpp 35261 2010-12-20 17:44:59Z vboxsync $ */
2
2
/** @file
3
3
 * VBoxManage - The disk related commands.
4
4
 */
35
35
#include <iprt/ctype.h>
36
36
#include <iprt/getopt.h>
37
37
#include <VBox/log.h>
38
 
#include <VBox/VBoxHDD.h>
 
38
#include <VBox/vd.h>
39
39
 
40
40
#include "VBoxManage.h"
41
41
using namespace com;
47
47
 
48
48
static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
49
49
{
50
 
    RTPrintf("ERROR: ");
51
 
    RTPrintfV(pszFormat, va);
52
 
    RTPrintf("\n");
53
 
    RTPrintf("Error code %Rrc at %s(%u) in function %s\n", rc, RT_SRC_POS_ARGS);
 
50
    RTMsgError(pszFormat, va);
 
51
    RTMsgError("Error code %Rrc at %s(%u) in function %s", rc, RT_SRC_POS_ARGS);
54
52
}
55
53
 
56
54
 
98
96
    return rc;
99
97
}
100
98
 
101
 
static int parseDiskType(const char *psz, MediumType_T *pDiskType)
 
99
int parseDiskType(const char *psz, MediumType_T *pDiskType)
102
100
{
103
101
    int rc = VINF_SUCCESS;
104
102
    MediumType_T DiskType = MediumType_Normal;
110
108
        DiskType = MediumType_Writethrough;
111
109
    else if (!RTStrICmp(psz, "shareable"))
112
110
        DiskType = MediumType_Shareable;
 
111
    else if (!RTStrICmp(psz, "readonly"))
 
112
        DiskType = MediumType_Readonly;
 
113
    else if (!RTStrICmp(psz, "multiattach"))
 
114
        DiskType = MediumType_MultiAttach;
113
115
    else
114
116
        rc = VERR_PARSE_ERROR;
115
117
 
146
148
    return rc;
147
149
}
148
150
 
 
151
HRESULT findMedium(HandlerArg *a, const char *pszFilenameOrUuid,
 
152
                   DeviceType_T enmDevType, bool fSilent,
 
153
                   ComPtr<IMedium> &pMedium)
 
154
{
 
155
    HRESULT rc;
 
156
    Guid id(pszFilenameOrUuid);
 
157
    char szFilenameAbs[RTPATH_MAX] = "";
 
158
 
 
159
    /* If it is no UUID, convert the filename to an absolute one. */
 
160
    if (id.isEmpty())
 
161
    {
 
162
        int irc = RTPathAbs(pszFilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
 
163
        if (RT_FAILURE(irc))
 
164
        {
 
165
            if (!fSilent)
 
166
                RTMsgError("Cannot convert filename \"%s\" to absolute path", pszFilenameOrUuid);
 
167
            return E_FAIL;
 
168
        }
 
169
        pszFilenameOrUuid = szFilenameAbs;
 
170
    }
 
171
 
 
172
    if (!fSilent)
 
173
        CHECK_ERROR(a->virtualBox, FindMedium(Bstr(pszFilenameOrUuid).raw(),
 
174
                                              enmDevType, pMedium.asOutParam()));
 
175
    else
 
176
        rc = a->virtualBox->FindMedium(Bstr(pszFilenameOrUuid).raw(),
 
177
                                       enmDevType, pMedium.asOutParam());
 
178
    return rc;
 
179
}
 
180
 
 
181
HRESULT findOrOpenMedium(HandlerArg *a, const char *pszFilenameOrUuid,
 
182
                         DeviceType_T enmDevType, ComPtr<IMedium> &pMedium,
 
183
                         bool *pfWasUnknown)
 
184
{
 
185
    HRESULT rc;
 
186
    bool fWasUnknown = false;
 
187
    Guid id(pszFilenameOrUuid);
 
188
    char szFilenameAbs[RTPATH_MAX] = "";
 
189
 
 
190
    /* If it is no UUID, convert the filename to an absolute one. */
 
191
    if (id.isEmpty())
 
192
    {
 
193
        int irc = RTPathAbs(pszFilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
 
194
        if (RT_FAILURE(irc))
 
195
        {
 
196
            RTMsgError("Cannot convert filename \"%s\" to absolute path", pszFilenameOrUuid);
 
197
            return E_FAIL;
 
198
        }
 
199
        pszFilenameOrUuid = szFilenameAbs;
 
200
    }
 
201
 
 
202
    rc = a->virtualBox->FindMedium(Bstr(pszFilenameOrUuid).raw(), enmDevType,
 
203
                                   pMedium.asOutParam());
 
204
    /* If the medium is unknown try to open it. */
 
205
    if (!pMedium)
 
206
    {
 
207
        CHECK_ERROR(a->virtualBox, OpenMedium(Bstr(pszFilenameOrUuid).raw(),
 
208
                                              enmDevType, AccessMode_ReadWrite,
 
209
                                              pMedium.asOutParam()));
 
210
        if (SUCCEEDED(rc))
 
211
            fWasUnknown = true;
 
212
    }
 
213
    if (RT_VALID_PTR(pfWasUnknown))
 
214
        *pfWasUnknown = fWasUnknown;
 
215
    return rc;
 
216
}
 
217
 
 
218
static HRESULT createHardDisk(HandlerArg *a, const char *pszFormat,
 
219
                              const char *pszFilename, ComPtr<IMedium> &pMedium)
 
220
{
 
221
    HRESULT rc;
 
222
    char szFilenameAbs[RTPATH_MAX] = "";
 
223
 
 
224
    /** @todo laziness shortcut. should really check the MediumFormatCapabilities */
 
225
    if (RTStrICmp(pszFormat, "iSCSI"))
 
226
    {
 
227
        int irc = RTPathAbs(pszFilename, szFilenameAbs, sizeof(szFilenameAbs));
 
228
        if (RT_FAILURE(irc))
 
229
        {
 
230
            RTMsgError("Cannot convert filename \"%s\" to absolute path", pszFilename);
 
231
            return E_FAIL;
 
232
        }
 
233
        pszFilename = szFilenameAbs;
 
234
    }
 
235
 
 
236
    CHECK_ERROR(a->virtualBox, CreateHardDisk(Bstr(pszFormat).raw(),
 
237
                                              Bstr(pszFilename).raw(),
 
238
                                              pMedium.asOutParam()));
 
239
    return rc;
 
240
}
 
241
 
149
242
static const RTGETOPTDEF g_aCreateHardDiskOptions[] =
150
243
{
151
244
    { "--filename",     'f', RTGETOPT_REQ_STRING },
152
245
    { "-filename",      'f', RTGETOPT_REQ_STRING },     // deprecated
153
246
    { "--size",         's', RTGETOPT_REQ_UINT64 },
154
247
    { "-size",          's', RTGETOPT_REQ_UINT64 },     // deprecated
 
248
    { "--sizebyte",     'S', RTGETOPT_REQ_UINT64 },
155
249
    { "--format",       'o', RTGETOPT_REQ_STRING },
156
250
    { "-format",        'o', RTGETOPT_REQ_STRING },     // deprecated
157
251
    { "--static",       'F', RTGETOPT_REQ_NOTHING },
158
252
    { "-static",        'F', RTGETOPT_REQ_NOTHING },    // deprecated
159
253
    { "--variant",      'm', RTGETOPT_REQ_STRING },
160
254
    { "-variant",       'm', RTGETOPT_REQ_STRING },     // deprecated
161
 
    { "--type",         't', RTGETOPT_REQ_STRING },
162
 
    { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
163
 
    { "--comment",      'c', RTGETOPT_REQ_STRING },
164
 
    { "-comment",       'c', RTGETOPT_REQ_STRING },     // deprecated
165
 
    { "--remember",     'r', RTGETOPT_REQ_NOTHING },
166
 
    { "-remember",      'r', RTGETOPT_REQ_NOTHING },    // deprecated
167
 
    { "--register",     'r', RTGETOPT_REQ_NOTHING },    // deprecated (inofficial)
168
 
    { "-register",      'r', RTGETOPT_REQ_NOTHING },    // deprecated
169
255
};
170
256
 
171
257
int handleCreateHardDisk(HandlerArg *a)
172
258
{
173
259
    HRESULT rc;
174
260
    int vrc;
175
 
    Bstr filename;
176
 
    uint64_t sizeMB = 0;
177
 
    Bstr format = "VDI";
 
261
    const char *filename = NULL;
 
262
    uint64_t size = 0;
 
263
    const char *format = "VDI";
178
264
    MediumVariant_T DiskVariant = MediumVariant_Standard;
179
 
    Bstr comment;
180
 
    bool fRemember = false;
181
 
    MediumType_T DiskType = MediumType_Normal;
182
265
 
183
266
    int c;
184
267
    RTGETOPTUNION ValueUnion;
195
278
                break;
196
279
 
197
280
            case 's':   // --size
198
 
                sizeMB = ValueUnion.u64;
 
281
                size = ValueUnion.u64 * _1M;
 
282
                break;
 
283
 
 
284
            case 'S':   // --sizebyte
 
285
                size = ValueUnion.u64;
199
286
                break;
200
287
 
201
288
            case 'o':   // --format
216
303
                    return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz);
217
304
                break;
218
305
 
219
 
            case 'c':   // --comment
220
 
                comment = ValueUnion.psz;
221
 
                break;
222
 
 
223
 
            case 'r':   // --remember
224
 
                fRemember = true;
225
 
                break;
226
 
 
227
 
            case 't':   // --type
228
 
                vrc = parseDiskType(ValueUnion.psz, &DiskType);
229
 
                if (    RT_FAILURE(vrc)
230
 
                    ||  (   DiskType != MediumType_Normal
231
 
                         && DiskType != MediumType_Writethrough
232
 
                         && DiskType != MediumType_Shareable))
233
 
                    return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
234
 
                break;
235
 
 
236
306
            case VINF_GETOPT_NOT_OPTION:
237
307
                return errorSyntax(USAGE_CREATEHD, "Invalid parameter '%s'", ValueUnion.psz);
238
308
 
254
324
    }
255
325
 
256
326
    /* check the outcome */
257
 
    if (   filename.isEmpty()
258
 
        || sizeMB == 0)
 
327
    if (   !filename
 
328
        || !*filename
 
329
        || size == 0)
259
330
        return errorSyntax(USAGE_CREATEHD, "Parameters --filename and --size are required");
260
331
 
261
332
    /* check for filename extension */
 
333
    /** @todo use IMediumFormat to cover all extensions generically */
262
334
    Utf8Str strName(filename);
263
335
    if (!RTPathHaveExt(strName.c_str()))
264
336
    {
269
341
            strName.append(".vhd");
270
342
        else
271
343
            strName.append(".vdi");
272
 
        filename = Bstr(strName);
 
344
        filename = strName.c_str();
273
345
    }
274
346
 
275
347
    ComPtr<IMedium> hardDisk;
276
 
    CHECK_ERROR(a->virtualBox, CreateHardDisk(format, filename, hardDisk.asOutParam()));
 
348
    rc = createHardDisk(a, format, filename, hardDisk);
277
349
    if (SUCCEEDED(rc) && hardDisk)
278
350
    {
279
 
        /* we will close the hard disk after the storage has been successfully
280
 
         * created unless fRemember is set */
281
 
        bool doClose = false;
282
 
 
283
 
        if (!comment.isEmpty())
284
 
        {
285
 
            CHECK_ERROR(hardDisk,COMSETTER(Description)(comment));
286
 
        }
287
 
 
288
351
        ComPtr<IProgress> progress;
289
 
        CHECK_ERROR(hardDisk, CreateBaseStorage(sizeMB, DiskVariant, progress.asOutParam()));
 
352
        CHECK_ERROR(hardDisk, CreateBaseStorage(size, DiskVariant, progress.asOutParam()));
290
353
        if (SUCCEEDED(rc) && progress)
291
354
        {
292
355
            rc = showProgress(progress);
294
357
            {
295
358
                com::ProgressErrorInfo info(progress);
296
359
                if (info.isBasicAvailable())
297
 
                    RTPrintf("Error: failed to create hard disk. Error message: %lS\n", info.getText().raw());
 
360
                    RTMsgError("Failed to create hard disk. Error message: %lS", info.getText().raw());
298
361
                else
299
 
                    RTPrintf("Error: failed to create hard disk. No error message available!\n");
 
362
                    RTMsgError("Failed to create hard disk. No error message available!");
300
363
            }
301
364
            else
302
365
            {
303
 
                doClose = !fRemember;
304
 
 
305
366
                Bstr uuid;
306
367
                CHECK_ERROR(hardDisk, COMGETTER(Id)(uuid.asOutParam()));
307
 
 
308
 
                if (   DiskType == MediumType_Writethrough
309
 
                    || DiskType == MediumType_Shareable)
310
 
                {
311
 
                    CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
312
 
                }
313
 
 
314
 
                RTPrintf("Disk image created. UUID: %s\n", Utf8Str(uuid).raw());
 
368
                RTPrintf("Disk image created. UUID: %s\n", Utf8Str(uuid).c_str());
315
369
            }
316
370
        }
317
 
        if (doClose)
318
 
        {
319
 
            CHECK_ERROR(hardDisk, Close());
320
 
        }
 
371
        CHECK_ERROR(hardDisk, Close());
321
372
    }
322
373
    return SUCCEEDED(rc) ? 0 : 1;
323
374
}
324
375
 
325
 
#if 0 /* disabled until disk shrinking is implemented based on VBoxHDD */
326
 
static DECLCALLBACK(int) hardDiskProgressCallback(PVM pVM, unsigned uPercent, void *pvUser)
327
 
{
328
 
    unsigned *pPercent = (unsigned *)pvUser;
329
 
 
330
 
    if (*pPercent != uPercent)
331
 
    {
332
 
        *pPercent = uPercent;
333
 
        RTPrintf(".");
334
 
        if ((uPercent % 10) == 0 && uPercent)
335
 
            RTPrintf("%d%%", uPercent);
336
 
        RTStrmFlush(g_pStdOut);
337
 
    }
338
 
 
339
 
    return VINF_SUCCESS;
340
 
}
341
 
#endif
342
 
 
343
376
static const RTGETOPTDEF g_aModifyHardDiskOptions[] =
344
377
{
345
378
    { "--type",         't', RTGETOPT_REQ_STRING },
351
384
    { "--compact",      'c', RTGETOPT_REQ_NOTHING },
352
385
    { "-compact",       'c', RTGETOPT_REQ_NOTHING },    // deprecated
353
386
    { "compact",        'c', RTGETOPT_REQ_NOTHING },    // deprecated
 
387
    { "--resize",       'r', RTGETOPT_REQ_UINT64 },
 
388
    { "--resizebyte",   'R', RTGETOPT_REQ_UINT64 }
354
389
};
355
390
 
356
391
int handleModifyHardDisk(HandlerArg *a)
360
395
    ComPtr<IMedium> hardDisk;
361
396
    MediumType_T DiskType;
362
397
    bool AutoReset = false;
363
 
    bool fModifyDiskType = false, fModifyAutoReset = false, fModifyCompact = false;;
 
398
    bool fModifyDiskType = false, fModifyAutoReset = false, fModifyCompact = false;
 
399
    bool fModifyResize = false;
 
400
    uint64_t cbResize = 0;
364
401
    const char *FilenameOrUuid = NULL;
 
402
    bool unknown = false;
365
403
 
366
404
    int c;
367
405
    RTGETOPTUNION ValueUnion;
391
429
                fModifyCompact = true;
392
430
                break;
393
431
 
 
432
            case 'r':   // --resize
 
433
                cbResize = ValueUnion.u64 * _1M;
 
434
                fModifyResize = true;
 
435
                break;
 
436
 
 
437
            case 'R':   // --resizebyte
 
438
                cbResize = ValueUnion.u64;
 
439
                fModifyResize = true;
 
440
                break;
 
441
 
394
442
            case VINF_GETOPT_NOT_OPTION:
395
443
                if (!FilenameOrUuid)
396
444
                    FilenameOrUuid = ValueUnion.psz;
418
466
    if (!FilenameOrUuid)
419
467
        return errorSyntax(USAGE_MODIFYHD, "Disk name or UUID required");
420
468
 
421
 
    if (!fModifyDiskType && !fModifyAutoReset && !fModifyCompact)
 
469
    if (!fModifyDiskType && !fModifyAutoReset && !fModifyCompact && !fModifyResize)
422
470
        return errorSyntax(USAGE_MODIFYHD, "No operation specified");
423
471
 
424
 
    /* first guess is that it's a UUID */
425
 
    Guid uuid(FilenameOrUuid);
426
 
    rc = a->virtualBox->GetHardDisk(uuid.toUtf16(), hardDisk.asOutParam());
427
 
    /* no? then it must be a filename */
428
 
    if (!hardDisk)
 
472
    /* Depending on the operation the medium must be in the registry or
 
473
     * may be opened on demand. */
 
474
    if (fModifyDiskType || fModifyAutoReset)
 
475
        rc = findMedium(a, FilenameOrUuid, DeviceType_HardDisk, false /* fSilent */, hardDisk);
 
476
    else
 
477
        rc = findOrOpenMedium(a, FilenameOrUuid, DeviceType_HardDisk,
 
478
                              hardDisk, &unknown);
 
479
    if (FAILED(rc))
 
480
        return 1;
 
481
    if (hardDisk.isNull())
429
482
    {
430
 
        CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(FilenameOrUuid), hardDisk.asOutParam()));
431
 
        if (FAILED(rc))
432
 
            return 1;
 
483
        RTMsgError("Invalid hard disk reference, avoiding crash");
 
484
        return 1;
433
485
    }
434
486
 
435
487
    if (fModifyDiskType)
436
488
    {
437
 
        /* hard disk must be registered */
438
 
        if (SUCCEEDED(rc) && hardDisk)
439
 
        {
440
 
            MediumType_T hddType;
441
 
            CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
 
489
        MediumType_T hddType;
 
490
        CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
442
491
 
443
 
            if (hddType != DiskType)
444
 
                CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
445
 
        }
446
 
        else
447
 
            return errorArgument("Hard disk image not registered");
 
492
        if (hddType != DiskType)
 
493
            CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
448
494
    }
449
495
 
450
496
    if (fModifyAutoReset)
454
500
 
455
501
    if (fModifyCompact)
456
502
    {
457
 
        bool unknown = false;
458
 
        /* the hard disk image might not be registered */
459
 
        if (!hardDisk)
460
 
        {
461
 
            unknown = true;
462
 
            rc = a->virtualBox->OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam());
463
 
            if (rc == VBOX_E_FILE_ERROR)
464
 
            {
465
 
                char szFilenameAbs[RTPATH_MAX] = "";
466
 
                int irc = RTPathAbs(FilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
467
 
                if (RT_FAILURE(irc))
468
 
                {
469
 
                    RTPrintf("Cannot convert filename \"%s\" to absolute path\n", FilenameOrUuid);
470
 
                    return 1;
471
 
                }
472
 
                CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam()));
473
 
            }
474
 
            else if (FAILED(rc))
475
 
                CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam()));
476
 
        }
477
 
        if (SUCCEEDED(rc) && hardDisk)
478
 
        {
479
 
            ComPtr<IProgress> progress;
480
 
            CHECK_ERROR(hardDisk, Compact(progress.asOutParam()));
481
 
            if (SUCCEEDED(rc))
482
 
                rc = showProgress(progress);
483
 
            if (FAILED(rc))
484
 
            {
485
 
                if (rc == E_NOTIMPL)
486
 
                {
487
 
                    RTPrintf("Error: Compact hard disk operation is not implemented!\n");
488
 
                    RTPrintf("The functionality will be restored later.\n");
489
 
                }
490
 
                else if (rc == VBOX_E_NOT_SUPPORTED)
491
 
                {
492
 
                    RTPrintf("Error: Compact hard disk operation for this format is not implemented yet!\n");
493
 
                }
494
 
                else
495
 
                    com::GluePrintRCMessage(rc);
496
 
            }
497
 
            if (unknown)
498
 
                hardDisk->Close();
499
 
        }
500
 
    }
 
503
        ComPtr<IProgress> progress;
 
504
        CHECK_ERROR(hardDisk, Compact(progress.asOutParam()));
 
505
        if (SUCCEEDED(rc))
 
506
            rc = showProgress(progress);
 
507
        if (FAILED(rc))
 
508
        {
 
509
            if (rc == E_NOTIMPL)
 
510
                RTMsgError("Compact hard disk operation is not implemented!");
 
511
            else if (rc == VBOX_E_NOT_SUPPORTED)
 
512
                RTMsgError("Compact hard disk operation for this format is not implemented yet!");
 
513
            else
 
514
                com::GluePrintRCMessage(rc);
 
515
        }
 
516
    }
 
517
 
 
518
    if (fModifyResize)
 
519
    {
 
520
        ComPtr<IProgress> progress;
 
521
        CHECK_ERROR(hardDisk, Resize(cbResize, progress.asOutParam()));
 
522
        if (SUCCEEDED(rc))
 
523
            rc = showProgress(progress);
 
524
        if (FAILED(rc))
 
525
        {
 
526
            if (rc == E_NOTIMPL)
 
527
                RTMsgError("Resize hard disk operation is not implemented!");
 
528
            else if (rc == VBOX_E_NOT_SUPPORTED)
 
529
                RTMsgError("Resize hard disk operation for this format is not implemented yet!");
 
530
            else
 
531
                com::GluePrintRCMessage(rc);
 
532
        }
 
533
    }
 
534
 
 
535
    if (unknown)
 
536
        hardDisk->Close();
501
537
 
502
538
    return SUCCEEDED(rc) ? 0 : 1;
503
539
}
511
547
    { "--existing",     'E', RTGETOPT_REQ_NOTHING },
512
548
    { "--variant",      'm', RTGETOPT_REQ_STRING },
513
549
    { "-variant",       'm', RTGETOPT_REQ_STRING },
514
 
    { "--type",         't', RTGETOPT_REQ_STRING },
515
 
    { "-type",          't', RTGETOPT_REQ_STRING },
516
 
    { "--remember",     'r', RTGETOPT_REQ_NOTHING },
517
 
    { "-remember",      'r', RTGETOPT_REQ_NOTHING },
518
 
    { "--register",     'r', RTGETOPT_REQ_NOTHING },
519
 
    { "-register",      'r', RTGETOPT_REQ_NOTHING },
520
550
};
521
551
 
522
552
int handleCloneHardDisk(HandlerArg *a)
523
553
{
524
554
    HRESULT rc;
525
555
    int vrc;
526
 
    Bstr src, dst;
 
556
    const char *pszSrc = NULL;
 
557
    const char *pszDst = NULL;
527
558
    Bstr format;
528
559
    MediumVariant_T DiskVariant = MediumVariant_Standard;
529
560
    bool fExisting = false;
530
 
    bool fRemember = false;
531
 
    bool fSetDiskType = false;
532
 
    MediumType_T DiskType = MediumType_Normal;
533
561
 
534
562
    int c;
535
563
    RTGETOPTUNION ValueUnion;
563
591
                    return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz);
564
592
                break;
565
593
 
566
 
            case 'r':   // --remember
567
 
                fRemember = true;
568
 
                break;
569
 
 
570
 
            case 't':   // --type
571
 
                vrc = parseDiskType(ValueUnion.psz, &DiskType);
572
 
                if (RT_FAILURE(vrc))
573
 
                    return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
574
 
                fSetDiskType = true;
575
 
                break;
576
 
 
577
594
            case VINF_GETOPT_NOT_OPTION:
578
 
                if (src.isEmpty())
579
 
                    src = ValueUnion.psz;
580
 
                else if (dst.isEmpty())
581
 
                    dst = ValueUnion.psz;
 
595
                if (!pszSrc)
 
596
                    pszSrc = ValueUnion.psz;
 
597
                else if (!pszDst)
 
598
                    pszDst = ValueUnion.psz;
582
599
                else
583
600
                    return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", ValueUnion.psz);
584
601
                break;
600
617
        }
601
618
    }
602
619
 
603
 
    if (src.isEmpty())
 
620
    if (!pszSrc)
604
621
        return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing");
605
 
    if (dst.isEmpty())
 
622
    if (!pszDst)
606
623
        return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing");
607
624
    if (fExisting && (!format.isEmpty() || DiskVariant != MediumType_Normal))
608
625
        return errorSyntax(USAGE_CLONEHD, "Specified options which cannot be used with --existing");
612
629
    bool fSrcUnknown = false;
613
630
    bool fDstUnknown = false;
614
631
 
615
 
    /* first guess is that it's a UUID */
616
 
    rc = a->virtualBox->GetHardDisk(src, srcDisk.asOutParam());
617
 
    /* no? then it must be a filename */
618
 
    if (FAILED (rc))
619
 
        rc = a->virtualBox->FindHardDisk(src, srcDisk.asOutParam());
620
 
    /* no? well, then it's an unknown image */
621
 
    if (FAILED (rc))
622
 
    {
623
 
        rc = a->virtualBox->OpenHardDisk(src, AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), srcDisk.asOutParam());
624
 
        if (rc == VBOX_E_FILE_ERROR)
625
 
        {
626
 
            char szFilenameAbs[RTPATH_MAX] = "";
627
 
            int irc = RTPathAbs(Utf8Str(src).c_str(), szFilenameAbs, sizeof(szFilenameAbs));
628
 
            if (RT_FAILURE(irc))
629
 
            {
630
 
                RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Utf8Str(src).raw());
631
 
                return 1;
632
 
            }
633
 
            CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), srcDisk.asOutParam()));
634
 
        }
635
 
        else if (FAILED(rc))
636
 
            CHECK_ERROR(a->virtualBox, OpenHardDisk(src, AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), srcDisk.asOutParam()));
637
 
        if (SUCCEEDED (rc))
638
 
            fSrcUnknown = true;
639
 
    }
 
632
    rc = findOrOpenMedium(a, pszSrc, DeviceType_HardDisk, srcDisk, &fSrcUnknown);
 
633
    if (FAILED(rc))
 
634
        return 1;
640
635
 
641
636
    do
642
637
    {
643
 
        if (!SUCCEEDED(rc))
644
 
            break;
645
 
 
646
638
        /* open/create destination hard disk */
647
639
        if (fExisting)
648
640
        {
649
 
            /* first guess is that it's a UUID */
650
 
            rc = a->virtualBox->GetHardDisk(dst, dstDisk.asOutParam());
651
 
            /* no? then it must be a filename */
652
 
            if (FAILED (rc))
653
 
                rc = a->virtualBox->FindHardDisk(dst, dstDisk.asOutParam());
654
 
            /* no? well, then it's an unknown image */
655
 
            if (FAILED (rc))
656
 
            {
657
 
                rc = a->virtualBox->OpenHardDisk(dst, AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), dstDisk.asOutParam());
658
 
                if (rc == VBOX_E_FILE_ERROR)
659
 
                {
660
 
                    char szFilenameAbs[RTPATH_MAX] = "";
661
 
                    int irc = RTPathAbs(Utf8Str(dst).c_str(), szFilenameAbs, sizeof(szFilenameAbs));
662
 
                    if (RT_FAILURE(irc))
663
 
                    {
664
 
                        RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Utf8Str(dst).raw());
665
 
                        return 1;
666
 
                    }
667
 
                    CHECK_ERROR_BREAK(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), dstDisk.asOutParam()));
668
 
                }
669
 
                else if (FAILED(rc))
670
 
                    CHECK_ERROR_BREAK(a->virtualBox, OpenHardDisk(dst, AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), dstDisk.asOutParam()));
671
 
                if (SUCCEEDED (rc))
672
 
                    fDstUnknown = true;
673
 
            }
674
 
            else
675
 
                fRemember = true;
676
 
            if (SUCCEEDED(rc))
677
 
            {
678
 
                /* Perform accessibility check now. */
679
 
                MediumState_T state;
680
 
                CHECK_ERROR_BREAK(dstDisk, RefreshState(&state));
681
 
            }
682
 
            CHECK_ERROR_BREAK(dstDisk, COMGETTER(Format) (format.asOutParam()));
 
641
            rc = findOrOpenMedium(a, pszDst, DeviceType_HardDisk, dstDisk, &fDstUnknown);
 
642
            if (FAILED(rc))
 
643
                break;
 
644
 
 
645
            /* Perform accessibility check now. */
 
646
            MediumState_T state;
 
647
            CHECK_ERROR_BREAK(dstDisk, RefreshState(&state));
 
648
            CHECK_ERROR_BREAK(dstDisk, COMGETTER(Format)(format.asOutParam()));
683
649
        }
684
650
        else
685
651
        {
686
652
            /* use the format of the source hard disk if unspecified */
687
653
            if (format.isEmpty())
688
 
                CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format) (format.asOutParam()));
689
 
            CHECK_ERROR_BREAK(a->virtualBox, CreateHardDisk(format, dst, dstDisk.asOutParam()));
 
654
                CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format)(format.asOutParam()));
 
655
            rc = createHardDisk(a, Utf8Str(format).c_str(), pszDst, dstDisk);
 
656
            if (FAILED(rc))
 
657
                break;
690
658
        }
691
659
 
692
660
        ComPtr<IProgress> progress;
697
665
        {
698
666
            com::ProgressErrorInfo info(progress);
699
667
            if (info.isBasicAvailable())
700
 
                RTPrintf("Error: failed to clone hard disk. Error message: %lS\n", info.getText().raw());
 
668
                RTMsgError("Failed to clone hard disk. Error message: %lS", info.getText().raw());
701
669
            else
702
 
                RTPrintf("Error: failed to clone hard disk. No error message available!\n");
 
670
                RTMsgError("Failed to clone hard disk. No error message available!");
703
671
            break;
704
672
        }
705
673
 
707
675
        CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam()));
708
676
 
709
677
        RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n",
710
 
                 format.raw(), Utf8Str(uuid).raw());
 
678
                 format.raw(), Utf8Str(uuid).c_str());
711
679
    }
712
680
    while (0);
713
681
 
714
 
    if (!fRemember && !dstDisk.isNull())
 
682
    if (fDstUnknown && !dstDisk.isNull())
715
683
    {
716
684
        /* forget the created clone */
717
685
        dstDisk->Close();
718
686
    }
719
 
    else if (fSetDiskType)
720
 
    {
721
 
        CHECK_ERROR(dstDisk, COMSETTER(Type)(DiskType));
722
 
    }
723
 
 
724
687
    if (fSrcUnknown)
725
688
    {
726
689
        /* close the unknown hard disk to forget it again */
740
703
    { "-variant",       'm', RTGETOPT_REQ_STRING },
741
704
};
742
705
 
743
 
int handleConvertFromRaw(int argc, char *argv[])
 
706
RTEXITCODE handleConvertFromRaw(int argc, char *argv[])
744
707
{
745
708
    int rc = VINF_SUCCESS;
746
709
    bool fReadFromStdIn = false;
798
761
 
799
762
    if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize))
800
763
        return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
801
 
    RTPrintf("Converting from raw image file=\"%s\" to file=\"%s\"...\n",
802
 
             srcfilename, dstfilename);
 
764
    RTStrmPrintf(g_pStdErr, "Converting from raw image file=\"%s\" to file=\"%s\"...\n",
 
765
                 srcfilename, dstfilename);
803
766
 
804
767
    PVBOXHDD pDisk = NULL;
805
768
 
823
786
        rc = RTFileOpen(&File, srcfilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
824
787
    if (RT_FAILURE(rc))
825
788
    {
826
 
        RTPrintf("File=\"%s\" open error: %Rrf\n", srcfilename, rc);
 
789
        RTMsgError("Cannot open file \"%s\": %Rrc", srcfilename, rc);
827
790
        goto out;
828
791
    }
829
792
 
835
798
        rc = RTFileGetSize(File, &cbFile);
836
799
    if (RT_FAILURE(rc))
837
800
    {
838
 
        RTPrintf("Error getting image size for file \"%s\": %Rrc\n", srcfilename, rc);
 
801
        RTMsgError("Cannot get image size for file \"%s\": %Rrc", srcfilename, rc);
839
802
        goto out;
840
803
    }
841
804
 
842
 
    RTPrintf("Creating %s image with size %RU64 bytes (%RU64MB)...\n", (uImageFlags & VD_IMAGE_FLAGS_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
 
805
    RTStrmPrintf(g_pStdErr, "Creating %s image with size %RU64 bytes (%RU64MB)...\n",
 
806
                 (uImageFlags & VD_IMAGE_FLAGS_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
843
807
    char pszComment[256];
844
808
    RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", srcfilename);
845
 
    rc = VDCreate(pVDIfs, &pDisk);
 
809
    rc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk);
846
810
    if (RT_FAILURE(rc))
847
811
    {
848
 
        RTPrintf("Error while creating the virtual disk container: %Rrc\n", rc);
 
812
        RTMsgError("Cannot create the virtual disk container: %Rrc", rc);
849
813
        goto out;
850
814
    }
851
815
 
852
816
    Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
853
817
           (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
854
 
    PDMMEDIAGEOMETRY PCHS, LCHS;
 
818
    VDGEOMETRY PCHS, LCHS;
855
819
    PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
856
820
    PCHS.cHeads = 16;
857
821
    PCHS.cSectors = 63;
863
827
                      VD_OPEN_FLAGS_NORMAL, NULL, NULL);
864
828
    if (RT_FAILURE(rc))
865
829
    {
866
 
        RTPrintf("Error while creating the disk image \"%s\": %Rrc\n", dstfilename, rc);
 
830
        RTMsgError("Cannot create the disk image \"%s\": %Rrc", dstfilename, rc);
867
831
        goto out;
868
832
    }
869
833
 
873
837
    if (!pvBuf)
874
838
    {
875
839
        rc = VERR_NO_MEMORY;
876
 
        RTPrintf("Not enough memory allocating buffers for image \"%s\": %Rrc\n", dstfilename, rc);
 
840
        RTMsgError("Out of memory allocating buffers for image \"%s\": %Rrc", dstfilename, rc);
877
841
        goto out;
878
842
    }
879
843
 
885
849
        size_t cbToRead;
886
850
        cbRead = 0;
887
851
        cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ?
888
 
                            cbBuffer : (size_t) (cbFile - offFile);
 
852
                            cbBuffer : (size_t)(cbFile - offFile);
889
853
        rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
890
854
        if (RT_FAILURE(rc) || !cbRead)
891
855
            break;
892
856
        rc = VDWrite(pDisk, offFile, pvBuf, cbRead);
893
857
        if (RT_FAILURE(rc))
894
858
        {
895
 
            RTPrintf("Failed to write to disk image \"%s\": %Rrc\n", dstfilename, rc);
 
859
            RTMsgError("Failed to write to disk image \"%s\": %Rrc", dstfilename, rc);
896
860
            goto out;
897
861
        }
898
862
        offFile += cbRead;
906
870
    if (File != NIL_RTFILE)
907
871
        RTFileClose(File);
908
872
 
909
 
    return RT_FAILURE(rc);
910
 
}
911
 
 
912
 
static const RTGETOPTDEF g_aAddiSCSIDiskOptions[] =
913
 
{
914
 
    { "--server",       's', RTGETOPT_REQ_STRING },
915
 
    { "-server",        's', RTGETOPT_REQ_STRING },     // deprecated
916
 
    { "--target",       'T', RTGETOPT_REQ_STRING },
917
 
    { "-target",        'T', RTGETOPT_REQ_STRING },     // deprecated
918
 
    { "--port",         'p', RTGETOPT_REQ_STRING },
919
 
    { "-port",          'p', RTGETOPT_REQ_STRING },     // deprecated
920
 
    { "--lun",          'l', RTGETOPT_REQ_STRING },
921
 
    { "-lun",           'l', RTGETOPT_REQ_STRING },     // deprecated
922
 
    { "--encodedlun",   'L', RTGETOPT_REQ_STRING },
923
 
    { "-encodedlun",    'L', RTGETOPT_REQ_STRING },     // deprecated
924
 
    { "--username",     'u', RTGETOPT_REQ_STRING },
925
 
    { "-username",      'u', RTGETOPT_REQ_STRING },     // deprecated
926
 
    { "--password",     'P', RTGETOPT_REQ_STRING },
927
 
    { "-password",      'P', RTGETOPT_REQ_STRING },     // deprecated
928
 
    { "--type",         't', RTGETOPT_REQ_STRING },
929
 
    { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
930
 
    { "--intnet",       'I', RTGETOPT_REQ_NOTHING },
931
 
    { "-intnet",        'I', RTGETOPT_REQ_NOTHING },    // deprecated
932
 
};
933
 
 
934
 
int handleAddiSCSIDisk(HandlerArg *a)
935
 
{
936
 
    HRESULT rc;
937
 
    int vrc;
938
 
    Bstr server;
939
 
    Bstr target;
940
 
    Bstr port;
941
 
    Bstr lun;
942
 
    Bstr username;
943
 
    Bstr password;
944
 
    Bstr comment;
945
 
    bool fIntNet = false;
946
 
    MediumType_T DiskType = MediumType_Normal;
947
 
 
948
 
    int c;
949
 
    RTGETOPTUNION ValueUnion;
950
 
    RTGETOPTSTATE GetState;
951
 
    // start at 0 because main() has hacked both the argc and argv given to us
952
 
    RTGetOptInit(&GetState, a->argc, a->argv, g_aAddiSCSIDiskOptions, RT_ELEMENTS(g_aAddiSCSIDiskOptions),
953
 
                 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
954
 
    while ((c = RTGetOpt(&GetState, &ValueUnion)))
955
 
    {
956
 
        switch (c)
957
 
        {
958
 
            case 's':   // --server
959
 
                server = ValueUnion.psz;
960
 
                break;
961
 
 
962
 
            case 'T':   // --target
963
 
                target = ValueUnion.psz;
964
 
                break;
965
 
 
966
 
            case 'p':   // --port
967
 
                port = ValueUnion.psz;
968
 
                break;
969
 
 
970
 
            case 'l':   // --lun
971
 
                lun = ValueUnion.psz;
972
 
                break;
973
 
 
974
 
            case 'L':   // --encodedlun
975
 
                lun = BstrFmt("enc%s", ValueUnion.psz);
976
 
                break;
977
 
 
978
 
            case 'u':   // --username
979
 
                username = ValueUnion.psz;
980
 
                break;
981
 
 
982
 
            case 'P':   // --password
983
 
                password = ValueUnion.psz;
984
 
                break;
985
 
 
986
 
            case 't':   // --type
987
 
                vrc = parseDiskType(ValueUnion.psz, &DiskType);
988
 
                if (RT_FAILURE(vrc))
989
 
                    return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
990
 
                break;
991
 
 
992
 
            case 'I':   // --intnet
993
 
                fIntNet = true;
994
 
                break;
995
 
 
996
 
            case VINF_GETOPT_NOT_OPTION:
997
 
                return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", ValueUnion.psz);
998
 
 
999
 
            default:
1000
 
                if (c > 0)
1001
 
                {
1002
 
                    if (RT_C_IS_PRINT(c))
1003
 
                        return errorSyntax(USAGE_ADDISCSIDISK, "Invalid option -%c", c);
1004
 
                    else
1005
 
                        return errorSyntax(USAGE_ADDISCSIDISK, "Invalid option case %i", c);
1006
 
                }
1007
 
                else if (c == VERR_GETOPT_UNKNOWN_OPTION)
1008
 
                    return errorSyntax(USAGE_ADDISCSIDISK, "unknown option: %s\n", ValueUnion.psz);
1009
 
                else if (ValueUnion.pDef)
1010
 
                    return errorSyntax(USAGE_ADDISCSIDISK, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
1011
 
                else
1012
 
                    return errorSyntax(USAGE_ADDISCSIDISK, "error: %Rrs", c);
1013
 
        }
1014
 
    }
1015
 
 
1016
 
    /* check for required options */
1017
 
    if (server.isEmpty() || target.isEmpty())
1018
 
        return errorSyntax(USAGE_ADDISCSIDISK, "Parameters --server and --target are required");
1019
 
 
1020
 
    do
1021
 
    {
1022
 
        ComPtr<IMedium> hardDisk;
1023
 
        /** @todo move the location stuff to Main, which can use pfnComposeName
1024
 
         * from the disk backends to construct the location properly. Also do
1025
 
         * not use slashes to separate the parts, as otherwise only the last
1026
 
         * element comtaining information will be shown. */
1027
 
        if (lun.isEmpty() || lun == "0" || lun == "enc0")
1028
 
        {
1029
 
            CHECK_ERROR_BREAK (a->virtualBox,
1030
 
                CreateHardDisk(Bstr ("iSCSI"),
1031
 
                               BstrFmt ("%ls|%ls", server.raw(), target.raw()),
1032
 
                               hardDisk.asOutParam()));
1033
 
        }
1034
 
        else
1035
 
        {
1036
 
            CHECK_ERROR_BREAK (a->virtualBox,
1037
 
                CreateHardDisk(Bstr ("iSCSI"),
1038
 
                               BstrFmt ("%ls|%ls|%ls", server.raw(), target.raw(), lun.raw()),
1039
 
                               hardDisk.asOutParam()));
1040
 
        }
1041
 
        if (FAILED(rc)) break;
1042
 
 
1043
 
        if (!port.isEmpty())
1044
 
            server = BstrFmt ("%ls:%ls", server.raw(), port.raw());
1045
 
 
1046
 
        com::SafeArray <BSTR> names;
1047
 
        com::SafeArray <BSTR> values;
1048
 
 
1049
 
        Bstr ("TargetAddress").detachTo (names.appendedRaw());
1050
 
        server.detachTo (values.appendedRaw());
1051
 
        Bstr ("TargetName").detachTo (names.appendedRaw());
1052
 
        target.detachTo (values.appendedRaw());
1053
 
 
1054
 
        if (!lun.isEmpty())
1055
 
        {
1056
 
            Bstr ("LUN").detachTo (names.appendedRaw());
1057
 
            lun.detachTo (values.appendedRaw());
1058
 
        }
1059
 
        if (!username.isEmpty())
1060
 
        {
1061
 
            Bstr ("InitiatorUsername").detachTo (names.appendedRaw());
1062
 
            username.detachTo (values.appendedRaw());
1063
 
        }
1064
 
        if (!password.isEmpty())
1065
 
        {
1066
 
            Bstr ("InitiatorSecret").detachTo (names.appendedRaw());
1067
 
            password.detachTo (values.appendedRaw());
1068
 
        }
1069
 
 
1070
 
        /// @todo add --initiator option - until that happens rely on the
1071
 
        // defaults of the iSCSI initiator code. Setting it to a constant
1072
 
        // value does more harm than good, as the initiator name is supposed
1073
 
        // to identify a particular initiator uniquely.
1074
 
//        Bstr ("InitiatorName").detachTo (names.appendedRaw());
1075
 
//        Bstr ("iqn.2008-04.com.sun.virtualbox.initiator").detachTo (values.appendedRaw());
1076
 
 
1077
 
        /// @todo add --targetName and --targetPassword options
1078
 
 
1079
 
        if (fIntNet)
1080
 
        {
1081
 
            Bstr ("HostIPStack").detachTo (names.appendedRaw());
1082
 
            Bstr ("0").detachTo (values.appendedRaw());
1083
 
        }
1084
 
 
1085
 
        CHECK_ERROR_BREAK (hardDisk,
1086
 
            SetProperties (ComSafeArrayAsInParam (names),
1087
 
                           ComSafeArrayAsInParam (values)));
1088
 
 
1089
 
        if (DiskType != MediumType_Normal)
1090
 
        {
1091
 
            CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
1092
 
        }
1093
 
 
1094
 
        Bstr guid;
1095
 
        CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
1096
 
        RTPrintf("iSCSI disk created. UUID: %s\n", Utf8Str(guid).raw());
1097
 
    }
1098
 
    while (0);
1099
 
 
1100
 
    return SUCCEEDED(rc) ? 0 : 1;
 
873
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
1101
874
}
1102
875
 
1103
876
static const RTGETOPTDEF g_aShowHardDiskInfoOptions[] =
1150
923
 
1151
924
    ComPtr<IMedium> hardDisk;
1152
925
    bool unknown = false;
1153
 
    /* first guess is that it's a UUID */
1154
 
    Bstr uuid(FilenameOrUuid);
1155
 
    rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
1156
 
    /* no? then it must be a filename */
1157
 
    if (FAILED (rc))
1158
 
    {
1159
 
        rc = a->virtualBox->FindHardDisk(Bstr(FilenameOrUuid), hardDisk.asOutParam());
1160
 
        /* no? well, then it's an unkwnown image */
1161
 
        if (FAILED (rc))
1162
 
        {
1163
 
            rc = a->virtualBox->OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam());
1164
 
            if (rc == VBOX_E_FILE_ERROR)
1165
 
            {
1166
 
                char szFilenameAbs[RTPATH_MAX] = "";
1167
 
                int vrc = RTPathAbs(FilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
1168
 
                if (RT_FAILURE(vrc))
1169
 
                {
1170
 
                    RTPrintf("Cannot convert filename \"%s\" to absolute path\n", FilenameOrUuid);
1171
 
                    return 1;
1172
 
                }
1173
 
                CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam()));
1174
 
            }
1175
 
            else if (FAILED(rc))
1176
 
                CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, false, Bstr(""), false, Bstr(""), hardDisk.asOutParam()));
1177
 
            if (SUCCEEDED (rc))
1178
 
            {
1179
 
                unknown = true;
1180
 
            }
1181
 
        }
1182
 
    }
 
926
 
 
927
    rc = findOrOpenMedium(a, FilenameOrUuid, DeviceType_HardDisk, hardDisk, &unknown);
 
928
    if (FAILED(rc))
 
929
        return 1;
 
930
 
1183
931
    do
1184
932
    {
1185
 
        if (!SUCCEEDED(rc))
1186
 
            break;
1187
 
 
 
933
        Bstr uuid;
1188
934
        hardDisk->COMGETTER(Id)(uuid.asOutParam());
1189
 
        RTPrintf("UUID:                 %s\n", Utf8Str(uuid).raw());
 
935
        RTPrintf("UUID:                 %s\n", Utf8Str(uuid).c_str());
1190
936
 
1191
937
        /* check for accessibility */
1192
938
        /// @todo NEWMEDIA check accessibility of all parents
1193
939
        /// @todo NEWMEDIA print the full state value
1194
940
        MediumState_T state;
1195
 
        CHECK_ERROR_BREAK (hardDisk, RefreshState(&state));
 
941
        CHECK_ERROR_BREAK(hardDisk, RefreshState(&state));
1196
942
        RTPrintf("Accessible:           %s\n", state != MediumState_Inaccessible ? "yes" : "no");
1197
943
 
1198
944
        if (state == MediumState_Inaccessible)
1199
945
        {
1200
946
            Bstr err;
1201
 
            CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
 
947
            CHECK_ERROR_BREAK(hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
1202
948
            RTPrintf("Access Error:         %lS\n", err.raw());
1203
949
        }
1204
950
 
1209
955
            RTPrintf("Description:          %lS\n", description.raw());
1210
956
        }
1211
957
 
1212
 
        ULONG64 logicalSize;
 
958
        LONG64 logicalSize;
1213
959
        hardDisk->COMGETTER(LogicalSize)(&logicalSize);
1214
 
        RTPrintf("Logical size:         %llu MBytes\n", logicalSize);
1215
 
        ULONG64 actualSize;
 
960
        RTPrintf("Logical size:         %lld MBytes\n", logicalSize);
 
961
        LONG64 actualSize;
1216
962
        hardDisk->COMGETTER(Size)(&actualSize);
1217
 
        RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
 
963
        RTPrintf("Current size on disk: %lld MBytes\n", actualSize >> 20);
1218
964
 
1219
965
        ComPtr <IMedium> parent;
1220
 
        hardDisk->COMGETTER(Parent) (parent.asOutParam());
 
966
        hardDisk->COMGETTER(Parent)(parent.asOutParam());
1221
967
 
1222
968
        MediumType_T type;
1223
969
        hardDisk->COMGETTER(Type)(&type);
1239
985
            case MediumType_Shareable:
1240
986
                typeStr = "shareable";
1241
987
                break;
 
988
            case MediumType_Readonly:
 
989
                typeStr = "readonly";
 
990
                break;
 
991
            case MediumType_MultiAttach:
 
992
                typeStr = "multiattach";
 
993
                break;
1242
994
        }
1243
995
        RTPrintf("Type:                 %s\n", typeStr);
1244
996
 
1245
997
        Bstr format;
1246
998
        hardDisk->COMGETTER(Format)(format.asOutParam());
1247
999
        RTPrintf("Storage format:       %lS\n", format.raw());
 
1000
        ULONG variant;
 
1001
        hardDisk->COMGETTER(Variant)(&variant);
 
1002
        const char *variantStr = "unknown";
 
1003
        switch (variant & ~(MediumVariant_Fixed | MediumVariant_Diff))
 
1004
        {
 
1005
            case MediumVariant_VmdkSplit2G:
 
1006
                variantStr = "split2G";
 
1007
                break;
 
1008
            case MediumVariant_VmdkStreamOptimized:
 
1009
                variantStr = "streamOptimized";
 
1010
                break;
 
1011
            case MediumVariant_VmdkESX:
 
1012
                variantStr = "ESX";
 
1013
                break;
 
1014
            case MediumVariant_Standard:
 
1015
                variantStr = "default";
 
1016
                break;
 
1017
        }
 
1018
        const char *variantTypeStr = "dynamic";
 
1019
        if (variant & MediumVariant_Fixed)
 
1020
            variantTypeStr = "fixed";
 
1021
        else if (variant & MediumVariant_Diff)
 
1022
            variantTypeStr = "differencing";
 
1023
        RTPrintf("Format variant:       %s %s\n", variantTypeStr, variantStr);
 
1024
 
 
1025
        /// @todo also dump config parameters (iSCSI)
1248
1026
 
1249
1027
        if (!unknown)
1250
1028
        {
1253
1031
            for (size_t j = 0; j < machineIds.size(); ++ j)
1254
1032
            {
1255
1033
                ComPtr<IMachine> machine;
1256
 
                CHECK_ERROR(a->virtualBox, GetMachine(machineIds[j], machine.asOutParam()));
 
1034
                CHECK_ERROR(a->virtualBox, FindMachine(machineIds[j], machine.asOutParam()));
1257
1035
                ASSERT(machine);
1258
1036
                Bstr name;
1259
1037
                machine->COMGETTER(Name)(name.asOutParam());
1289
1067
    return SUCCEEDED(rc) ? 0 : 1;
1290
1068
}
1291
1069
 
1292
 
static const RTGETOPTDEF g_aOpenMediumOptions[] =
1293
 
{
1294
 
    { "disk",           'd', RTGETOPT_REQ_NOTHING },
1295
 
    { "dvd",            'D', RTGETOPT_REQ_NOTHING },
1296
 
    { "floppy",         'f', RTGETOPT_REQ_NOTHING },
1297
 
    { "--type",         't', RTGETOPT_REQ_STRING },
1298
 
    { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
1299
 
    { "--uuid",         'u', RTGETOPT_REQ_UUID },
1300
 
    { "--parentuuid",   'p', RTGETOPT_REQ_UUID },
1301
 
};
1302
 
 
1303
 
int handleOpenMedium(HandlerArg *a)
1304
 
{
1305
 
    HRESULT rc = S_OK;
1306
 
    int vrc;
1307
 
    enum {
1308
 
        CMD_NONE,
1309
 
        CMD_DISK,
1310
 
        CMD_DVD,
1311
 
        CMD_FLOPPY
1312
 
    } cmd = CMD_NONE;
1313
 
    const char *Filename = NULL;
1314
 
    MediumType_T DiskType = MediumType_Normal;
1315
 
    bool fDiskType = false;
1316
 
    bool fSetImageId = false;
1317
 
    bool fSetParentId = false;
1318
 
    Guid ImageId;
1319
 
    ImageId.clear();
1320
 
    Guid ParentId;
1321
 
    ParentId.clear();
1322
 
 
1323
 
    int c;
1324
 
    RTGETOPTUNION ValueUnion;
1325
 
    RTGETOPTSTATE GetState;
1326
 
    // start at 0 because main() has hacked both the argc and argv given to us
1327
 
    RTGetOptInit(&GetState, a->argc, a->argv, g_aOpenMediumOptions, RT_ELEMENTS(g_aOpenMediumOptions),
1328
 
                 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
1329
 
    while ((c = RTGetOpt(&GetState, &ValueUnion)))
1330
 
    {
1331
 
        switch (c)
1332
 
        {
1333
 
            case 'd':   // disk
1334
 
                if (cmd != CMD_NONE)
1335
 
                    return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1336
 
                cmd = CMD_DISK;
1337
 
                break;
1338
 
 
1339
 
            case 'D':   // DVD
1340
 
                if (cmd != CMD_NONE)
1341
 
                    return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1342
 
                cmd = CMD_DVD;
1343
 
                break;
1344
 
 
1345
 
            case 'f':   // floppy
1346
 
                if (cmd != CMD_NONE)
1347
 
                    return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
1348
 
                cmd = CMD_FLOPPY;
1349
 
                break;
1350
 
 
1351
 
            case 't':   // --type
1352
 
                vrc = parseDiskType(ValueUnion.psz, &DiskType);
1353
 
                if (RT_FAILURE(vrc))
1354
 
                    return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
1355
 
                fDiskType = true;
1356
 
                break;
1357
 
 
1358
 
            case 'u':   // --uuid
1359
 
                ImageId = ValueUnion.Uuid;
1360
 
                fSetImageId = true;
1361
 
                break;
1362
 
 
1363
 
            case 'p':   // --parentuuid
1364
 
                ParentId = ValueUnion.Uuid;
1365
 
                fSetParentId = true;
1366
 
                break;
1367
 
 
1368
 
            case VINF_GETOPT_NOT_OPTION:
1369
 
                if (!Filename)
1370
 
                    Filename = ValueUnion.psz;
1371
 
                else
1372
 
                    return errorSyntax(USAGE_OPENMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
1373
 
                break;
1374
 
 
1375
 
            default:
1376
 
                if (c > 0)
1377
 
                {
1378
 
                    if (RT_C_IS_PRINT(c))
1379
 
                        return errorSyntax(USAGE_OPENMEDIUM, "Invalid option -%c", c);
1380
 
                    else
1381
 
                        return errorSyntax(USAGE_OPENMEDIUM, "Invalid option case %i", c);
1382
 
                }
1383
 
                else if (c == VERR_GETOPT_UNKNOWN_OPTION)
1384
 
                    return errorSyntax(USAGE_OPENMEDIUM, "unknown option: %s\n", ValueUnion.psz);
1385
 
                else if (ValueUnion.pDef)
1386
 
                    return errorSyntax(USAGE_OPENMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
1387
 
                else
1388
 
                    return errorSyntax(USAGE_OPENMEDIUM, "error: %Rrs", c);
1389
 
        }
1390
 
    }
1391
 
 
1392
 
    /* check for required options */
1393
 
    if (cmd == CMD_NONE)
1394
 
        return errorSyntax(USAGE_OPENMEDIUM, "Command variant disk/dvd/floppy required");
1395
 
    if (!Filename)
1396
 
        return errorSyntax(USAGE_OPENMEDIUM, "Disk name required");
1397
 
 
1398
 
    /** @todo remove this hack!
1399
 
     * First try opening the image as is (using the regular API semantics for
1400
 
     * images with relative path or without path), and if that fails with a
1401
 
     * file related error then try it again with what the client thinks the
1402
 
     * relative path would mean. Requires doing the command twice in certain
1403
 
     * cases. This is an ugly hack and needs to be removed whevever we have a
1404
 
     * chance to clean up the API semantics. */
1405
 
    if (cmd == CMD_DISK)
1406
 
    {
1407
 
        ComPtr<IMedium> hardDisk;
1408
 
        Bstr ImageIdStr = BstrFmt("%RTuuid", &ImageId);
1409
 
        Bstr ParentIdStr = BstrFmt("%RTuuid", &ParentId);
1410
 
        rc = a->virtualBox->OpenHardDisk(Bstr(Filename), AccessMode_ReadWrite, fSetImageId, ImageIdStr, fSetParentId, ParentIdStr, hardDisk.asOutParam());
1411
 
        if (rc == VBOX_E_FILE_ERROR)
1412
 
        {
1413
 
            char szFilenameAbs[RTPATH_MAX] = "";
1414
 
            int irc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
1415
 
            if (RT_FAILURE(irc))
1416
 
            {
1417
 
                RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
1418
 
                return 1;
1419
 
            }
1420
 
            CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, fSetImageId, ImageIdStr, fSetParentId, ParentIdStr, hardDisk.asOutParam()));
1421
 
        }
1422
 
        else if (FAILED(rc))
1423
 
            CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(Filename), AccessMode_ReadWrite, fSetImageId, ImageIdStr, fSetParentId, ParentIdStr, hardDisk.asOutParam()));
1424
 
        if (SUCCEEDED(rc) && hardDisk)
1425
 
        {
1426
 
            /* change the type if requested */
1427
 
            if (DiskType != MediumType_Normal)
1428
 
            {
1429
 
                CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
1430
 
            }
1431
 
        }
1432
 
    }
1433
 
    else if (cmd == CMD_DVD)
1434
 
    {
1435
 
        if (fDiskType || fSetParentId)
1436
 
            return errorSyntax(USAGE_OPENMEDIUM, "Invalid option for DVD images");
1437
 
        Bstr ImageIdStr = BstrFmt("%RTuuid", &ImageId);
1438
 
        ComPtr<IMedium> dvdImage;
1439
 
        rc = a->virtualBox->OpenDVDImage(Bstr(Filename), ImageIdStr, dvdImage.asOutParam());
1440
 
        if (rc == VBOX_E_FILE_ERROR)
1441
 
        {
1442
 
            char szFilenameAbs[RTPATH_MAX] = "";
1443
 
            int irc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
1444
 
            if (RT_FAILURE(irc))
1445
 
            {
1446
 
                RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
1447
 
                return 1;
1448
 
            }
1449
 
            CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(szFilenameAbs), ImageIdStr, dvdImage.asOutParam()));
1450
 
        }
1451
 
        else if (FAILED(rc))
1452
 
            CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(Filename), ImageIdStr, dvdImage.asOutParam()));
1453
 
    }
1454
 
    else if (cmd == CMD_FLOPPY)
1455
 
    {
1456
 
        if (fDiskType || fSetImageId || fSetParentId)
1457
 
            return errorSyntax(USAGE_OPENMEDIUM, "Invalid option for floppy images");
1458
 
        Bstr ImageIdStr = BstrFmt("%RTuuid", &ImageId);
1459
 
        ComPtr<IMedium> floppyImage;
1460
 
        rc = a->virtualBox->OpenFloppyImage(Bstr(Filename), ImageIdStr, floppyImage.asOutParam());
1461
 
        if (rc == VBOX_E_FILE_ERROR)
1462
 
        {
1463
 
            char szFilenameAbs[RTPATH_MAX] = "";
1464
 
            int irc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
1465
 
            if (RT_FAILURE(irc))
1466
 
            {
1467
 
                RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
1468
 
                return 1;
1469
 
            }
1470
 
            CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(szFilenameAbs), ImageIdStr, floppyImage.asOutParam()));
1471
 
        }
1472
 
        else if (FAILED(rc))
1473
 
            CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(Filename), ImageIdStr, floppyImage.asOutParam()));
1474
 
    }
1475
 
 
1476
 
    return SUCCEEDED(rc) ? 0 : 1;
1477
 
}
1478
 
 
1479
1070
static const RTGETOPTDEF g_aCloseMediumOptions[] =
1480
1071
{
1481
1072
    { "disk",           'd', RTGETOPT_REQ_NOTHING },
1560
1151
 
1561
1152
    ComPtr<IMedium> medium;
1562
1153
 
1563
 
    /* first guess is that it's a UUID */
1564
 
    Bstr uuid(FilenameOrUuid);
1565
 
 
1566
1154
    if (cmd == CMD_DISK)
1567
 
    {
1568
 
        rc = a->virtualBox->GetHardDisk(uuid, medium.asOutParam());
1569
 
        /* not a UUID or not registered? Then it must be a filename */
1570
 
        if (!medium)
1571
 
        {
1572
 
            CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(FilenameOrUuid), medium.asOutParam()));
1573
 
        }
1574
 
    }
1575
 
    else
1576
 
    if (cmd == CMD_DVD)
1577
 
    {
1578
 
        rc = a->virtualBox->GetDVDImage(uuid, medium.asOutParam());
1579
 
        /* not a UUID or not registered? Then it must be a filename */
1580
 
        if (!medium)
1581
 
        {
1582
 
            CHECK_ERROR(a->virtualBox, FindDVDImage(Bstr(FilenameOrUuid), medium.asOutParam()));
1583
 
        }
1584
 
    }
1585
 
    else
1586
 
    if (cmd == CMD_FLOPPY)
1587
 
    {
1588
 
        rc = a->virtualBox->GetFloppyImage(uuid, medium.asOutParam());
1589
 
        /* not a UUID or not registered? Then it must be a filename */
1590
 
        if (!medium)
1591
 
        {
1592
 
            CHECK_ERROR(a->virtualBox, FindFloppyImage(Bstr(FilenameOrUuid), medium.asOutParam()));
1593
 
        }
1594
 
    }
 
1155
        rc = findMedium(a, FilenameOrUuid, DeviceType_HardDisk, false /* fSilent */, medium);
 
1156
    else if (cmd == CMD_DVD)
 
1157
        rc = findMedium(a, FilenameOrUuid, DeviceType_DVD, false /* fSilent */, medium);
 
1158
    else if (cmd == CMD_FLOPPY)
 
1159
        rc = findMedium(a, FilenameOrUuid, DeviceType_Floppy, false /* fSilent */, medium);
1595
1160
 
1596
1161
    if (SUCCEEDED(rc) && medium)
1597
1162
    {
1606
1171
                {
1607
1172
                    com::ProgressErrorInfo info(progress);
1608
1173
                    if (info.isBasicAvailable())
1609
 
                        RTPrintf("Error: failed to delete medium. Error message: %lS\n", info.getText().raw());
 
1174
                        RTMsgError("Failed to delete medium. Error message: %lS", info.getText().raw());
1610
1175
                    else
1611
 
                        RTPrintf("Error: failed to delete medium. No error message available!\n");
 
1176
                        RTMsgError("Failed to delete medium. No error message available!");
1612
1177
                }
1613
1178
            }
1614
1179
            else
1615
 
                RTPrintf("Error: failed to delete medium. Error code %Rrc\n", rc);
 
1180
                RTMsgError("Failed to delete medium. Error code %Rrc", rc);
1616
1181
        }
1617
1182
        CHECK_ERROR(medium, Close());
1618
1183
    }