VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp@ 32712

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

VBoxManage: forgot the help for guestproperty and guestcontrol; enable the latter for VBOX_ONLY_DOCS=1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.9 KB
Line 
1/* $Id: VBoxManageGuestProp.cpp 32712 2010-09-23 12:16:51Z vboxsync $ */
2/** @file
3 * VBoxManage - Implementation of guestproperty command.
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.215389.xyz. 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#include "VBoxManage.h"
23
24#ifndef VBOX_ONLY_DOCS
25
26#include <VBox/com/com.h>
27#include <VBox/com/string.h>
28#include <VBox/com/array.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/errorprint.h>
31
32#include <VBox/com/VirtualBox.h>
33#include <VBox/com/EventQueue.h>
34
35#include <VBox/log.h>
36#include <iprt/asm.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39#include <iprt/time.h>
40#include <iprt/thread.h>
41
42#ifdef USE_XPCOM_QUEUE
43# include <sys/select.h>
44# include <errno.h>
45#endif
46
47#ifdef RT_OS_DARWIN
48# include <CoreFoundation/CFRunLoop.h>
49#endif
50
51using namespace com;
52
53#endif /* !VBOX_ONLY_DOCS */
54
55void usageGuestProperty(PRTSTREAM pStrm)
56{
57 RTStrmPrintf(pStrm,
58 "VBoxManage guestproperty get <vmname>|<uuid>\n"
59 " <property> [--verbose]\n"
60 "\n");
61 RTStrmPrintf(pStrm,
62 "VBoxManage guestproperty set <vmname>|<uuid>\n"
63 " <property> [<value> [--flags <flags>]]\n"
64 "\n");
65 RTStrmPrintf(pStrm,
66 "VBoxManage guestproperty enumerate <vmname>|<uuid>\n"
67 " [--patterns <patterns>]\n"
68 "\n");
69 RTStrmPrintf(pStrm,
70 "VBoxManage guestproperty wait <vmname>|<uuid> <patterns>\n"
71 " [--timeout <msec>] [--fail-on-timeout]\n"
72 "\n");
73}
74
75#ifndef VBOX_ONLY_DOCS
76
77static int handleGetGuestProperty(HandlerArg *a)
78{
79 HRESULT rc = S_OK;
80
81 bool verbose = false;
82 if ( a->argc == 3
83 && ( !strcmp(a->argv[2], "--verbose")
84 || !strcmp(a->argv[2], "-verbose")))
85 verbose = true;
86 else if (a->argc != 2)
87 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
88
89 ComPtr<IMachine> machine;
90 /* assume it's a UUID */
91 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
92 if (FAILED(rc) || !machine)
93 {
94 /* must be a name */
95 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
96 }
97 if (machine)
98 {
99 /* open a session for the VM - new or existing */
100 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
101
102 /* get the mutable session machine */
103 a->session->COMGETTER(Machine)(machine.asOutParam());
104
105 Bstr value;
106 LONG64 i64Timestamp;
107 Bstr flags;
108 CHECK_ERROR(machine, GetGuestProperty(Bstr(a->argv[1]), value.asOutParam(),
109 &i64Timestamp, flags.asOutParam()));
110 if (!value)
111 RTPrintf("No value set!\n");
112 if (value)
113 RTPrintf("Value: %lS\n", value.raw());
114 if (value && verbose)
115 {
116 RTPrintf("Timestamp: %lld\n", i64Timestamp);
117 RTPrintf("Flags: %lS\n", flags.raw());
118 }
119 }
120 return SUCCEEDED(rc) ? 0 : 1;
121}
122
123static int handleSetGuestProperty(HandlerArg *a)
124{
125 HRESULT rc = S_OK;
126
127 /*
128 * Check the syntax. We can deduce the correct syntax from the number of
129 * arguments.
130 */
131 bool usageOK = true;
132 const char *pszName = NULL;
133 const char *pszValue = NULL;
134 const char *pszFlags = NULL;
135 if (a->argc == 3)
136 pszValue = a->argv[2];
137 else if (a->argc == 4)
138 usageOK = false;
139 else if (a->argc == 5)
140 {
141 pszValue = a->argv[2];
142 if ( strcmp(a->argv[3], "--flags")
143 && strcmp(a->argv[3], "-flags"))
144 usageOK = false;
145 pszFlags = a->argv[4];
146 }
147 else if (a->argc != 2)
148 usageOK = false;
149 if (!usageOK)
150 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
151 /* This is always needed. */
152 pszName = a->argv[1];
153
154 ComPtr<IMachine> machine;
155 /* assume it's a UUID */
156 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
157 if (FAILED(rc) || !machine)
158 {
159 /* must be a name */
160 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
161 }
162 if (machine)
163 {
164 /* open a session for the VM - new or existing */
165 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
166
167 /* get the mutable session machine */
168 a->session->COMGETTER(Machine)(machine.asOutParam());
169
170 if (!pszValue && !pszFlags)
171 CHECK_ERROR(machine, SetGuestPropertyValue(Bstr(pszName), Bstr("")));
172 else if (!pszFlags)
173 CHECK_ERROR(machine, SetGuestPropertyValue(Bstr(pszName), Bstr(pszValue)));
174 else
175 CHECK_ERROR(machine, SetGuestProperty(Bstr(pszName), Bstr(pszValue), Bstr(pszFlags)));
176
177 if (SUCCEEDED(rc))
178 CHECK_ERROR(machine, SaveSettings());
179
180 a->session->UnlockMachine();
181 }
182 return SUCCEEDED(rc) ? 0 : 1;
183}
184
185/**
186 * Enumerates the properties in the guest property store.
187 *
188 * @returns 0 on success, 1 on failure
189 * @note see the command line API description for parameters
190 */
191static int handleEnumGuestProperty(HandlerArg *a)
192{
193 /*
194 * Check the syntax. We can deduce the correct syntax from the number of
195 * arguments.
196 */
197 if ( a->argc < 1
198 || a->argc == 2
199 || ( a->argc > 3
200 && strcmp(a->argv[1], "--patterns")
201 && strcmp(a->argv[1], "-patterns")))
202 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
203
204 /*
205 * Pack the patterns
206 */
207 Utf8Str Utf8Patterns(a->argc > 2 ? a->argv[2] : "");
208 for (int i = 3; i < a->argc; ++i)
209 Utf8Patterns = Utf8StrFmt ("%s,%s", Utf8Patterns.c_str(), a->argv[i]);
210
211 /*
212 * Make the actual call to Main.
213 */
214 ComPtr<IMachine> machine;
215 /* assume it's a UUID */
216 HRESULT rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
217 if (FAILED(rc) || !machine)
218 {
219 /* must be a name */
220 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
221 }
222 if (machine)
223 {
224 /* open a session for the VM - new or existing */
225 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
226
227 /* get the mutable session machine */
228 a->session->COMGETTER(Machine)(machine.asOutParam());
229
230 com::SafeArray<BSTR> names;
231 com::SafeArray<BSTR> values;
232 com::SafeArray<LONG64> timestamps;
233 com::SafeArray<BSTR> flags;
234 CHECK_ERROR(machine, EnumerateGuestProperties(Bstr(Utf8Patterns),
235 ComSafeArrayAsOutParam(names),
236 ComSafeArrayAsOutParam(values),
237 ComSafeArrayAsOutParam(timestamps),
238 ComSafeArrayAsOutParam(flags)));
239 if (SUCCEEDED(rc))
240 {
241 if (names.size() == 0)
242 RTPrintf("No properties found.\n");
243 for (unsigned i = 0; i < names.size(); ++i)
244 RTPrintf("Name: %lS, value: %lS, timestamp: %lld, flags: %lS\n",
245 names[i], values[i], timestamps[i], flags[i]);
246 }
247 }
248 return SUCCEEDED(rc) ? 0 : 1;
249}
250
251/**
252 * Enumerates the properties in the guest property store.
253 *
254 * @returns 0 on success, 1 on failure
255 * @note see the command line API description for parameters
256 */
257static int handleWaitGuestProperty(HandlerArg *a)
258{
259 /*
260 * Handle arguments
261 */
262 bool fFailOnTimeout = false;
263 const char *pszPatterns = NULL;
264 uint32_t cMsTimeout = RT_INDEFINITE_WAIT;
265 bool usageOK = true;
266 if (a->argc < 2)
267 usageOK = false;
268 else
269 pszPatterns = a->argv[1];
270 ComPtr<IMachine> machine;
271 /* assume it's a UUID */
272 HRESULT rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
273 if (FAILED(rc) || !machine)
274 {
275 /* must be a name */
276 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
277 }
278 if (!machine)
279 usageOK = false;
280 for (int i = 2; usageOK && i < a->argc; ++i)
281 {
282 if ( !strcmp(a->argv[i], "--timeout")
283 || !strcmp(a->argv[i], "-timeout"))
284 {
285 if ( i + 1 >= a->argc
286 || RTStrToUInt32Full(a->argv[i + 1], 10, &cMsTimeout) != VINF_SUCCESS)
287 usageOK = false;
288 else
289 ++i;
290 }
291 else if (!strcmp(a->argv[i], "--fail-on-timeout"))
292 fFailOnTimeout = true;
293 else
294 usageOK = false;
295 }
296 if (!usageOK)
297 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
298
299 /*
300 * Set up the event listener and wait until found match or timeout.
301 */
302 Bstr aMachStrGuid;
303 machine->COMGETTER(Id)(aMachStrGuid.asOutParam());
304 Guid aMachGuid(aMachStrGuid);
305 ComPtr<IEventSource> es;
306 CHECK_ERROR(a->virtualBox, COMGETTER(EventSource)(es.asOutParam()));
307 ComPtr<IEventListener> listener;
308 CHECK_ERROR(es, CreateListener(listener.asOutParam()));
309 com::SafeArray <VBoxEventType_T> eventTypes(1);
310 eventTypes.push_back(VBoxEventType_OnGuestPropertyChanged);
311 CHECK_ERROR(es, RegisterListener(listener, ComSafeArrayAsInParam(eventTypes), false));
312
313 uint64_t u64Started = RTTimeMilliTS();
314 bool fSignalled = false;
315 do
316 {
317 unsigned cMsWait;
318 if (cMsTimeout == RT_INDEFINITE_WAIT)
319 cMsWait = 1000;
320 else
321 {
322 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
323 if (cMsElapsed >= cMsTimeout)
324 break; /* timed out */
325 cMsWait = RT_MIN(1000, cMsTimeout - (uint32_t)cMsElapsed);
326 }
327
328 ComPtr<IEvent> ev;
329 rc = es->GetEvent(listener, cMsWait, ev.asOutParam());
330 if (ev)
331 {
332 VBoxEventType_T aType;
333 rc = ev->COMGETTER(Type)(&aType);
334 switch (aType)
335 {
336 case VBoxEventType_OnGuestPropertyChanged:
337 {
338 ComPtr<IGuestPropertyChangedEvent> gpcev = ev;
339 Assert(gpcev);
340 Bstr aNextStrGuid;
341 gpcev->COMGETTER(MachineId)(aNextStrGuid.asOutParam());
342 if (aMachGuid != Guid(aNextStrGuid))
343 continue;
344 Bstr aNextName;
345 gpcev->COMGETTER(Name)(aNextName.asOutParam());
346 if (RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
347 Utf8Str(aNextName).c_str(), RTSTR_MAX, NULL))
348 {
349 Bstr aNextValue, aNextFlags;
350 gpcev->COMGETTER(Value)(aNextValue.asOutParam());
351 gpcev->COMGETTER(Flags)(aNextFlags.asOutParam());
352 RTPrintf("Name: %lS, value: %lS, flags: %lS\n",
353 aNextName.raw(), aNextValue.raw(), aNextFlags.raw());
354 fSignalled = true;
355 }
356 break;
357 }
358 default:
359 AssertFailed();
360 }
361 }
362 } while (!fSignalled);
363
364 es->UnregisterListener(listener);
365
366 int rcRet = 0;
367 if (!fSignalled)
368 {
369 RTMsgError("Time out or interruption while waiting for a notification.");
370 if (fFailOnTimeout)
371 rcRet = 2;
372 }
373 return rcRet;
374}
375
376/**
377 * Access the guest property store.
378 *
379 * @returns 0 on success, 1 on failure
380 * @note see the command line API description for parameters
381 */
382int handleGuestProperty(HandlerArg *a)
383{
384 HandlerArg arg = *a;
385 arg.argc = a->argc - 1;
386 arg.argv = a->argv + 1;
387
388 if (a->argc == 0)
389 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
390
391 /* switch (cmd) */
392 if (strcmp(a->argv[0], "get") == 0)
393 return handleGetGuestProperty(&arg);
394 if (strcmp(a->argv[0], "set") == 0)
395 return handleSetGuestProperty(&arg);
396 if (strcmp(a->argv[0], "enumerate") == 0)
397 return handleEnumGuestProperty(&arg);
398 if (strcmp(a->argv[0], "wait") == 0)
399 return handleWaitGuestProperty(&arg);
400
401 /* default: */
402 return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
403}
404
405#endif /* !VBOX_ONLY_DOCS */
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