VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp@ 31482

Last change on this file since 31482 was 31333, checked in by vboxsync, 15 years ago

Main: rework new implementation of Machine::Unregister() and Machine::Delete() to be more flexible and still easy to use

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.3 KB
Line 
1/* $Id: VBoxManageMisc.cpp 31333 2010-08-03 13:00:54Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#ifndef VBOX_ONLY_DOCS
23#include <VBox/com/com.h>
24#include <VBox/com/string.h>
25#include <VBox/com/Guid.h>
26#include <VBox/com/array.h>
27#include <VBox/com/ErrorInfo.h>
28#include <VBox/com/errorprint.h>
29#include <VBox/com/EventQueue.h>
30
31#include <VBox/com/VirtualBox.h>
32
33#include <vector>
34#include <list>
35#endif /* !VBOX_ONLY_DOCS */
36
37#include <iprt/asm.h>
38#include <iprt/buildconfig.h>
39#include <iprt/cidr.h>
40#include <iprt/ctype.h>
41#include <iprt/dir.h>
42#include <iprt/env.h>
43#include <VBox/err.h>
44#include <iprt/file.h>
45#include <iprt/initterm.h>
46#include <iprt/param.h>
47#include <iprt/path.h>
48#include <iprt/stream.h>
49#include <iprt/string.h>
50#include <iprt/stdarg.h>
51#include <iprt/thread.h>
52#include <iprt/uuid.h>
53#include <iprt/getopt.h>
54#include <iprt/ctype.h>
55#include <VBox/version.h>
56#include <VBox/log.h>
57
58#include "VBoxManage.h"
59
60using namespace com;
61
62
63
64int handleRegisterVM(HandlerArg *a)
65{
66 HRESULT rc;
67
68 if (a->argc != 1)
69 return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
70
71 ComPtr<IMachine> machine;
72 /** @todo Ugly hack to get both the API interpretation of relative paths
73 * and the client's interpretation of relative paths. Remove after the API
74 * has been redesigned. */
75 rc = a->virtualBox->OpenMachine(Bstr(a->argv[0]), machine.asOutParam());
76 if (rc == VBOX_E_FILE_ERROR)
77 {
78 char szVMFileAbs[RTPATH_MAX] = "";
79 int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs));
80 if (RT_FAILURE(vrc))
81 {
82 RTPrintf("Cannot convert filename \"%s\" to absolute path\n", a->argv[0]);
83 return 1;
84 }
85 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs), machine.asOutParam()));
86 }
87 else if (FAILED(rc))
88 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
89 if (SUCCEEDED(rc))
90 {
91 ASSERT(machine);
92 CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
93 }
94 return SUCCEEDED(rc) ? 0 : 1;
95}
96
97static const RTGETOPTDEF g_aUnregisterVMOptions[] =
98{
99 { "--delete", 'd', RTGETOPT_REQ_NOTHING },
100 { "-delete", 'd', RTGETOPT_REQ_NOTHING }, // deprecated
101};
102
103int handleUnregisterVM(HandlerArg *a)
104{
105 HRESULT rc;
106 const char *VMName = NULL;
107 bool fDelete = false;
108
109 int c;
110 RTGETOPTUNION ValueUnion;
111 RTGETOPTSTATE GetState;
112 // start at 0 because main() has hacked both the argc and argv given to us
113 RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions),
114 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
115 while ((c = RTGetOpt(&GetState, &ValueUnion)))
116 {
117 switch (c)
118 {
119 case 'd': // --delete
120 fDelete = true;
121 break;
122
123 case VINF_GETOPT_NOT_OPTION:
124 if (!VMName)
125 VMName = ValueUnion.psz;
126 else
127 return errorSyntax(USAGE_UNREGISTERVM, "Invalid parameter '%s'", ValueUnion.psz);
128 break;
129
130 default:
131 if (c > 0)
132 {
133 if (RT_C_IS_PRINT(c))
134 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option -%c", c);
135 else
136 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option case %i", c);
137 }
138 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
139 return errorSyntax(USAGE_UNREGISTERVM, "unknown option: %s\n", ValueUnion.psz);
140 else if (ValueUnion.pDef)
141 return errorSyntax(USAGE_UNREGISTERVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
142 else
143 return errorSyntax(USAGE_UNREGISTERVM, "error: %Rrs", c);
144 }
145 }
146
147 /* check for required options */
148 if (!VMName)
149 return errorSyntax(USAGE_UNREGISTERVM, "VM name required");
150
151 ComPtr<IMachine> machine;
152 /* assume it's a UUID */
153 rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
154 if (FAILED(rc) || !machine)
155 {
156 /* must be a name */
157 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
158 }
159 if (machine)
160 {
161 SafeIfaceArray<IMedium> aMedia;
162 CleanupMode_T cleanupMode = CleanupMode_DetachAllReturnNone;
163 if (fDelete)
164 cleanupMode = CleanupMode_DetachAllReturnHardDisksOnly;
165 CHECK_ERROR(machine, Unregister(cleanupMode,
166 ComSafeArrayAsOutParam(aMedia)));
167 if (SUCCEEDED(rc))
168 {
169 if (fDelete)
170 {
171 ComPtr<IProgress> pProgress;
172 CHECK_ERROR(machine, Delete(ComSafeArrayAsInParam(aMedia), pProgress.asOutParam()));
173 CHECK_ERROR(pProgress, WaitForCompletion(-1));
174 }
175 }
176 }
177 return SUCCEEDED(rc) ? 0 : 1;
178}
179
180int handleCreateVM(HandlerArg *a)
181{
182 HRESULT rc;
183 Bstr baseFolder;
184 Bstr settingsFile;
185 Bstr name;
186 Bstr osTypeId;
187 RTUUID id;
188 bool fRegister = false;
189
190 RTUuidClear(&id);
191 for (int i = 0; i < a->argc; i++)
192 {
193 if ( !strcmp(a->argv[i], "--basefolder")
194 || !strcmp(a->argv[i], "-basefolder"))
195 {
196 if (a->argc <= i + 1)
197 return errorArgument("Missing argument to '%s'", a->argv[i]);
198 i++;
199 baseFolder = a->argv[i];
200 }
201 else if ( !strcmp(a->argv[i], "--settingsfile")
202 || !strcmp(a->argv[i], "-settingsfile"))
203 {
204 if (a->argc <= i + 1)
205 return errorArgument("Missing argument to '%s'", a->argv[i]);
206 i++;
207 settingsFile = a->argv[i];
208 }
209 else if ( !strcmp(a->argv[i], "--name")
210 || !strcmp(a->argv[i], "-name"))
211 {
212 if (a->argc <= i + 1)
213 return errorArgument("Missing argument to '%s'", a->argv[i]);
214 i++;
215 name = a->argv[i];
216 }
217 else if ( !strcmp(a->argv[i], "--ostype")
218 || !strcmp(a->argv[i], "-ostype"))
219 {
220 if (a->argc <= i + 1)
221 return errorArgument("Missing argument to '%s'", a->argv[i]);
222 i++;
223 osTypeId = a->argv[i];
224 }
225 else if ( !strcmp(a->argv[i], "--uuid")
226 || !strcmp(a->argv[i], "-uuid"))
227 {
228 if (a->argc <= i + 1)
229 return errorArgument("Missing argument to '%s'", a->argv[i]);
230 i++;
231 if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
232 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
233 }
234 else if ( !strcmp(a->argv[i], "--register")
235 || !strcmp(a->argv[i], "-register"))
236 {
237 fRegister = true;
238 }
239 else
240 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
241 }
242 if (!name)
243 return errorSyntax(USAGE_CREATEVM, "Parameter --name is required");
244
245 if (!baseFolder.isEmpty() && !settingsFile.isEmpty())
246 return errorSyntax(USAGE_CREATEVM, "Cannot specify both --basefolder and --settingsfile together");
247
248 do
249 {
250 ComPtr<IMachine> machine;
251
252 if (settingsFile.isEmpty())
253 CHECK_ERROR_BREAK(a->virtualBox,
254 CreateMachine(name, osTypeId, baseFolder, Guid(id).toUtf16(), FALSE, machine.asOutParam()));
255 else
256 CHECK_ERROR_BREAK(a->virtualBox,
257 CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id).toUtf16(), machine.asOutParam()));
258
259 CHECK_ERROR_BREAK(machine, SaveSettings());
260 if (fRegister)
261 {
262 CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
263 }
264 Bstr uuid;
265 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
266 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
267 RTPrintf("Virtual machine '%ls' is created%s.\n"
268 "UUID: %s\n"
269 "Settings file: '%ls'\n",
270 name.raw(), fRegister ? " and registered" : "",
271 Utf8Str(uuid).raw(), settingsFile.raw());
272 }
273 while (0);
274
275 return SUCCEEDED(rc) ? 0 : 1;
276}
277
278int handleStartVM(HandlerArg *a)
279{
280 HRESULT rc;
281 const char *VMName = NULL;
282 Bstr sessionType = "gui";
283
284 static const RTGETOPTDEF s_aStartVMOptions[] =
285 {
286 { "--type", 't', RTGETOPT_REQ_STRING },
287 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
288 };
289 int c;
290 RTGETOPTUNION ValueUnion;
291 RTGETOPTSTATE GetState;
292 // start at 0 because main() has hacked both the argc and argv given to us
293 RTGetOptInit(&GetState, a->argc, a->argv, s_aStartVMOptions, RT_ELEMENTS(s_aStartVMOptions),
294 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
295 while ((c = RTGetOpt(&GetState, &ValueUnion)))
296 {
297 switch (c)
298 {
299 case 't': // --type
300 if (!RTStrICmp(ValueUnion.psz, "gui"))
301 {
302 sessionType = "gui";
303 }
304#ifdef VBOX_WITH_VBOXSDL
305 else if (!RTStrICmp(ValueUnion.psz, "sdl"))
306 {
307 sessionType = "sdl";
308 }
309#endif
310#ifdef VBOX_WITH_VRDP
311 else if (!RTStrICmp(ValueUnion.psz, "vrdp"))
312 {
313 sessionType = "vrdp";
314 }
315#endif
316#ifdef VBOX_WITH_HEADLESS
317 else if (!RTStrICmp(ValueUnion.psz, "capture"))
318 {
319 sessionType = "capture";
320 }
321 else if (!RTStrICmp(ValueUnion.psz, "headless"))
322 {
323 sessionType = "headless";
324 }
325#endif
326 else
327 return errorArgument("Invalid session type '%s'", ValueUnion.psz);
328 break;
329
330 case VINF_GETOPT_NOT_OPTION:
331 if (!VMName)
332 VMName = ValueUnion.psz;
333 else
334 return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
335 break;
336
337 default:
338 if (c > 0)
339 {
340 if (RT_C_IS_PRINT(c))
341 return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
342 else
343 return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
344 }
345 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
346 return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
347 else if (ValueUnion.pDef)
348 return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
349 else
350 return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
351 }
352 }
353
354 /* check for required options */
355 if (!VMName)
356 return errorSyntax(USAGE_STARTVM, "VM name required");
357
358 ComPtr<IMachine> machine;
359 /* assume it's a UUID */
360 rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
361 if (FAILED(rc) || !machine)
362 {
363 /* must be a name */
364 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
365 }
366 if (machine)
367 {
368 Bstr env;
369#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
370 /* make sure the VM process will start on the same display as VBoxManage */
371 Utf8Str str;
372 const char *pszDisplay = RTEnvGet("DISPLAY");
373 if (pszDisplay)
374 str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
375 const char *pszXAuth = RTEnvGet("XAUTHORITY");
376 if (pszXAuth)
377 str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
378 env = str;
379#endif
380 ComPtr<IProgress> progress;
381 CHECK_ERROR_RET(machine, LaunchVMProcess(a->session, sessionType, env, progress.asOutParam()), rc);
382 RTPrintf("Waiting for the VM to power on...\n");
383 CHECK_ERROR_RET(progress, WaitForCompletion(-1), 1);
384
385 BOOL completed;
386 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
387 ASSERT(completed);
388
389 LONG iRc;
390 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
391 if (FAILED(iRc))
392 {
393 ComPtr<IVirtualBoxErrorInfo> errorInfo;
394 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
395 ErrorInfo info(errorInfo, COM_IIDOF(IVirtualBoxErrorInfo));
396 com::GluePrintErrorInfo(info);
397 }
398 else
399 {
400 RTPrintf("VM has been successfully started.\n");
401 }
402 }
403
404 /* it's important to always close sessions */
405 a->session->UnlockMachine();
406
407 return SUCCEEDED(rc) ? 0 : 1;
408}
409
410int handleDiscardState(HandlerArg *a)
411{
412 HRESULT rc;
413
414 if (a->argc != 1)
415 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
416
417 ComPtr<IMachine> machine;
418 /* assume it's a UUID */
419 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
420 if (FAILED(rc) || !machine)
421 {
422 /* must be a name */
423 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
424 }
425 if (machine)
426 {
427 do
428 {
429 /* we have to open a session for this task */
430 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
431 do
432 {
433 ComPtr<IConsole> console;
434 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
435 CHECK_ERROR_BREAK(console, DiscardSavedState());
436 } while (0);
437 CHECK_ERROR_BREAK(a->session, UnlockMachine());
438 } while (0);
439 }
440
441 return SUCCEEDED(rc) ? 0 : 1;
442}
443
444int handleAdoptState(HandlerArg *a)
445{
446 HRESULT rc;
447
448 if (a->argc != 2)
449 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
450
451 ComPtr<IMachine> machine;
452 /* assume it's a UUID */
453 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
454 if (FAILED(rc) || !machine)
455 {
456 /* must be a name */
457 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
458 }
459 if (machine)
460 {
461 do
462 {
463 /* we have to open a session for this task */
464 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
465 do
466 {
467 ComPtr<IConsole> console;
468 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
469 CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(a->argv[1])));
470 } while (0);
471 CHECK_ERROR_BREAK(a->session, UnlockMachine());
472 } while (0);
473 }
474
475 return SUCCEEDED(rc) ? 0 : 1;
476}
477
478int handleGetExtraData(HandlerArg *a)
479{
480 HRESULT rc = S_OK;
481
482 if (a->argc != 2)
483 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
484
485 /* global data? */
486 if (!strcmp(a->argv[0], "global"))
487 {
488 /* enumeration? */
489 if (!strcmp(a->argv[1], "enumerate"))
490 {
491 SafeArray<BSTR> aKeys;
492 CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
493
494 for (size_t i = 0;
495 i < aKeys.size();
496 ++i)
497 {
498 Bstr bstrKey(aKeys[i]);
499 Bstr bstrValue;
500 CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey, bstrValue.asOutParam()));
501
502 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
503 }
504 }
505 else
506 {
507 Bstr value;
508 CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
509 if (!value.isEmpty())
510 RTPrintf("Value: %lS\n", value.raw());
511 else
512 RTPrintf("No value set!\n");
513 }
514 }
515 else
516 {
517 ComPtr<IMachine> machine;
518 /* assume it's a UUID */
519 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
520 if (FAILED(rc) || !machine)
521 {
522 /* must be a name */
523 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
524 }
525 if (machine)
526 {
527 /* enumeration? */
528 if (!strcmp(a->argv[1], "enumerate"))
529 {
530 SafeArray<BSTR> aKeys;
531 CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
532
533 for (size_t i = 0;
534 i < aKeys.size();
535 ++i)
536 {
537 Bstr bstrKey(aKeys[i]);
538 Bstr bstrValue;
539 CHECK_ERROR(machine, GetExtraData(bstrKey, bstrValue.asOutParam()));
540
541 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
542 }
543 }
544 else
545 {
546 Bstr value;
547 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
548 if (!value.isEmpty())
549 RTPrintf("Value: %lS\n", value.raw());
550 else
551 RTPrintf("No value set!\n");
552 }
553 }
554 }
555 return SUCCEEDED(rc) ? 0 : 1;
556}
557
558int handleSetExtraData(HandlerArg *a)
559{
560 HRESULT rc = S_OK;
561
562 if (a->argc < 2)
563 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
564
565 /* global data? */
566 if (!strcmp(a->argv[0], "global"))
567 {
568 if (a->argc < 3)
569 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
570 else if (a->argc == 3)
571 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
572 else
573 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
574 }
575 else
576 {
577 ComPtr<IMachine> machine;
578 /* assume it's a UUID */
579 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
580 if (FAILED(rc) || !machine)
581 {
582 /* must be a name */
583 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
584 }
585 if (machine)
586 {
587 if (a->argc < 3)
588 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
589 else if (a->argc == 3)
590 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
591 else
592 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
593 }
594 }
595 return SUCCEEDED(rc) ? 0 : 1;
596}
597
598int handleSetProperty(HandlerArg *a)
599{
600 HRESULT rc;
601
602 /* there must be two arguments: property name and value */
603 if (a->argc != 2)
604 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
605
606 ComPtr<ISystemProperties> systemProperties;
607 a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
608
609 if (!strcmp(a->argv[0], "hdfolder"))
610 {
611 /* reset to default? */
612 if (!strcmp(a->argv[1], "default"))
613 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
614 else
615 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
616 }
617 else if (!strcmp(a->argv[0], "machinefolder"))
618 {
619 /* reset to default? */
620 if (!strcmp(a->argv[1], "default"))
621 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
622 else
623 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
624 }
625 else if (!strcmp(a->argv[0], "vrdpauthlibrary"))
626 {
627 /* reset to default? */
628 if (!strcmp(a->argv[1], "default"))
629 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
630 else
631 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
632 }
633 else if (!strcmp(a->argv[0], "websrvauthlibrary"))
634 {
635 /* reset to default? */
636 if (!strcmp(a->argv[1], "default"))
637 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
638 else
639 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
640 }
641 else if (!strcmp(a->argv[0], "loghistorycount"))
642 {
643 uint32_t uVal;
644 int vrc;
645 vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
646 if (vrc != VINF_SUCCESS)
647 return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
648 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
649 }
650 else
651 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
652
653 return SUCCEEDED(rc) ? 0 : 1;
654}
655
656int handleSharedFolder(HandlerArg *a)
657{
658 HRESULT rc;
659
660 /* we need at least a command and target */
661 if (a->argc < 2)
662 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
663
664 ComPtr<IMachine> machine;
665 /* assume it's a UUID */
666 rc = a->virtualBox->GetMachine(Bstr(a->argv[1]), machine.asOutParam());
667 if (FAILED(rc) || !machine)
668 {
669 /* must be a name */
670 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
671 }
672 if (!machine)
673 return 1;
674
675 if (!strcmp(a->argv[0], "add"))
676 {
677 /* we need at least four more parameters */
678 if (a->argc < 5)
679 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
680
681 char *name = NULL;
682 char *hostpath = NULL;
683 bool fTransient = false;
684 bool fWritable = true;
685 bool fAutoMount = false;
686
687 for (int i = 2; i < a->argc; i++)
688 {
689 if ( !strcmp(a->argv[i], "--name")
690 || !strcmp(a->argv[i], "-name"))
691 {
692 if (a->argc <= i + 1 || !*a->argv[i+1])
693 return errorArgument("Missing argument to '%s'", a->argv[i]);
694 i++;
695 name = a->argv[i];
696 }
697 else if ( !strcmp(a->argv[i], "--hostpath")
698 || !strcmp(a->argv[i], "-hostpath"))
699 {
700 if (a->argc <= i + 1 || !*a->argv[i+1])
701 return errorArgument("Missing argument to '%s'", a->argv[i]);
702 i++;
703 hostpath = a->argv[i];
704 }
705 else if ( !strcmp(a->argv[i], "--readonly")
706 || !strcmp(a->argv[i], "-readonly"))
707 {
708 fWritable = false;
709 }
710 else if ( !strcmp(a->argv[i], "--transient")
711 || !strcmp(a->argv[i], "-transient"))
712 {
713 fTransient = true;
714 }
715 else if ( !strcmp(a->argv[i], "--automount")
716 || !strcmp(a->argv[i], "-automount"))
717 {
718 fAutoMount = true;
719 }
720 else
721 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
722 }
723
724 if (NULL != strstr(name, " "))
725 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
726
727 /* required arguments */
728 if (!name || !hostpath)
729 {
730 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
731 }
732
733 if (fTransient)
734 {
735 ComPtr <IConsole> console;
736
737 /* open an existing session for the VM */
738 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
739 /* get the session machine */
740 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
741 /* get the session console */
742 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
743
744 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath),
745 fWritable, fAutoMount));
746 if (console)
747 a->session->UnlockMachine();
748 }
749 else
750 {
751 /* open a session for the VM */
752 SessionType_T st;
753 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
754
755 /* get the mutable session machine */
756 a->session->COMGETTER(Machine)(machine.asOutParam());
757
758 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath),
759 fWritable, fAutoMount));
760 if (SUCCEEDED(rc))
761 CHECK_ERROR(machine, SaveSettings());
762
763 a->session->UnlockMachine();
764 }
765 }
766 else if (!strcmp(a->argv[0], "remove"))
767 {
768 /* we need at least two more parameters */
769 if (a->argc < 3)
770 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
771
772 char *name = NULL;
773 bool fTransient = false;
774
775 for (int i = 2; i < a->argc; i++)
776 {
777 if ( !strcmp(a->argv[i], "--name")
778 || !strcmp(a->argv[i], "-name"))
779 {
780 if (a->argc <= i + 1 || !*a->argv[i+1])
781 return errorArgument("Missing argument to '%s'", a->argv[i]);
782 i++;
783 name = a->argv[i];
784 }
785 else if ( !strcmp(a->argv[i], "--transient")
786 || !strcmp(a->argv[i], "-transient"))
787 {
788 fTransient = true;
789 }
790 else
791 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
792 }
793
794 /* required arguments */
795 if (!name)
796 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
797
798 if (fTransient)
799 {
800 ComPtr <IConsole> console;
801
802 /* open an existing session for the VM */
803 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
804 /* get the session machine */
805 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
806 /* get the session console */
807 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
808
809 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
810
811 if (console)
812 a->session->UnlockMachine();
813 }
814 else
815 {
816 /* open a session for the VM */
817 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
818
819 /* get the mutable session machine */
820 a->session->COMGETTER(Machine)(machine.asOutParam());
821
822 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
823
824 /* commit and close the session */
825 CHECK_ERROR(machine, SaveSettings());
826 a->session->UnlockMachine();
827 }
828 }
829 else
830 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
831
832 return 0;
833}
834
835int handleVMStatistics(HandlerArg *a)
836{
837 HRESULT rc;
838
839 /* at least one option: the UUID or name of the VM */
840 if (a->argc < 1)
841 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
842
843 /* try to find the given machine */
844 ComPtr<IMachine> machine;
845 Bstr uuid(a->argv[0]);
846 if (!Guid(a->argv[0]).isEmpty())
847 CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
848 else
849 {
850 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
851 if (SUCCEEDED(rc))
852 machine->COMGETTER(Id)(uuid.asOutParam());
853 }
854 if (FAILED(rc))
855 return 1;
856
857 /* parse arguments. */
858 bool fReset = false;
859 bool fWithDescriptions = false;
860 const char *pszPattern = NULL; /* all */
861 for (int i = 1; i < a->argc; i++)
862 {
863 if ( !strcmp(a->argv[i], "--pattern")
864 || !strcmp(a->argv[i], "-pattern"))
865 {
866 if (pszPattern)
867 return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
868 if (i + 1 >= a->argc)
869 return errorArgument("Missing argument to '%s'", a->argv[i]);
870 pszPattern = a->argv[++i];
871 }
872 else if ( !strcmp(a->argv[i], "--descriptions")
873 || !strcmp(a->argv[i], "-descriptions"))
874 fWithDescriptions = true;
875 /* add: --file <filename> and --formatted */
876 else if ( !strcmp(a->argv[i], "--reset")
877 || !strcmp(a->argv[i], "-reset"))
878 fReset = true;
879 else
880 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
881 }
882 if (fReset && fWithDescriptions)
883 return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
884
885
886 /* open an existing session for the VM. */
887 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
888 if (SUCCEEDED(rc))
889 {
890 /* get the session console. */
891 ComPtr <IConsole> console;
892 CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
893 if (SUCCEEDED(rc))
894 {
895 /* get the machine debugger. */
896 ComPtr <IMachineDebugger> debugger;
897 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
898 if (SUCCEEDED(rc))
899 {
900 if (fReset)
901 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
902 else
903 {
904 Bstr stats;
905 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
906 if (SUCCEEDED(rc))
907 {
908 /* if (fFormatted)
909 { big mess }
910 else
911 */
912 RTPrintf("%ls\n", stats.raw());
913 }
914 }
915 }
916 a->session->UnlockMachine();
917 }
918 }
919
920 return SUCCEEDED(rc) ? 0 : 1;
921}
922
Note: See TracBrowser for help on using the repository browser.

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