VirtualBox

source: vbox/trunk/src/VBox/ImageMounter/vboximg-mount/vboximgMedia.cpp

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/* $Id: vboximgMedia.cpp 106061 2024-09-16 14:03:52Z vboxsync $ $Revision: 106061 $ */
2/** @file
3 * vboximgMedia.cpp - Disk Image Flattening FUSE Program.
4 */
5
6/*
7 * Copyright (C) 2009-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <VirtualBox_XPCOM.h>
29#include <VBox/com/VirtualBox.h>
30#include <VBox/vd.h>
31#include <VBox/vd-ifs.h>
32#include <VBox/log.h>
33#include <iprt/errcore.h>
34#include <VBox/com/ErrorInfo.h>
35#include <VBox/com/NativeEventQueue.h>
36#include <VBox/com/com.h>
37#include <VBox/com/string.h>
38#include <VBox/com/Guid.h>
39#include <VBox/com/array.h>
40#include <VBox/com/errorprint.h>
41#include <VBox/vd-plugin.h>
42#include <iprt/initterm.h>
43#include <iprt/assert.h>
44#include <iprt/message.h>
45#include <iprt/critsect.h>
46#include <iprt/asm.h>
47#include <iprt/mem.h>
48#include <iprt/string.h>
49#include <iprt/initterm.h>
50#include <iprt/stream.h>
51#include <iprt/types.h>
52#include <iprt/path.h>
53#include <iprt/utf16.h>
54#include <math.h>
55#include "vboximgOpts.h"
56
57using namespace com;
58
59extern VBOXIMGOPTS g_vboximgOpts;
60
61#define SAFENULL(strPtr) (strPtr ? strPtr : "") /** Makes null harmless to print */
62#define CSTR(arg) Utf8Str(arg).c_str() /** Converts XPCOM string type to C string type */
63#define MAX_UUID_LEN 256 /** Max length of a UUID */
64#define VM_MAX_NAME 32 /** Max length of VM name we handle */
65
66typedef struct MEDIUMINFO
67{
68 char *pszName;
69 char *pszUuid;
70 char *pszBaseUuid;
71 char *pszPath;
72 char *pszDescription;
73 char *pszState;
74 char *pszType;
75 char *pszFormat;
76 bool fSnapshot;
77 PRInt64 cbSize;
78 MediumType_T type;
79 MediumState_T state;
80 ~MEDIUMINFO()
81 {
82 RTMemFree(pszName);
83 RTMemFree(pszUuid);
84 RTMemFree(pszPath);
85 RTMemFree(pszDescription);
86 RTMemFree(pszFormat);
87 }
88} MEDIUMINFO;
89
90
91char *vboximgScaledSize(size_t size)
92{
93 uint64_t exp = 0;
94 if (size > 0)
95 exp = log2((double)size);
96 static const char s_aMagnitude[] = { ' ', 'K', 'M', 'G', 'T', 'P' };
97 char scaledMagnitude = s_aMagnitude[exp / 10];
98 /* This workaround is because IPRT RT*Printf* funcs don't handle floating point format specifiers */
99 double cbScaled = (double)size / pow(2, (double)(((uint64_t)(exp / 10)) * 10));
100 uint64_t intPart = cbScaled;
101 uint64_t fracPart = (cbScaled - (double)intPart) * 10;
102 char tmp[256];
103 RTStrPrintf(tmp, sizeof (tmp), "%d.%d%c", intPart, fracPart, scaledMagnitude);
104 return RTStrDup(tmp);
105}
106
107static int getMediumInfo(IMachine *pMachine, IMedium *pMedium, MEDIUMINFO **ppMediumInfo)
108{
109 RT_NOREF(pMachine);
110
111 MEDIUMINFO *info = new MEDIUMINFO();
112 *ppMediumInfo = info;
113
114 Bstr name;
115 Bstr uuid;
116 Bstr baseUuid;
117 Bstr path;
118 Bstr description;
119 Bstr format;
120 PRInt64 *pSize = &info->cbSize;
121 ComPtr<IMedium> pBase;
122 MediumType_T *pType = &info->type;
123 MediumState_T *pState = &info->state;
124
125 *pState = MediumState_NotCreated;
126
127 HRESULT hrc;
128
129 CHECK_ERROR(pMedium, RefreshState(pState));
130 CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam()));
131 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
132 CHECK_ERROR(pBase, COMGETTER(Id)(baseUuid.asOutParam()));
133
134 CHECK_ERROR(pMedium, COMGETTER(State)(pState));
135
136 CHECK_ERROR(pMedium, COMGETTER(Location)(path.asOutParam()));
137 CHECK_ERROR(pMedium, COMGETTER(Format)(format.asOutParam()));
138 CHECK_ERROR(pMedium, COMGETTER(Type)(pType));
139 CHECK_ERROR(pMedium, COMGETTER(Size)(pSize));
140
141 info->pszUuid = RTStrDup((char *)CSTR(uuid));
142 info->pszBaseUuid = RTStrDup((char *)CSTR(baseUuid));
143 info->pszPath = RTStrDup((char *)CSTR(path));
144 info->pszFormat = RTStrDup((char *)CSTR(format));
145 info->fSnapshot = RTStrCmp(CSTR(uuid), CSTR(baseUuid)) != 0;
146
147 if (info->fSnapshot)
148 {
149 /** @todo Determine the VM snapshot this and set name and description
150 * to the snapshot name/description
151 */
152 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
153 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
154 }
155 else
156 {
157 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
158 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
159 }
160
161 info->pszName = RTStrDup((char *)CSTR(name));
162 info->pszDescription = RTStrDup((char *)CSTR(description));
163
164 switch(*pType)
165 {
166 case MediumType_Normal:
167 info->pszType = (char *)"normal";
168 break;
169 case MediumType_Immutable:
170 info->pszType = (char *)"immutable";
171 break;
172 case MediumType_Writethrough:
173 info->pszType = (char *)"writethrough";
174 break;
175 case MediumType_Shareable:
176 info->pszType = (char *)"shareable";
177 break;
178 case MediumType_Readonly:
179 info->pszType = (char *)"readonly";
180 break;
181 case MediumType_MultiAttach:
182 info->pszType = (char *)"multiattach";
183 break;
184 default:
185 info->pszType = (char *)"?";
186 }
187
188 switch(*pState)
189 {
190 case MediumState_NotCreated:
191 info->pszState = (char *)"uncreated";
192 break;
193 case MediumState_Created:
194 info->pszState = (char *)"created";
195 break;
196 case MediumState_LockedRead:
197 info->pszState = (char *)"rlock";
198 break;
199 case MediumState_LockedWrite:
200 info->pszState = (char *)"wlock";
201 break;
202 case MediumState_Inaccessible:
203 info->pszState = (char *)"no access";
204 break;
205 case MediumState_Creating:
206 info->pszState = (char *)"creating";
207 break;
208 case MediumState_Deleting:
209 info->pszState = (char *)"deleting";
210 break;
211 default:
212 info->pszState = (char *)"?";
213 }
214 return VINF_SUCCESS;
215}
216
217static void displayMediumInfo(MEDIUMINFO *pInfo, int nestLevel, bool fLast)
218{
219 char *pszSzScaled = vboximgScaledSize(pInfo->cbSize);
220 int cPad = nestLevel * 2;
221 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
222 {
223 RTPrintf("%3s %-*s %7s %-9s %9s %-*s %s\n",
224 !fLast ? (pInfo->fSnapshot ? " | " : " +-") : (pInfo->fSnapshot ? " " : " +-"),
225 VM_MAX_NAME, pInfo->fSnapshot ? "+- <snapshot>" : pInfo->pszName,
226 pszSzScaled,
227 pInfo->pszFormat,
228 pInfo->pszState,
229 cPad, "", pInfo->pszUuid);
230 }
231 else
232 {
233 if (!pInfo->fSnapshot)
234 {
235 RTPrintf(" Image: %s\n", pInfo->pszName);
236 if (pInfo->pszDescription && RTStrNLen(pInfo->pszDescription, 256) > 0)
237 RTPrintf("Desc: %s\n", pInfo->pszDescription);
238 RTPrintf(" UUID: %s\n", pInfo->pszUuid);
239 if (g_vboximgOpts.fVerbose)
240 {
241 RTPrintf(" Path: %s\n", pInfo->pszPath);
242 RTPrintf(" Format: %s\n", pInfo->pszFormat);
243 RTPrintf(" Size: %s\n", pszSzScaled);
244 RTPrintf(" State: %s\n", pInfo->pszState);
245 RTPrintf(" Type: %s\n", pInfo->pszType);
246 }
247 RTPrintf("\n");
248 }
249 else
250 {
251 RTPrintf(" Snapshot: %s\n", pInfo->pszUuid);
252 if (g_vboximgOpts.fVerbose)
253 {
254 RTPrintf(" Name: %s\n", pInfo->pszName);
255 RTPrintf(" Desc: %s\n", pInfo->pszDescription);
256 }
257 RTPrintf(" Size: %s\n", pszSzScaled);
258 if (g_vboximgOpts.fVerbose)
259 RTPrintf(" Path: %s\n", pInfo->pszPath);
260 RTPrintf("\n");
261 }
262 }
263 RTMemFree(pszSzScaled);
264}
265
266static int vboximgListBranch(IMachine *pMachine, IMedium *pMedium, uint8_t nestLevel, bool fLast)
267{
268 MEDIUMINFO *pMediumInfo;
269 int vrc = getMediumInfo(pMachine, pMedium, &pMediumInfo);
270 if (RT_FAILURE(vrc))
271 return vrc;
272
273 displayMediumInfo(pMediumInfo, nestLevel, fLast);
274
275 HRESULT hrc;
276 com::SafeIfaceArray<IMedium> pChildren;
277 CHECK_ERROR_RET(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(pChildren)), VERR_NOT_FOUND); /** @todo r=andy Find a better rc. */
278
279 for (size_t i = 0; i < pChildren.size(); i++)
280 vboximgListBranch(pMachine, pChildren[i], nestLevel + 1, fLast);
281
282 delete pMediumInfo;
283
284 return VINF_SUCCESS;
285}
286
287static int listMedia(IVirtualBox *pVirtualBox, IMachine *pMachine, char *vmName, char *vmUuid)
288{
289 RT_NOREF(pVirtualBox);
290 RT_NOREF(vmName);
291 RT_NOREF(vmUuid);
292
293 int vrc = VINF_SUCCESS;
294
295 com::SafeIfaceArray<IMediumAttachment> pMediumAttachments;
296
297 HRESULT hrc;
298 CHECK_ERROR(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(pMediumAttachments)));
299
300 for (size_t i = 0; i < pMediumAttachments.size(); i++)
301 {
302 bool fLast = (i == pMediumAttachments.size() - 1);
303 DeviceType_T deviceType;
304
305 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Type)(&deviceType));
306 if (deviceType != DeviceType_HardDisk)
307 continue;
308
309 ComPtr<IMedium> pMedium;
310 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Medium)(pMedium.asOutParam()));
311
312 ComPtr<IMedium> pBase;
313 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
314 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
315 RTPrintf(" |\n");
316 else
317 RTPrintf("\n");
318
319 vrc = vboximgListBranch(pMachine, pBase, 0, fLast);
320 if (RT_FAILURE(vrc))
321 {
322 RTPrintf("vboximgListBranch failed with %Rrc\n", vrc);
323 break;
324 }
325 }
326
327 return vrc;
328}
329/**
330 * Display all registered VMs on the screen with some information about each
331 *
332 * @param virtualBox VirtualBox instance object.
333 */
334int vboximgListVMs(IVirtualBox *pVirtualBox)
335{
336 HRESULT hrc;
337 com::SafeIfaceArray<IMachine> pMachines;
338 CHECK_ERROR(pVirtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam(pMachines)));
339
340 if (g_vboximgOpts.fWide)
341 {
342 RTPrintf("\n");
343 RTPrintf("VM Image Size Type State UUID (hierarchy)\n");
344 }
345
346 int vrc = VINF_SUCCESS;
347
348 for (size_t i = 0; i < pMachines.size(); ++i)
349 {
350 ComPtr<IMachine> pMachine = pMachines[i];
351 if (pMachine)
352 {
353 BOOL fAccessible;
354 CHECK_ERROR(pMachines[i], COMGETTER(Accessible)(&fAccessible));
355 if (fAccessible)
356 {
357 Bstr machineName;
358 Bstr machineUuid;
359 Bstr description;
360 Bstr machineLocation;
361
362 CHECK_ERROR(pMachine, COMGETTER(Name)(machineName.asOutParam()));
363 CHECK_ERROR(pMachine, COMGETTER(Id)(machineUuid.asOutParam()));
364 CHECK_ERROR(pMachine, COMGETTER(Description)(description.asOutParam()));
365 CHECK_ERROR(pMachine, COMGETTER(SettingsFilePath)(machineLocation.asOutParam()));
366
367
368 if ( g_vboximgOpts.pszVm == NULL
369 || RTStrNCmp(CSTR(machineUuid), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0
370 || RTStrNCmp((const char *)machineName.raw(), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0)
371 {
372 if (g_vboximgOpts.fVerbose)
373 {
374 RTPrintf("-----------------------------------------------------------------\n");
375 RTPrintf("VM Name: \"%s\"\n", CSTR(machineName));
376 RTPrintf("UUID: %s\n", CSTR(machineUuid));
377 if (*description.raw() != '\0')
378 RTPrintf("Desc: %s\n", CSTR(description));
379 RTPrintf("Path: %s\n", CSTR(machineLocation));
380 }
381 else
382 {
383 if (g_vboximgOpts.fWide & !g_vboximgOpts.fVerbose)
384 {
385 RTPrintf("----------------------------------------------------------------- "
386 "------------------------------------\n");
387 RTPrintf("%-*s %*s %s\n", VM_MAX_NAME, CSTR(machineName), 33, "", CSTR(machineUuid));
388 }
389 else
390 {
391 RTPrintf("-----------------------------------------------------------------\n");
392 RTPrintf("VM: %s\n", CSTR(machineName));
393 RTPrintf("UUID: %s\n", CSTR(machineUuid));
394 }
395 }
396
397 int vrc2 = listMedia(pVirtualBox, pMachine,
398 RTStrDup(CSTR(machineName)), RTStrDup(CSTR(machineUuid)));
399 if (RT_SUCCESS(vrc))
400 vrc = vrc2;
401
402 RTPrintf("\n");
403 }
404 }
405 }
406 }
407
408 return vrc;
409}
410
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