VirtualBox

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

Last change on this file since 100838 was 98103, checked in by vboxsync, 2 years 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.4 KB
Line 
1/* $Id: vboximgMedia.cpp 98103 2023-01-17 14:15:46Z vboxsync $ $Revision: 98103 $ */
2/** @file
3 * vboximgMedia.cpp - Disk Image Flattening FUSE Program.
4 */
5
6/*
7 * Copyright (C) 2009-2023 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 char scaledMagnitude = ((char []){ ' ', 'K', 'M', 'G', 'T', 'P' })[exp / 10];
97 /* This workaround is because IPRT RT*Printf* funcs don't handle floating point format specifiers */
98 double cbScaled = (double)size / pow(2, (double)(((uint64_t)(exp / 10)) * 10));
99 uint64_t intPart = cbScaled;
100 uint64_t fracPart = (cbScaled - (double)intPart) * 10;
101 char tmp[256];
102 RTStrPrintf(tmp, sizeof (tmp), "%d.%d%c", intPart, fracPart, scaledMagnitude);
103 return RTStrDup(tmp);
104}
105
106static int getMediumInfo(IMachine *pMachine, IMedium *pMedium, MEDIUMINFO **ppMediumInfo)
107{
108 RT_NOREF(pMachine);
109
110 MEDIUMINFO *info = new MEDIUMINFO();
111 *ppMediumInfo = info;
112
113 Bstr name;
114 Bstr uuid;
115 Bstr baseUuid;
116 Bstr path;
117 Bstr description;
118 Bstr format;
119 PRInt64 *pSize = &info->cbSize;
120 ComPtr<IMedium> pBase;
121 MediumType_T *pType = &info->type;
122 MediumState_T *pState = &info->state;
123
124 *pState = MediumState_NotCreated;
125
126 HRESULT hrc;
127
128 CHECK_ERROR(pMedium, RefreshState(pState));
129 CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam()));
130 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
131 CHECK_ERROR(pBase, COMGETTER(Id)(baseUuid.asOutParam()));
132
133 CHECK_ERROR(pMedium, COMGETTER(State)(pState));
134
135 CHECK_ERROR(pMedium, COMGETTER(Location)(path.asOutParam()));
136 CHECK_ERROR(pMedium, COMGETTER(Format)(format.asOutParam()));
137 CHECK_ERROR(pMedium, COMGETTER(Type)(pType));
138 CHECK_ERROR(pMedium, COMGETTER(Size)(pSize));
139
140 info->pszUuid = RTStrDup((char *)CSTR(uuid));
141 info->pszBaseUuid = RTStrDup((char *)CSTR(baseUuid));
142 info->pszPath = RTStrDup((char *)CSTR(path));
143 info->pszFormat = RTStrDup((char *)CSTR(format));
144 info->fSnapshot = RTStrCmp(CSTR(uuid), CSTR(baseUuid)) != 0;
145
146 if (info->fSnapshot)
147 {
148 /** @todo Determine the VM snapshot this and set name and description
149 * to the snapshot name/description
150 */
151 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
152 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
153 }
154 else
155 {
156 CHECK_ERROR(pMedium, COMGETTER(Name)(name.asOutParam()));
157 CHECK_ERROR(pMedium, COMGETTER(Description)(description.asOutParam()));
158 }
159
160 info->pszName = RTStrDup((char *)CSTR(name));
161 info->pszDescription = RTStrDup((char *)CSTR(description));
162
163 switch(*pType)
164 {
165 case MediumType_Normal:
166 info->pszType = (char *)"normal";
167 break;
168 case MediumType_Immutable:
169 info->pszType = (char *)"immutable";
170 break;
171 case MediumType_Writethrough:
172 info->pszType = (char *)"writethrough";
173 break;
174 case MediumType_Shareable:
175 info->pszType = (char *)"shareable";
176 break;
177 case MediumType_Readonly:
178 info->pszType = (char *)"readonly";
179 break;
180 case MediumType_MultiAttach:
181 info->pszType = (char *)"multiattach";
182 break;
183 default:
184 info->pszType = (char *)"?";
185 }
186
187 switch(*pState)
188 {
189 case MediumState_NotCreated:
190 info->pszState = (char *)"uncreated";
191 break;
192 case MediumState_Created:
193 info->pszState = (char *)"created";
194 break;
195 case MediumState_LockedRead:
196 info->pszState = (char *)"rlock";
197 break;
198 case MediumState_LockedWrite:
199 info->pszState = (char *)"wlock";
200 break;
201 case MediumState_Inaccessible:
202 info->pszState = (char *)"no access";
203 break;
204 case MediumState_Creating:
205 info->pszState = (char *)"creating";
206 break;
207 case MediumState_Deleting:
208 info->pszState = (char *)"deleting";
209 break;
210 default:
211 info->pszState = (char *)"?";
212 }
213 return VINF_SUCCESS;
214}
215
216static void displayMediumInfo(MEDIUMINFO *pInfo, int nestLevel, bool fLast)
217{
218 char *pszSzScaled = vboximgScaledSize(pInfo->cbSize);
219 int cPad = nestLevel * 2;
220 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
221 {
222 RTPrintf("%3s %-*s %7s %-9s %9s %-*s %s\n",
223 !fLast ? (pInfo->fSnapshot ? " | " : " +-") : (pInfo->fSnapshot ? " " : " +-"),
224 VM_MAX_NAME, pInfo->fSnapshot ? "+- <snapshot>" : pInfo->pszName,
225 pszSzScaled,
226 pInfo->pszFormat,
227 pInfo->pszState,
228 cPad, "", pInfo->pszUuid);
229 }
230 else
231 {
232 if (!pInfo->fSnapshot)
233 {
234 RTPrintf(" Image: %s\n", pInfo->pszName);
235 if (pInfo->pszDescription && RTStrNLen(pInfo->pszDescription, 256) > 0)
236 RTPrintf("Desc: %s\n", pInfo->pszDescription);
237 RTPrintf(" UUID: %s\n", pInfo->pszUuid);
238 if (g_vboximgOpts.fVerbose)
239 {
240 RTPrintf(" Path: %s\n", pInfo->pszPath);
241 RTPrintf(" Format: %s\n", pInfo->pszFormat);
242 RTPrintf(" Size: %s\n", pszSzScaled);
243 RTPrintf(" State: %s\n", pInfo->pszState);
244 RTPrintf(" Type: %s\n", pInfo->pszType);
245 }
246 RTPrintf("\n");
247 }
248 else
249 {
250 RTPrintf(" Snapshot: %s\n", pInfo->pszUuid);
251 if (g_vboximgOpts.fVerbose)
252 {
253 RTPrintf(" Name: %s\n", pInfo->pszName);
254 RTPrintf(" Desc: %s\n", pInfo->pszDescription);
255 }
256 RTPrintf(" Size: %s\n", pszSzScaled);
257 if (g_vboximgOpts.fVerbose)
258 RTPrintf(" Path: %s\n", pInfo->pszPath);
259 RTPrintf("\n");
260 }
261 }
262 RTMemFree(pszSzScaled);
263}
264
265static int vboximgListBranch(IMachine *pMachine, IMedium *pMedium, uint8_t nestLevel, bool fLast)
266{
267 MEDIUMINFO *pMediumInfo;
268 int vrc = getMediumInfo(pMachine, pMedium, &pMediumInfo);
269 if (RT_FAILURE(vrc))
270 return vrc;
271
272 displayMediumInfo(pMediumInfo, nestLevel, fLast);
273
274 HRESULT hrc;
275 com::SafeIfaceArray<IMedium> pChildren;
276 CHECK_ERROR_RET(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(pChildren)), VERR_NOT_FOUND); /** @todo r=andy Find a better rc. */
277
278 for (size_t i = 0; i < pChildren.size(); i++)
279 vboximgListBranch(pMachine, pChildren[i], nestLevel + 1, fLast);
280
281 delete pMediumInfo;
282
283 return VINF_SUCCESS;
284}
285
286static int listMedia(IVirtualBox *pVirtualBox, IMachine *pMachine, char *vmName, char *vmUuid)
287{
288 RT_NOREF(pVirtualBox);
289 RT_NOREF(vmName);
290 RT_NOREF(vmUuid);
291
292 int vrc = VINF_SUCCESS;
293
294 com::SafeIfaceArray<IMediumAttachment> pMediumAttachments;
295
296 HRESULT hrc;
297 CHECK_ERROR(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(pMediumAttachments)));
298
299 for (size_t i = 0; i < pMediumAttachments.size(); i++)
300 {
301 bool fLast = (i == pMediumAttachments.size() - 1);
302 DeviceType_T deviceType;
303
304 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Type)(&deviceType));
305 if (deviceType != DeviceType_HardDisk)
306 continue;
307
308 ComPtr<IMedium> pMedium;
309 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Medium)(pMedium.asOutParam()));
310
311 ComPtr<IMedium> pBase;
312 CHECK_ERROR(pMedium, COMGETTER(Base)(pBase.asOutParam()));
313 if (g_vboximgOpts.fWide && !g_vboximgOpts.fVerbose)
314 RTPrintf(" |\n");
315 else
316 RTPrintf("\n");
317
318 vrc = vboximgListBranch(pMachine, pBase, 0, fLast);
319 if (RT_FAILURE(vrc))
320 {
321 RTPrintf("vboximgListBranch failed with %Rrc\n", vrc);
322 break;
323 }
324 }
325
326 return vrc;
327}
328/**
329 * Display all registered VMs on the screen with some information about each
330 *
331 * @param virtualBox VirtualBox instance object.
332 */
333int vboximgListVMs(IVirtualBox *pVirtualBox)
334{
335 HRESULT hrc;
336 com::SafeIfaceArray<IMachine> pMachines;
337 CHECK_ERROR(pVirtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam(pMachines)));
338
339 if (g_vboximgOpts.fWide)
340 {
341 RTPrintf("\n");
342 RTPrintf("VM Image Size Type State UUID (hierarchy)\n");
343 }
344
345 int vrc = VINF_SUCCESS;
346
347 for (size_t i = 0; i < pMachines.size(); ++i)
348 {
349 ComPtr<IMachine> pMachine = pMachines[i];
350 if (pMachine)
351 {
352 BOOL fAccessible;
353 CHECK_ERROR(pMachines[i], COMGETTER(Accessible)(&fAccessible));
354 if (fAccessible)
355 {
356 Bstr machineName;
357 Bstr machineUuid;
358 Bstr description;
359 Bstr machineLocation;
360
361 CHECK_ERROR(pMachine, COMGETTER(Name)(machineName.asOutParam()));
362 CHECK_ERROR(pMachine, COMGETTER(Id)(machineUuid.asOutParam()));
363 CHECK_ERROR(pMachine, COMGETTER(Description)(description.asOutParam()));
364 CHECK_ERROR(pMachine, COMGETTER(SettingsFilePath)(machineLocation.asOutParam()));
365
366
367 if ( g_vboximgOpts.pszVm == NULL
368 || RTStrNCmp(CSTR(machineUuid), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0
369 || RTStrNCmp((const char *)machineName.raw(), g_vboximgOpts.pszVm, MAX_UUID_LEN) == 0)
370 {
371 if (g_vboximgOpts.fVerbose)
372 {
373 RTPrintf("-----------------------------------------------------------------\n");
374 RTPrintf("VM Name: \"%s\"\n", CSTR(machineName));
375 RTPrintf("UUID: %s\n", CSTR(machineUuid));
376 if (*description.raw() != '\0')
377 RTPrintf("Desc: %s\n", CSTR(description));
378 RTPrintf("Path: %s\n", CSTR(machineLocation));
379 }
380 else
381 {
382 if (g_vboximgOpts.fWide & !g_vboximgOpts.fVerbose)
383 {
384 RTPrintf("----------------------------------------------------------------- "
385 "------------------------------------\n");
386 RTPrintf("%-*s %*s %s\n", VM_MAX_NAME, CSTR(machineName), 33, "", CSTR(machineUuid));
387 }
388 else
389 {
390 RTPrintf("-----------------------------------------------------------------\n");
391 RTPrintf("VM: %s\n", CSTR(machineName));
392 RTPrintf("UUID: %s\n", CSTR(machineUuid));
393 }
394 }
395
396 int vrc2 = listMedia(pVirtualBox, pMachine,
397 RTStrDup(CSTR(machineName)), RTStrDup(CSTR(machineUuid)));
398 if (RT_SUCCESS(vrc))
399 vrc = vrc2;
400
401 RTPrintf("\n");
402 }
403 }
404 }
405 }
406
407 return vrc;
408}
409
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