VirtualBox

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

Last change on this file since 32962 was 32718, checked in by vboxsync, 14 years ago

com/string: Remove bool conversion operator and other convenience error operators. They are hiding programming errors (like incorrect empty string checks, and in one case a free of the wrong pointer).

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