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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
*******************************************************************************/
25
25
#include <VBox/com/com.h>
26
26
#include <VBox/com/string.h>
 
27
#include <VBox/com/array.h>
27
28
#include <VBox/com/ErrorInfo.h>
28
29
#include <VBox/com/errorprint.h>
29
30
 
35
36
#include "VBoxManage.h"
36
37
using namespace com;
37
38
 
 
39
/**
 
40
 * Helper function used with "VBoxManage snapshot ... dump". Gets called to find the
 
41
 * snapshot in the machine's snapshot tree that uses a particular diff image child of
 
42
 * a medium.
 
43
 * Horribly inefficient since we keep re-querying the snapshots tree for each image,
 
44
 * but this is for quick debugging only.
 
45
 * @param pMedium
 
46
 * @param pThisSnapshot
 
47
 * @param pCurrentSnapshot
 
48
 * @param uMediumLevel
 
49
 * @param uSnapshotLevel
 
50
 * @return
 
51
 */
 
52
bool FindAndPrintSnapshotUsingMedium(ComPtr<IMedium> &pMedium,
 
53
                                     ComPtr<ISnapshot> &pThisSnapshot,
 
54
                                     ComPtr<ISnapshot> &pCurrentSnapshot,
 
55
                                     uint32_t uMediumLevel,
 
56
                                     uint32_t uSnapshotLevel)
 
57
{
 
58
    HRESULT rc;
 
59
 
 
60
    do
 
61
    {
 
62
        // get snapshot machine so we can figure out which diff image this created
 
63
        ComPtr<IMachine> pSnapshotMachine;
 
64
        CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Machine)(pSnapshotMachine.asOutParam()));
 
65
 
 
66
        // get media attachments
 
67
        SafeIfaceArray<IMediumAttachment> aAttachments;
 
68
        CHECK_ERROR_BREAK(pSnapshotMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments)));
 
69
 
 
70
        for (uint32_t i = 0;
 
71
             i < aAttachments.size();
 
72
             ++i)
 
73
        {
 
74
            ComPtr<IMediumAttachment> pAttach(aAttachments[i]);
 
75
            DeviceType_T type;
 
76
            CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type));
 
77
            if (type == DeviceType_HardDisk)
 
78
            {
 
79
                ComPtr<IMedium> pMediumInSnapshot;
 
80
                CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pMediumInSnapshot.asOutParam()));
 
81
 
 
82
                if (pMediumInSnapshot == pMedium)
 
83
                {
 
84
                    // get snapshot name
 
85
                    Bstr bstrSnapshotName;
 
86
                    CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Name)(bstrSnapshotName.asOutParam()));
 
87
 
 
88
                    RTPrintf("%*s  \"%ls\"%s\n",
 
89
                             50 + uSnapshotLevel * 2, "",            // indent
 
90
                             bstrSnapshotName.raw(),
 
91
                             (pThisSnapshot == pCurrentSnapshot) ? " (CURSNAP)" : "");
 
92
                    return true;        // found
 
93
                }
 
94
            }
 
95
        }
 
96
 
 
97
        // not found: then recurse into child snapshots
 
98
        SafeIfaceArray<ISnapshot> aSnapshots;
 
99
        CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Children)(ComSafeArrayAsOutParam(aSnapshots)));
 
100
 
 
101
        for (uint32_t i = 0;
 
102
            i < aSnapshots.size();
 
103
            ++i)
 
104
        {
 
105
            ComPtr<ISnapshot> pChild(aSnapshots[i]);
 
106
            if (FindAndPrintSnapshotUsingMedium(pMedium,
 
107
                                                pChild,
 
108
                                                pCurrentSnapshot,
 
109
                                                uMediumLevel,
 
110
                                                uSnapshotLevel + 1))
 
111
                // found:
 
112
                break;
 
113
        }
 
114
    } while (0);
 
115
 
 
116
    return false;
 
117
}
 
