VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/ResourceStoreImpl.cpp@ 107461

Last change on this file since 107461 was 107461, checked in by vboxsync, 3 weeks ago

Main/src-client/ResourceStoreImpl.cpp: Missing field initialisers, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: ResourceStoreImpl.cpp 107461 2025-01-07 11:11:10Z vboxsync $ */
2/** @file
3 * VirtualBox COM resource store class implementation
4 */
5
6/*
7 * Copyright (C) 2023-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#define LOG_GROUP LOG_GROUP_MAIN_RESOURCESTORE
29#include "LoggingNew.h"
30
31#include "ResourceStoreImpl.h"
32#include "ConsoleImpl.h"
33#include "VirtualBoxImpl.h"
34
35#include "AutoCaller.h"
36
37#include <VBox/com/array.h>
38#include <VBox/vmm/pdmdrv.h>
39#include <VBox/err.h>
40
41#include <iprt/cpp/utils.h>
42#include <iprt/file.h>
43#include <iprt/vfs.h>
44
45
46// defines
47////////////////////////////////////////////////////////////////////////////////
48
49
50// globals
51////////////////////////////////////////////////////////////////////////////////
52
53/**
54 * Resource store driver instance data.
55 */
56typedef struct DRVMAINRESOURCESTORE
57{
58 /** Pointer to the keyboard object. */
59 ResourceStore *pResourceStore;
60 /** Pointer to the driver instance structure. */
61 PPDMDRVINS pDrvIns;
62 /** Our VFS connector interface. */
63 PDMIVFSCONNECTOR IVfs;
64} DRVMAINRESOURCESTORE, *PDRVMAINRESOURCESTORE;
65
66/** The resource store map keyed by namespace/entity. */
67typedef std::map<Utf8Str, RTVFSFILE> ResourceStoreMap;
68/** The resource store map iterator. */
69typedef std::map<Utf8Str, RTVFSFILE>::iterator ResourceStoreIter;
70
71struct BackupableResourceStoreData
72{
73 BackupableResourceStoreData()
74 { }
75
76 /** The resource store. */
77 ResourceStoreMap mapResources;
78};
79
80/////////////////////////////////////////////////////////////////////////////
81// ResourceStore::Data structure
82/////////////////////////////////////////////////////////////////////////////
83
84struct ResourceStore::Data
85{
86 Data()
87 : pParent(NULL),
88 cRefs(0)
89 { }
90
91 /** The Console owning this resource store. */
92 Console * const pParent;
93 /** Number of references held to this resource store from the various devices/drivers. */
94 volatile uint32_t cRefs;
95
96 Backupable<BackupableResourceStoreData> bd;
97};
98
99// constructor / destructor
100////////////////////////////////////////////////////////////////////////////////
101
102DEFINE_EMPTY_CTOR_DTOR(ResourceStore)
103
104HRESULT ResourceStore::FinalConstruct()
105{
106 return BaseFinalConstruct();
107}
108
109void ResourceStore::FinalRelease()
110{
111 uninit();
112 BaseFinalRelease();
113}
114
115
116// public initializer/uninitializer for internal purposes only
117/////////////////////////////////////////////////////////////////////////////
118
119/**
120 * Initializes the resource store object.
121 *
122 * @returns COM result indicator
123 * @param aParent Handle of our parent object
124 */
125HRESULT ResourceStore::init(Console *aParent)
126{
127 LogFlowThisFunc(("aParent=%p\n", aParent));
128
129 ComAssertRet(aParent, E_INVALIDARG);
130
131 /* Enclose the state transition NotReady->InInit->Ready */
132 AutoInitSpan autoInitSpan(this);
133 AssertReturn(autoInitSpan.isOk(), E_FAIL);
134
135 m = new Data();
136
137 unconst(m->pParent) = aParent;
138
139 m->bd.allocate();
140
141 /* Confirm a successful initialization */
142 autoInitSpan.setSucceeded();
143
144 return S_OK;
145}
146
147
148/**
149 * Uninitializes the instance and sets the ready flag to FALSE.
150 * Called either from FinalRelease() or by the parent when it gets destroyed.
151 */
152void ResourceStore::uninit()
153{
154 LogFlowThisFuncEnter();
155
156 /* Enclose the state transition Ready->InUninit->NotReady */
157 AutoUninitSpan autoUninitSpan(this);
158 if (autoUninitSpan.uninitDone())
159 return;
160
161 unconst(m->pParent) = NULL;
162
163 /* Delete the store content. */
164 ResourceStoreIter it = m->bd->mapResources.begin();
165 while (it != m->bd->mapResources.end())
166 {
167 RTVfsFileRelease(it->second);
168 it++;
169 }
170
171 m->bd->mapResources.clear();
172 m->bd.free();
173
174 delete m;
175 m = NULL;
176
177 LogFlowThisFuncLeave();
178}
179
180
181/**
182 * Adds the given item to the store under the namespace and path.
183 *
184 * @returns VBox status code.
185 * @param pszNamespace The namespace of the item.
186 * @param pszPath The path to the item.
187 * @param hVfsFile The item data as a VFS file handle, a reference is retained on success.
188 */
189int ResourceStore::i_addItem(const char *pszNamespace, const char *pszPath, RTVFSFILE hVfsFile)
190{
191 Utf8Str strKey;
192 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
193 AssertRCReturn(vrc, vrc);
194
195 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
196 try
197 {
198 RTVfsFileRetain(hVfsFile);
199 m->bd->mapResources[strKey] = hVfsFile;
200 }
201 catch (...)
202 {
203 AssertLogRelFailed();
204 vrc = VERR_UNEXPECTED_EXCEPTION;
205 }
206
207 return vrc;
208}
209
210
211//
212// private methods
213//
214/*static*/
215DECLCALLBACK(int) ResourceStore::i_resourceStoreQuerySize(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
216 uint64_t *pcb)
217{
218 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
219
220 Utf8Str strKey;
221 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
222 AssertRCReturn(vrc, vrc);
223
224 AutoReadLock rlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
225 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
226 if (it != pThis->pResourceStore->m->bd->mapResources.end())
227 {
228 RTVFSFILE hVfsFile = it->second;
229 return RTVfsFileQuerySize(hVfsFile, pcb);
230 }
231
232 return VERR_NOT_FOUND;
233}
234
235
236/*static*/
237DECLCALLBACK(int) ResourceStore::i_resourceStoreReadAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
238 void *pvBuf, size_t cbRead)
239{
240 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
241
242 Utf8Str strKey;
243 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
244 AssertRCReturn(vrc, vrc);
245
246 AutoReadLock rlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
247 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
248 if (it != pThis->pResourceStore->m->bd->mapResources.end())
249 {
250 RTVFSFILE hVfsFile = it->second;
251
252 vrc = RTVfsFileSeek(hVfsFile, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
253 AssertLogRelRC(vrc);
254
255 return RTVfsFileRead(hVfsFile, pvBuf, cbRead, NULL /*pcbRead*/);
256 }
257
258 return VERR_NOT_FOUND;
259}
260
261
262/*static*/
263DECLCALLBACK(int) ResourceStore::i_resourceStoreWriteAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
264 const void *pvBuf, size_t cbWrite)
265{
266 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
267
268 Utf8Str strKey;
269 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
270 AssertRCReturn(vrc, vrc);
271
272 AutoWriteLock wlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
273
274 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
275 if (it != pThis->pResourceStore->m->bd->mapResources.end())
276 {
277 RTVFSFILE hVfsFile = it->second;
278
279 vrc = RTVfsFileSeek(hVfsFile, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
280 AssertLogRelRC(vrc);
281 vrc = RTVfsFileSetSize(hVfsFile, cbWrite, RTVFSFILE_SIZE_F_NORMAL);
282 if (RT_SUCCESS(vrc))
283 vrc = RTVfsFileWrite(hVfsFile, pvBuf, cbWrite, NULL /*pcbWritten*/);
284 }
285 else
286 {
287 /* Create a new entry. */
288 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
289 vrc = RTVfsFileFromBuffer(RTFILE_O_READ | RTFILE_O_WRITE, pvBuf, cbWrite, &hVfsFile);
290 if (RT_SUCCESS(vrc))
291 {
292 try
293 {
294 pThis->pResourceStore->m->bd->mapResources[strKey] = hVfsFile;
295 }
296 catch (...)
297 {
298 AssertLogRelFailed();
299 RTVfsFileRelease(hVfsFile);
300 vrc = VERR_UNEXPECTED_EXCEPTION;
301 }
302 }
303 }
304
305 return vrc;
306}
307
308
309/*static*/
310DECLCALLBACK(int) ResourceStore::i_resourceStoreDelete(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath)
311{
312 PDRVMAINRESOURCESTORE pThis = RT_FROM_MEMBER(pInterface, DRVMAINRESOURCESTORE, IVfs);
313
314 Utf8Str strKey;
315 int vrc = strKey.printfNoThrow("%s/%s", pszNamespace, pszPath);
316 AssertRCReturn(vrc, vrc);
317
318 AutoWriteLock wlock(pThis->pResourceStore COMMA_LOCKVAL_SRC_POS);
319 ResourceStoreIter it = pThis->pResourceStore->m->bd->mapResources.find(strKey);
320 if (it != pThis->pResourceStore->m->bd->mapResources.end())
321 {
322 RTVFSFILE hVfsFile = it->second;
323 pThis->pResourceStore->m->bd->mapResources.erase(it);
324 RTVfsFileRelease(hVfsFile);
325 return VINF_SUCCESS;
326 }
327
328 return VERR_NOT_FOUND;
329}
330
331
332/**
333 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
334 */
335DECLCALLBACK(void *) ResourceStore::i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
336{
337 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
338 PDRVMAINRESOURCESTORE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
339
340 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
341 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVFSCONNECTOR, &pDrv->IVfs);
342 return NULL;
343}
344
345
346/**
347 * Destruct a resource store driver instance.
348 *
349 * @param pDrvIns The driver instance data.
350 */
351DECLCALLBACK(void) ResourceStore::i_drvDestruct(PPDMDRVINS pDrvIns)
352{
353 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
354 PDRVMAINRESOURCESTORE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
355 LogFlow(("ResourceStore::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
356
357 if (pThis->pResourceStore)
358 {
359 ASMAtomicDecU32(&pThis->pResourceStore->m->cRefs);
360 pThis->pResourceStore = NULL;
361 }
362}
363
364
365/**
366 * Construct a resource store driver instance.
367 *
368 * @copydoc FNPDMDRVCONSTRUCT
369 */
370DECLCALLBACK(int) ResourceStore::i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
371{
372 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
373 RT_NOREF(fFlags, pCfg);
374 PDRVMAINRESOURCESTORE pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINRESOURCESTORE);
375 LogFlow(("ResourceStore::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
376
377 /*
378 * Validate configuration.
379 */
380 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "", "");
381 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
382 ("Configuration error: Not possible to attach anything to this driver!\n"),
383 VERR_PDM_DRVINS_NO_ATTACH);
384
385 /*
386 * IBase.
387 */
388 pDrvIns->IBase.pfnQueryInterface = ResourceStore::i_drvQueryInterface;
389
390 pThis->IVfs.pfnQuerySize = ResourceStore::i_resourceStoreQuerySize;
391 pThis->IVfs.pfnReadAll = ResourceStore::i_resourceStoreReadAll;
392 pThis->IVfs.pfnWriteAll = ResourceStore::i_resourceStoreWriteAll;
393 pThis->IVfs.pfnDelete = ResourceStore::i_resourceStoreDelete;
394
395 /*
396 * Get the resource store object pointer.
397 */
398 com::Guid uuid(COM_IIDOF(IResourceStore));
399 pThis->pResourceStore = (ResourceStore *)PDMDrvHlpQueryGenericUserObject(pDrvIns, uuid.raw());
400 if (!pThis->pResourceStore)
401 {
402 AssertMsgFailed(("Configuration error: No/bad resource store object!\n"));
403 return VERR_NOT_FOUND;
404 }
405
406 ASMAtomicIncU32(&pThis->pResourceStore->m->cRefs);
407 return VINF_SUCCESS;
408}
409
410
411/**
412 * Resource store driver registration record.
413 */
414const PDMDRVREG ResourceStore::DrvReg =
415{
416 /* u32Version */
417 PDM_DRVREG_VERSION,
418 /* szName */
419 "ResourceStore",
420 /* szRCMod */
421 "",
422 /* szR0Mod */
423 "",
424 /* pszDescription */
425 "Main resource store driver (Main as in the API).",
426 /* fFlags */
427 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
428 /* fClass. */
429 PDM_DRVREG_CLASS_STATUS,
430 /* cMaxInstances */
431 ~0U,
432 /* cbInstance */
433 sizeof(DRVMAINRESOURCESTORE),
434 /* pfnConstruct */
435 ResourceStore::i_drvConstruct,
436 /* pfnDestruct */
437 ResourceStore::i_drvDestruct,
438 /* pfnRelocate */
439 NULL,
440 /* pfnIOCtl */
441 NULL,
442 /* pfnPowerOn */
443 NULL,
444 /* pfnReset */
445 NULL,
446 /* pfnSuspend */
447 NULL,
448 /* pfnResume */
449 NULL,
450 /* pfnAttach */
451 NULL,
452 /* pfnDetach */
453 NULL,
454 /* pfnPowerOff */
455 NULL,
456 /* pfnSoftReset */
457 NULL,
458 /* u32EndVersion */
459 PDM_DRVREG_VERSION
460};
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