VirtualBox

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

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

Main/Machine+Console: Extend the scope of the power up progress object, and collect error information from the frontend. Much better error signalling when the VM is started via openRemoteSession. Adjusted documentation accordingly, and finally fixed the incomprehensible messages emitted by VBoxManage startvm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use