118
 
 
119
/**
 
120
 * Helper function used with "VBoxManage snapshot ... dump". Called from DumpSnapshot()
 
121
 * for each hard disk attachment found in a virtual machine. This then writes out the
 
122
 * root (base) medium for that hard disk attachment and recurses into the children
 
123
 * tree of that medium, correlating it with the snapshots of the machine.
 
124
 * @param pCurrentStateMedium constant, the medium listed in the current machine data (latest diff image).
 
125
 * @param pMedium variant, initially the base medium, then a child of the base medium when recursing.
 
126
 * @param pRootSnapshot constant, the root snapshot of the machine, if any; this then looks into the child snapshots.
 
127
 * @param pCurrentSnapshot constant, the machine's current snapshot (so we can mark it in the output).
 
128
 * @param uLevel variant, the recursion level for output indentation.
 
129
 */
 
130
void DumpMediumWithChildren(ComPtr<IMedium> &pCurrentStateMedium,
 
131
                            ComPtr<IMedium> &pMedium,
 
132
                            ComPtr<ISnapshot> &pRootSnapshot,
 
133
                            ComPtr<ISnapshot> &pCurrentSnapshot,
 
134
                            uint32_t uLevel)
 
135
{
 
136
    HRESULT rc;
 
137
    do
 
138
    {
 
139
        // print this medium
 
140
        Bstr bstrMediumName;
 
141
        CHECK_ERROR_BREAK(pMedium, COMGETTER(Name)(bstrMediumName.asOutParam()));
 
142
        RTPrintf("%*s  \"%ls\"%s\n",
 
143
                 uLevel * 2, "",            // indent
 
144
                 bstrMediumName.raw(),
 
145
                 (pCurrentStateMedium == pMedium) ? " (CURSTATE)" : "");
 
146
 
 
147
        // find and print the snapshot that uses this particular medium (diff image)
 
148
        FindAndPrintSnapshotUsingMedium(pMedium, pRootSnapshot, pCurrentSnapshot, uLevel, 0);
 
149
 
 
150
        // recurse into children
 
151
        SafeIfaceArray<IMedium> aChildren;
 
152
        CHECK_ERROR_BREAK(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(aChildren)));
 
153
        for (uint32_t i = 0;
 
154
             i < aChildren.size();
 
155
             ++i)
 
156
        {
 
157
            ComPtr<IMedium> pChild(aChildren[i]);
 
158
            DumpMediumWithChildren(pCurrentStateMedium, pChild, pRootSnapshot, pCurrentSnapshot, uLevel + 1);
 
159
        }
 
160
    } while (0);
 
161
}
 
162
 
 
163
/**
 
164
 * Implementation for "VBoxManage snapshot ... dump". This goes thru the machine's
 
165
 * medium attachments and calls DumpMediumWithChildren() for each hard disk medium found,
 
166
 * which then dumps the parent/child tree of that medium together with the corresponding
 
167
 * snapshots.
 
168
 * @param pMachine Machine to dump snapshots for.
 
169
 */
 
170
void DumpSnapshot(ComPtr<IMachine> &pMachine)
 
171
{
 
172
    HRESULT rc;
 
173
 
 
174
    do
 
175
    {
 
176
        // get root snapshot
 
177
        ComPtr<ISnapshot> pSnapshot;
 
178
        CHECK_ERROR_BREAK(pMachine, GetSnapshot(Bstr(""), pSnapshot.asOutParam()));
 
179
 
 
180
        // get current snapshot
 
181
        ComPtr<ISnapshot> pCurrentSnapshot;
 
182
        CHECK_ERROR_BREAK(pMachine, COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam()));
 
183
 
 
184
        // get media attachments
 
185
        SafeIfaceArray<IMediumAttachment> aAttachments;
 
186
        CHECK_ERROR_BREAK(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments)));
 
187
        for (uint32_t i = 0;
 
188
             i < aAttachments.size();
 
189
             ++i)
 
190
        {
 
191
            ComPtr<IMediumAttachment> pAttach(aAttachments[i]);
 
192
            DeviceType_T type;
 
193
            CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type));
 
194
            if (type == DeviceType_HardDisk)
 
195
            {
 
196
                ComPtr<IMedium> pCurrentStateMedium;
 
197
                CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pCurrentStateMedium.asOutParam()));
 
198
 
 
199
                ComPtr<IMedium> pBaseMedium;
 
200
                CHECK_ERROR_BREAK(pCurrentStateMedium, COMGETTER(Base)(pBaseMedium.asOutParam()));
 
