VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp@ 4071

Last change on this file since 4071 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
1/** @file
2 *
3 * VBox frontends: VBoxManage (command-line interface):
4 * VBoxInternalManage
5 *
6 * VBoxInternalManage used to be a second CLI for doing special tricks,
7 * not intended for general usage, only for assisting VBox developers.
8 * It is now integrated into VBoxManage.
9 */
10
11/*
12 * Copyright (C) 2006-2007 innotek GmbH
13 *
14 * This file is part of VirtualBox Open Source Edition (OSE), as
15 * available from http://www.virtualbox.org. This file is free software;
16 * you can redistribute it and/or modify it under the terms of the GNU
17 * General Public License as published by the Free Software Foundation,
18 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
19 * distribution. VirtualBox OSE is distributed in the hope that it will
20 * be useful, but WITHOUT ANY WARRANTY of any kind.
21 */
22
23
24
25/*******************************************************************************
26* Header Files *
27*******************************************************************************/
28#include <VBox/com/com.h>
29#include <VBox/com/string.h>
30#include <VBox/com/Guid.h>
31#include <VBox/com/ErrorInfo.h>
32
33#include <VBox/com/VirtualBox.h>
34
35#include <iprt/runtime.h>
36#include <iprt/stream.h>
37#include <iprt/string.h>
38#include <iprt/uuid.h>
39#include <VBox/err.h>
40
41#include <VBox/VBoxHDD.h>
42
43#include "VBoxManage.h"
44
45#ifndef VBOX_OSE
46HRESULT CmdListPartitions(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
47HRESULT CmdCreateRawVMDK(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
48#endif /* !VBOX_OSE */
49
50using namespace com;
51
52/** flag whether we're in internal mode */
53bool fInternalMode;
54
55/**
56 * Print the usage info.
57 */
58void printUsageInternal(USAGECATEGORY u64Cmd)
59{
60 RTPrintf("Usage: VBoxManage internalcommands <command> [command arguments]\n"
61 "\n"
62 "Commands:\n"
63 "\n"
64 "%s%s%s%s%s"
65 "WARNING: This is a development tool and shall only be used to analyse\n"
66 " problems. It is completely unsupported and will change in\n"
67 " incompatible ways without warning.\n",
68 (u64Cmd & USAGE_LOADSYMS) ?
69 " loadsyms <vmname>|<uuid> <symfile> [delta] [module] [module address]\n"
70 " This will instruct DBGF to load the given symbolfile\n"
71 " during initialization.\n"
72 "\n"
73 : "",
74 (u64Cmd & USAGE_UNLOADSYMS) ?
75 " unloadsyms <vmname>|<uuid> <symfile>\n"
76 " Removes <symfile> from the list of symbol files that\n"
77 " should be loaded during DBF initialization.\n"
78 "\n"
79 : "",
80 (u64Cmd & USAGE_SETVDIUUID) ?
81 " setvdiuuid <filepath>\n"
82 " Assigns a new UUID to the given VDI file. This way, multiple copies\n"
83 " of VDI containers can be registered.\n"
84 "\n"
85 : "",
86 (u64Cmd & USAGE_LISTPARTITIONS) ?
87 " listpartitions -rawdisk <diskname>\n"
88 " Lists all partitions on <diskname>.\n"
89 "\n"
90 : "",
91 (u64Cmd & USAGE_CREATERAWVMDK) ?
92 " createrawvmdk -filename <filename> -rawdisk <diskname>\n"
93 " [-partitions <list of partition numbers> [-mbr <filename>] ]\n"
94 " [-register] [-relative]\n"
95 " Creates a new VMDK image which gives access to an entite host disk (if\n"
96 " the parameter -partitions is not specified) or some partitions of a\n"
97 " host disk. If access to individual partitions is granted, then the\n"
98 " parameter -mbr can be used to specify an alternative MBR to be used\n"
99 " (the partitioning information in the MBR file is ignored).\n"
100 " The diskname is on Linux e.g. /dev/sda, and on Windows e.g.\n"
101 " \\\\.\\PhysicalDisk0).\n"
102 " On Linux host the parameter -relative causes a VMDK file to be created\n"
103 " which refers to individual partitions instead to the entire disk.\n"
104 " Optionally the created image can be immediately registered.\n"
105 " The necessary partition numbers can be queried with\n"
106 " VBoxManage internalcommands listpartitions\n"
107 "\n"
108 : ""
109 );
110}
111
112/** @todo this is no longer necessary, we can enumerate extra data */
113/**
114 * Finds a new unique key name.
115 *
116 * I don't think this is 100% race condition proof, but we assumes
117 * the user is not trying to push this point.
118 *
119 * @returns Result from the insert.
120 * @param pMachine The Machine object.
121 * @param pszKeyBase The base key.
122 * @param rKey Reference to the string object in which we will return the key.
123 */
124static HRESULT NewUniqueKey(ComPtr<IMachine> pMachine, const char *pszKeyBase, Utf8Str &rKey)
125{
126 Bstr Keys;
127 HRESULT hrc = pMachine->GetExtraData(Bstr(pszKeyBase), Keys.asOutParam());
128 if (FAILED(hrc))
129 return hrc;
130
131 /* if there are no keys, it's simple. */
132 if (Keys.isEmpty())
133 {
134 rKey = "1";
135 return pMachine->SetExtraData(Bstr(pszKeyBase), Bstr("1"));
136 }
137
138 /* find a unique number - brute force rulez. */
139 Utf8Str KeysUtf8(Keys);
140 const char *pszKeys = RTStrStripL(KeysUtf8.raw());
141 for (unsigned i = 1; i < 1000000; i++)
142 {
143 char szKey[32];
144 size_t cchKey = RTStrPrintf(szKey, sizeof(szKey), "%#x", i);
145 const char *psz = strstr(pszKeys, szKey);
146 while (psz)
147 {
148 if ( ( psz == pszKeys
149 || psz[-1] == ' ')
150 && ( psz[cchKey] == ' '
151 || !psz[cchKey])
152 )
153 break;
154 psz = strstr(psz + cchKey, szKey);
155 }
156 if (!psz)
157 {
158 rKey = szKey;
159 Utf8StrFmt NewKeysUtf8("%s %s", pszKeys, szKey);
160 return pMachine->SetExtraData(Bstr(pszKeyBase), Bstr(NewKeysUtf8));
161 }
162 }
163 RTPrintf("Error: Cannot find unique key for '%s'!\n", pszKeyBase);
164 return E_FAIL;
165}
166
167
168#if 0
169/**
170 * Remove a key.
171 *
172 * I don't think this isn't 100% race condition proof, but we assumes
173 * the user is not trying to push this point.
174 *
175 * @returns Result from the insert.
176 * @param pMachine The machine object.
177 * @param pszKeyBase The base key.
178 * @param pszKey The key to remove.
179 */
180static HRESULT RemoveKey(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey)
181{
182 Bstr Keys;
183 HRESULT hrc = pMachine->GetExtraData(Bstr(pszKeyBase), Keys.asOutParam());
184 if (FAILED(hrc))
185 return hrc;
186
187 /* if there are no keys, it's simple. */
188 if (Keys.isEmpty())
189 return S_OK;
190
191 char *pszKeys;
192 int rc = RTStrUcs2ToUtf8(&pszKeys, Keys.raw());
193 if (VBOX_SUCCESS(rc))
194 {
195 /* locate it */
196 size_t cchKey = strlen(pszKey);
197 char *psz = strstr(pszKeys, pszKey);
198 while (psz)
199 {
200 if ( ( psz == pszKeys
201 || psz[-1] == ' ')
202 && ( psz[cchKey] == ' '
203 || !psz[cchKey])
204 )
205 break;
206 psz = strstr(psz + cchKey, pszKey);
207 }
208 if (psz)
209 {
210 /* remove it */
211 char *pszNext = RTStrStripL(psz + cchKey);
212 if (*pszNext)
213 memmove(psz, pszNext, strlen(pszNext) + 1);
214 else
215 *psz = '\0';
216 psz = RTStrStrip(pszKeys);
217
218 /* update */
219 hrc = pMachine->SetExtraData(Bstr(pszKeyBase), Bstr(psz));
220 }
221
222 RTStrFree(pszKeys);
223 return hrc;
224 }
225 else
226 RTPrintf("error: failed to delete key '%s' from '%s', string conversion error %Vrc!\n",
227 pszKey, pszKeyBase, rc);
228
229 return E_FAIL;
230}
231#endif
232
233
234/**
235 * Sets a key value, does necessary error bitching.
236 *
237 * @returns COM status code.
238 * @param pMachine The Machine object.
239 * @param pszKeyBase The key base.
240 * @param pszKey The key.
241 * @param pszAttribute The attribute name.
242 * @param pszValue The string value.
243 */
244static HRESULT SetString(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, const char *pszValue)
245{
246 HRESULT hrc = pMachine->SetExtraData(Bstr(Utf8StrFmt("%s/%s/%s", pszKeyBase, pszKey, pszAttribute)), Bstr(pszValue));
247 if (FAILED(hrc))
248 RTPrintf("error: Failed to set '%s/%s/%s' to '%s'! hrc=%#x\n",
249 pszKeyBase, pszKey, pszAttribute, pszValue, hrc);
250 return hrc;
251}
252
253
254/**
255 * Sets a key value, does necessary error bitching.
256 *
257 * @returns COM status code.
258 * @param pMachine The Machine object.
259 * @param pszKeyBase The key base.
260 * @param pszKey The key.
261 * @param pszAttribute The attribute name.
262 * @param u64Value The value.
263 */
264static HRESULT SetUInt64(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, uint64_t u64Value)
265{
266 char szValue[64];
267 RTStrPrintf(szValue, sizeof(szValue), "%#RX64", u64Value);
268 return SetString(pMachine, pszKeyBase, pszKey, pszAttribute, szValue);
269}
270
271
272/**
273 * Sets a key value, does necessary error bitching.
274 *
275 * @returns COM status code.
276 * @param pMachine The Machine object.
277 * @param pszKeyBase The key base.
278 * @param pszKey The key.
279 * @param pszAttribute The attribute name.
280 * @param i64Value The value.
281 */
282static HRESULT SetInt64(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, int64_t i64Value)
283{
284 char szValue[64];
285 RTStrPrintf(szValue, sizeof(szValue), "%RI64", i64Value);
286 return SetString(pMachine, pszKeyBase, pszKey, pszAttribute, szValue);
287}
288
289
290/**
291 * Identical to the 'loadsyms' command.
292 */
293static int CmdLoadSyms(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
294{
295 HRESULT rc;
296
297 /*
298 * Get the VM
299 */
300 ComPtr<IMachine> machine;
301 /* assume it's a UUID */
302 rc = aVirtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
303 if (FAILED(rc) || !machine)
304 {
305 /* must be a name */
306 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()), 1);
307 }
308
309 /*
310 * Parse the command.
311 */
312 const char *pszFilename;
313 int64_t offDelta = 0;
314 const char *pszModule = NULL;
315 uint64_t ModuleAddress = ~0;
316 uint64_t ModuleSize = 0;
317
318 /* filename */
319 if (argc < 2)
320 return errorArgument("Missing the filename argument!\n");
321 pszFilename = argv[1];
322
323 /* offDelta */
324 if (argc >= 3)
325 {
326 int rc = RTStrToInt64Ex(argv[2], NULL, 0, &offDelta);
327 if (VBOX_FAILURE(rc))
328 return errorArgument(argv[0], "Failed to read delta '%s', rc=%Vrc\n", argv[2], rc);
329 }
330
331 /* pszModule */
332 if (argc >= 4)
333 pszModule = argv[3];
334
335 /* ModuleAddress */
336 if (argc >= 5)
337 {
338 int rc = RTStrToUInt64Ex(argv[4], NULL, 0, &ModuleAddress);
339 if (VBOX_FAILURE(rc))
340 return errorArgument(argv[0], "Failed to read module address '%s', rc=%Vrc\n", argv[4], rc);
341 }
342
343 /* ModuleSize */
344 if (argc >= 6)
345 {
346 int rc = RTStrToUInt64Ex(argv[5], NULL, 0, &ModuleSize);
347 if (VBOX_FAILURE(rc))
348 return errorArgument(argv[0], "Failed to read module size '%s', rc=%Vrc\n", argv[5], rc);
349 }
350
351 /*
352 * Add extra data.
353 */
354 Utf8Str KeyStr;
355 HRESULT hrc = NewUniqueKey(machine, "VBoxInternal/DBGF/loadsyms", KeyStr);
356 if (SUCCEEDED(hrc))
357 hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Filename", pszFilename);
358 if (SUCCEEDED(hrc) && argc >= 3)
359 hrc = SetInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Delta", offDelta);
360 if (SUCCEEDED(hrc) && argc >= 4)
361 hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "Module", pszModule);
362 if (SUCCEEDED(hrc) && argc >= 5)
363 hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "ModuleAddress", ModuleAddress);
364 if (SUCCEEDED(hrc) && argc >= 6)
365 hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr, "ModuleSize", ModuleSize);
366
367 return FAILED(hrc);
368}
369
370static int handleSetVDIUUID(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
371{
372 /* we need exactly one parameter: the vdi file */
373 if (argc != 1)
374 {
375 return errorSyntax(USAGE_SETVDIUUID, "Not enough parameters");
376 }
377
378 /* generate a new UUID */
379 Guid uuid;
380 uuid.create();
381
382 /* just try it */
383 int rc = VDISetImageUUIDs(argv[0], uuid.raw(), NULL, NULL, NULL);
384 if (VBOX_FAILURE(rc))
385 {
386 RTPrintf("Error while setting a new UUID: %Vrc (%d)\n", rc, rc);
387 }
388 else
389 {
390 RTPrintf("UUID changed to: %s\n", uuid.toString().raw());
391 }
392
393 return 0;
394}
395
396/**
397 * Wrapper for handling internal commands
398 */
399int handleInternalCommands(int argc, char *argv[],
400 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
401{
402 fInternalMode = true;
403
404 /* at least a command is required */
405 if (argc < 1)
406 return errorSyntax(USAGE_ALL, "Command missing");
407
408 /*
409 * The 'string switch' on command name.
410 */
411 const char *pszCmd = argv[0];
412 if (!strcmp(pszCmd, "loadsyms"))
413 return CmdLoadSyms(argc - 1, &argv[1], aVirtualBox, aSession);
414 //if (!strcmp(pszCmd, "unloadsyms"))
415 // return CmdUnloadSyms(argc - 1 , &argv[1]);
416 if (!strcmp(pszCmd, "setvdiuuid"))
417 return handleSetVDIUUID(argc - 1, &argv[1], aVirtualBox, aSession);
418#ifndef VBOX_OSE
419 if (!strcmp(pszCmd, "listpartitions"))
420 return CmdListPartitions(argc - 1, &argv[1], aVirtualBox, aSession);
421 if (!strcmp(pszCmd, "createrawvmdk"))
422 return CmdCreateRawVMDK(argc - 1, &argv[1], aVirtualBox, aSession);
423#endif /* !VBOX_OSE */
424
425 /* default: */
426 return errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[0]).raw());
427}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette