VirtualBox

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

Last change on this file since 31273 was 31220, checked in by vboxsync, 15 years ago

Main: rename IConsole::forgetSavedState() to discardSavedState()

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