201
 
 
202
                Bstr bstrBaseMediumName;
 
203
                CHECK_ERROR_BREAK(pBaseMedium, COMGETTER(Name)(bstrBaseMediumName.asOutParam()));
 
204
 
 
205
                RTPrintf("[%RI32] Images and snapshots for medium \"%ls\"\n", i, bstrBaseMediumName.raw());
 
206
 
 
207
                DumpMediumWithChildren(pCurrentStateMedium,
 
208
                                       pBaseMedium,
 
209
                                       pSnapshot,
 
210
                                       pCurrentSnapshot,
 
211
                                       0);
 
212
            }
 
213
        }
 
214
    } while (0);
 
215
}
 
216
 
 
217
/**
 
218
 * Implementation for all VBoxManage snapshot ... subcommands.
 
219
 * @param a
 
220
 * @return
 
221
 */
38
222
int handleSnapshot(HandlerArg *a)
39
223
{
40
224
    HRESULT rc;
44
228
        return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
45
229
 
46
230
    /* the first argument must be the VM */
47
 
    ComPtr<IMachine> machine;
 
231
    Bstr bstrMachine(a->argv[0]);
 
232
    ComPtr<IMachine> pMachine;
48
233
    /* assume it's a UUID */
49
 
    rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
50
 
    if (FAILED(rc) || !machine)
 
234
    rc = a->virtualBox->GetMachine(bstrMachine, pMachine.asOutParam());
 
235
    if (FAILED(rc) || !pMachine)
51
236
    {
52
237
        /* must be a name */
53
 
        CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
 
238
        CHECK_ERROR(a->virtualBox, FindMachine(bstrMachine, pMachine.asOutParam()));
54
239
    }
55
 
    if (!machine)
 
240
    if (!pMachine)
56
241
        return 1;
57
 
    Bstr guid;
58
 
    machine->COMGETTER(Id)(guid.asOutParam());
 
242
    Bstr guidMachine;
 
243
    pMachine->COMGETTER(Id)(guidMachine.asOutParam());
59
244
 
60
245
    do
61
246
    {
62
247
        /* we have to open a session for this task. First try an existing session */
63
 
        rc = a->virtualBox->OpenExistingSession(a->session, guid);
 
248
        rc = a->virtualBox->OpenExistingSession(a->session, guidMachine);
64
249
        if (FAILED(rc))
65
 
            CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
 
250
            CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guidMachine));
66
251
        ComPtr<IConsole> console;
67
252
        CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
68
253
 
69
254
        /* switch based on the command */
 
255
        bool fDelete = false, fRestore = false;
70
256
        if (!strcmp(a->argv[1], "take"))
71
257
        {
72
258
            /* there must be a name */
77
263
                break;
78
264
            }
79
265
            Bstr name(a->argv[2]);
80
 
            if ((a->argc > 3) && (   (a->argc != 5)
81
 
                                  || (   strcmp(a->argv[3], "--description")
82
 
                                      && strcmp(a->argv[3], "-description")
83
 
                                      && strcmp(a->argv[3], "-desc"))))
84
 
            {
85
 
                errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");
86
 
                rc = E_FAIL;
87
 
                break;
88
 
            }
 
266
 
 
267
            /* parse the optional arguments */
89
268
            Bstr desc;
90
 
            if (a->argc == 5)
91
 
                desc = a->argv[4];
 
269
            bool fPause = false;
 
270
            static const RTGETOPTDEF s_aTakeOptions[] =
 
271
            {
 
272
                { "--description", 'd', RTGETOPT_REQ_STRING },
 
273
                { "-description",  'd', RTGETOPT_REQ_STRING },
 
274
                { "-desc",         'd', RTGETOPT_REQ_STRING },
 
275
                { "--pause",       'p', RTGETOPT_REQ_NOTHING }
 
276
            };
 
277
            RTGETOPTSTATE GetOptState;
 
278
            RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTakeOptions, RT_ELEMENTS(s_aTakeOptions), 3, 0 /*fFlags*/);
 
279
            int ch;
 
280
            RTGETOPTUNION Value;
 
281
            while (   SUCCEEDED(rc)
 
282
                   && (ch = RTGetOpt(&GetOptState, &Value)))
 
