VirtualBox

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

Last change on this file since 35273 was 35273, checked in by vboxsync, 13 years ago

IExtPackFile,IExtPackManager: Added progress and display info to the Install and Uninstall methods. No progress object will be returned in 4.0.0 as that is too risky.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use