283
            {
 
284
                switch (ch)
 
285
                {
 
286
                    case 'p':
 
287
                        fPause = true;
 
288
                        break;
 
289
 
 
290
                    case 'd':
 
291
                        desc = Value.psz;
 
292
                        break;
 
293
 
 
294
                    default:
 
295
                        errorGetOpt(USAGE_SNAPSHOT, ch, &Value);
 
296
                        rc = E_FAIL;
 
297
                        break;
 
298
                }
 
299
            }
 
300
            if (FAILED(rc))
 
301
                break;
 
302
 
 
303
            if (fPause)
 
304
            {
 
305
                MachineState_T machineState;
 
306
                CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
 
307
                if (machineState == MachineState_Running)
 
308
                    CHECK_ERROR_BREAK(console, Pause());
 
309
                else
 
310
                    fPause = false;
 
311
            }
 
312
 
92
313
            ComPtr<IProgress> progress;
93
314
            CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
94
315
 
95
 
            showProgress(progress);
96
 
            LONG iRc;
97
 
            progress->COMGETTER(ResultCode)(&iRc);
98
 
            rc = iRc;
 
316
            rc = showProgress(progress);
99
317
            if (FAILED(rc))
100
318
            {
101
319
                com::ProgressErrorInfo info(progress);
104
322
                else
105
323
                    RTPrintf("Error: failed to take snapshot. No error message available!\n");
106
324
            }
 
325
 
 
326
            if (fPause)
 
327
            {
 
328
                MachineState_T machineState;
 
329
                CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
 
330
                if (machineState == MachineState_Paused)
 
331
                {
 
332
                    if (SUCCEEDED(rc))
 
333
                        CHECK_ERROR_BREAK(console, Resume());
 
334
                    else
 
335
                        console->Resume();
 
336
                }
 
337
            }
107
338
        }
108
 
        else if (!strcmp(a->argv[1], "discard"))
 
339
        else if (    (fDelete = !strcmp(a->argv[1], "delete"))
 
340
                  || (fRestore = !strcmp(a->argv[1], "restore"))
 
341
                )
109
342
        {
110
343
            /* exactly one parameter: snapshot name */
111
344
            if (a->argc != 3)
115
348
                break;
116
349
            }
117
350
 
118
 
            ComPtr<ISnapshot> snapshot;
 
351
            ComPtr<ISnapshot> pSnapshot;
119
352
 
120
353
            /* assume it's a UUID */
121
 
            Bstr guid(a->argv[2]);
122
 
            if (!guid.isEmpty())
 
354
            Bstr guidSnap(a->argv[2]);
 
355
            if (!guidSnap.isEmpty())
123
356
            {
124
 
                CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
 
357
                CHECK_ERROR_BREAK(pMachine, GetSnapshot(guidSnap, pSnapshot.asOutParam()));
125
358
            }
126
359
            else
127
360
            {
128
361
                /* then it must be a name */
129
 
                CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
130
 
            }
131
 
 
132
 
            snapshot->COMGETTER(Id)(guid.asOutParam());
133
 
 
134
 
            ComPtr<IProgress> progress;
135
 
            CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));
136
 
 
137
 
            showProgress(progress);
138
 
            LONG iRc;
139
 
            progress->COMGETTER(ResultCode)(&iRc);
140
 
            rc = iRc;
141
 
            if (FAILED(rc))
142
 
            {
143
 
                com::ProgressErrorInfo info(progress);
144
 
                if (info.isBasicAvailable())
145
 
                    RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
146
 
                else
147
 
                    RTPrintf("Error: failed to discard snapshot. No error message available!\n");
148
 
            }
149
 
        }
150
 
        else if (!strcmp(a->argv[1], "discardcurrent"))
151
 
        {
152
 
            if (   (a->argc != 3)
153
 
                || (   strcmp(a->argv[2], "--state")
154
 
                    && strcmp(a->argv[2], "-state")
155
 
                    && strcmp(a->argv[2], "--all")
156
 
                    && strcmp(a->argv[2], "-all")))
157
 
            {
158
 
                errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
159
 
                rc = E_FAIL;
160
 
                break;
161
 
            }
162
 
            bool fAll = false;
163
 
            if (   !strcmp(a->argv[2], "--all")
164
 
                || !strcmp(a->argv[2], "-all"))
165
 
                fAll = true;
166
 
 
167
 
            ComPtr<IProgress> progress;
168
 
 
169
 
            if (fAll)
170
 
            {
171
 
                CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));
 
362
                CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), pSnapshot.asOutParam()));
 
363
                pSnapshot->COMGETTER(Id)(guidSnap.asOutParam());
 
364
            }
 
365
 
 
366
            ComPtr<IProgress> pProgress;
 
367
            if (fDelete)
 
368
            {
 
369
                CHECK_ERROR_BREAK(console, DeleteSnapshot(guidSnap, pProgress.asOutParam()));
172
370
            }
173
371
            else
174
372
            {
175
 
                CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));
 
373
                // must be restore
 
374
                CHECK_ERROR_BREAK(console, RestoreSnapshot(pSnapshot, pProgress.asOutParam()));
176
375
            }
177
376
 
178
 
            showProgress(progress);
179
 
            LONG iRc;
180
 
            progress->COMGETTER(ResultCode)(&iRc);
181
 
            rc = iRc;
 
377
            rc = showProgress(pProgress);
182
378
            if (FAILED(rc))
183
379
            {
184
 
                com::ProgressErrorInfo info(progress);
 
380
                com::ProgressErrorInfo info(pProgress);
185
381
                if (info.isBasicAvailable())
186
 
                    RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());
 
382
                    RTPrintf("Error: snapshot operation failed. Error message: %lS\n", info.getText().raw());
187
383
                else
188
 
                    RTPrintf("Error: failed to discard. No error message available!\n");
 
384
                    RTPrintf("Error: snapshot operation failed. No error message available!\n");
189
385
            }
190
 
 
191
386
        }
192
387
        else if (!strcmp(a->argv[1], "edit"))
193
388
        {
203
398
            if (   !strcmp(a->argv[2], "--current")
204
399
                || !strcmp(a->argv[2], "-current"))
205
400
            {
206
 
                CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
 
401
                CHECK_ERROR_BREAK(pMachine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
207
402
            }
208
403
            else
209
404
            {
210
405
                /* assume it's a UUID */
211
 
                Bstr guid(a->argv[2]);
212
 
                if (!guid.isEmpty())
 
406
                Bstr guidSnap(a->argv[2]);
 
407
                if (!guidSnap.isEmpty())
213
408
                {
214
 
                    CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
 
409
                    CHECK_ERROR_BREAK(pMachine, GetSnapshot(guidSnap, snapshot.asOutParam()));
215
410
                }
216
411
                else
217
412
                {
218
413
                    /* then it must be a name */
219
 
                    CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
 
414
                    CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
220
415
                }
221
416
            }
222
417
 
271
466
            ComPtr<ISnapshot> snapshot;
272
467
 
273
468
            /* assume it's a UUID */
274
 
            Bstr guid(a->argv[2]);
275
 
            if (!guid.isEmpty())
 
469
            Bstr guidSnap(a->argv[2]);
 
470
            if (!guidSnap.isEmpty())
276
471
            {
277
 
                CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
 
472
                CHECK_ERROR_BREAK(pMachine, GetSnapshot(guidSnap, snapshot.asOutParam()));
278
473
            }
279
474
            else
280
475
            {
281
476
                /* then it must be a name */
282
 
                CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
 
477
                CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
283
478
            }
284
479
 
285
480
            /* get the machine of the given snapshot */
286
 
            ComPtr<IMachine> machine;
287
 
            snapshot->COMGETTER(Machine)(machine.asOutParam());
288
 
            showVMInfo(a->virtualBox, machine, VMINFO_NONE, console);
 
481
            ComPtr<IMachine> pMachine2;
 
482
            snapshot->COMGETTER(Machine)(pMachine2.asOutParam());
 
483
            showVMInfo(a->virtualBox, pMachine2, VMINFO_NONE, console);
 
484
        }
 
485
        else if (!strcmp(a->argv[1], "dump"))          // undocumented parameter to debug snapshot info
 
486
        {
 
487
            DumpSnapshot(pMachine);
289
488
        }
290
489
        else
291
490
        {