VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dvm/dvm.cpp@ 62477

Last change on this file since 62477 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.4 KB
Line 
1/* $Id: dvm.cpp 62477 2016-07-22 18:27:37Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - generic code.
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/types.h>
32#include <iprt/assert.h>
33#include <iprt/mem.h>
34#include <iprt/dvm.h>
35#include <iprt/err.h>
36#include <iprt/asm.h>
37#include <iprt/string.h>
38#include <iprt/list.h>
39#include "internal/dvm.h"
40
41
42/*********************************************************************************************************************************
43* Structures and Typedefs *
44*********************************************************************************************************************************/
45
46/**
47 * The internal volume manager structure.
48 */
49typedef struct RTDVMINTERNAL
50{
51 /** The DVM magic (RTDVM_MAGIC). */
52 uint32_t u32Magic;
53 /** The disk descriptor. */
54 RTDVMDISK DvmDisk;
55 /** Pointer to the backend operations table after a successful probe. */
56 PCRTDVMFMTOPS pDvmFmtOps;
57 /** The format specific volume manager data. */
58 RTDVMFMT hVolMgrFmt;
59 /** Flags passed on manager creation. */
60 uint32_t fFlags;
61 /** Reference counter. */
62 uint32_t volatile cRefs;
63 /** List of recognised volumes (RTDVMVOLUMEINTERNAL). */
64 RTLISTANCHOR VolumeList;
65} RTDVMINTERNAL;
66/** Pointer to an internal volume manager. */
67typedef RTDVMINTERNAL *PRTDVMINTERNAL;
68
69/**
70 * The internal volume structure.
71 */
72typedef struct RTDVMVOLUMEINTERNAL
73{
74 /** The DVM volume magic (RTDVMVOLUME_MAGIC). */
75 uint32_t u32Magic;
76 /** Node for the volume list. */
77 RTLISTNODE VolumeNode;
78 /** Pointer to the owning volume manager. */
79 PRTDVMINTERNAL pVolMgr;
80 /** Format specific volume data. */
81 RTDVMVOLUMEFMT hVolFmt;
82 /** Set block status.callback */
83 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus;
84 /** Opaque user data. */
85 void *pvUser;
86 /** Reference counter. */
87 uint32_t volatile cRefs;
88} RTDVMVOLUMEINTERNAL;
89/** Pointer to an internal volume. */
90typedef RTDVMVOLUMEINTERNAL *PRTDVMVOLUMEINTERNAL;
91
92
93/*********************************************************************************************************************************
94* Global variables *
95*********************************************************************************************************************************/
96extern RTDVMFMTOPS g_rtDvmFmtMbr;
97extern RTDVMFMTOPS g_rtDvmFmtGpt;
98extern RTDVMFMTOPS g_rtDvmFmtBsdLbl;
99
100/**
101 * Supported volume formats.
102 */
103static PCRTDVMFMTOPS g_aDvmFmts[] =
104{
105 &g_rtDvmFmtMbr,
106 &g_rtDvmFmtGpt,
107 &g_rtDvmFmtBsdLbl
108};
109
110/**
111 * Descriptions of the volume types.
112 *
113 * This is indexed by RTDVMVOLTYPE.
114 */
115static const char * g_apcszDvmVolTypes[] =
116{
117 "Invalid",
118 "Unknown",
119 "NTFS",
120 "FAT16",
121 "FAT32",
122 "Linux swap",
123 "Linux native",
124 "Linux LVM",
125 "Linux SoftRaid",
126 "FreeBSD",
127 "NetBSD",
128 "OpenBSD",
129 "Mac OS X HFS or HFS+",
130 "Solaris"
131};
132
133/**
134 * Creates a new volume.
135 *
136 * @returns IPRT status code.
137 * @param pThis The DVM map instance.
138 * @param hVolFmt The format specific volume handle.
139 * @param phVol Where to store the generic volume handle on success.
140 */
141static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt,
142 PRTDVMVOLUME phVol)
143{
144 int rc = VINF_SUCCESS;
145 PRTDVMVOLUMEINTERNAL pVol = NULL;
146
147 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL));
148 if (pVol)
149 {
150 pVol->u32Magic = RTDVMVOLUME_MAGIC;
151 pVol->cRefs = 0;
152 pVol->pVolMgr = pThis;
153 pVol->hVolFmt = hVolFmt;
154
155 *phVol = pVol;
156 }
157 else
158 rc = VERR_NO_MEMORY;
159
160 return rc;
161}
162
163/**
164 * Destroys a volume handle.
165 *
166 * @param pThis The volume to destroy.
167 */
168static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)
169{
170 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr;
171
172 AssertPtr(pVolMgr);
173
174 /* Close the volume. */
175 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);
176
177 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD;
178 pThis->pVolMgr = NULL;
179 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT;
180 RTMemFree(pThis);
181
182 /* Release the reference of the volume manager. */
183 RTDvmRelease(pVolMgr);
184}
185
186RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead,
187 PFNDVMWRITE pfnWrite, uint64_t cbDisk,
188 uint64_t cbSector, uint32_t fFlags, void *pvUser)
189{
190 int rc = VINF_SUCCESS;
191 PRTDVMINTERNAL pThis;
192
193 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_MASK),
194 ("Invalid flags given %#x\n", fFlags),
195 VERR_INVALID_PARAMETER);
196
197 pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
198 if (pThis)
199 {
200 pThis->u32Magic = RTDVM_MAGIC;
201 pThis->DvmDisk.cbDisk = cbDisk;
202 pThis->DvmDisk.cbSector = cbSector;
203 pThis->DvmDisk.pvUser = pvUser;
204 pThis->DvmDisk.pfnRead = pfnRead;
205 pThis->DvmDisk.pfnWrite = pfnWrite;
206 pThis->pDvmFmtOps = NULL;
207 pThis->hVolMgrFmt = NIL_RTDVMFMT;
208 pThis->fFlags = fFlags;
209 pThis->cRefs = 1;
210 RTListInit(&pThis->VolumeList);
211 *phVolMgr = pThis;
212 }
213 else
214 rc = VERR_NO_MEMORY;
215
216 return rc;
217}
218
219RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr)
220{
221 PRTDVMINTERNAL pThis = hVolMgr;
222 AssertPtrReturn(pThis, UINT32_MAX);
223 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
224
225 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
226 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
227 return cRefs;
228}
229
230/**
231 * Destroys a volume manager handle.
232 *
233 * @param pThis The volume manager to destroy.
234 */
235static void rtDvmDestroy(PRTDVMINTERNAL pThis)
236{
237 if (pThis->hVolMgrFmt != NIL_RTDVMFMT)
238 {
239 AssertPtr(pThis->pDvmFmtOps);
240
241 /* Let the backend do it's own cleanup first. */
242 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt);
243 pThis->hVolMgrFmt = NIL_RTDVMFMT;
244 }
245
246 pThis->DvmDisk.cbDisk = 0;
247 pThis->DvmDisk.pvUser = NULL;
248 pThis->DvmDisk.pfnRead = NULL;
249 pThis->DvmDisk.pfnWrite = NULL;
250 pThis->u32Magic = RTDVM_MAGIC_DEAD;
251 RTMemFree(pThis);
252}
253
254RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr)
255{
256 PRTDVMINTERNAL pThis = hVolMgr;
257 if (pThis == NIL_RTDVM)
258 return 0;
259 AssertPtrReturn(pThis, UINT32_MAX);
260 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
261
262 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
263 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
264 if (cRefs == 0)
265 rtDvmDestroy(pThis);
266 return cRefs;
267}
268
269RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr)
270{
271 int rc = VINF_SUCCESS;
272 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
273 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL;
274 PRTDVMINTERNAL pThis = hVolMgr;
275 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
276 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
277 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
278
279 Assert(!pThis->pDvmFmtOps);
280
281 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
282 {
283 uint32_t uScore;
284 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
285
286 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
287 if ( RT_SUCCESS(rc)
288 && uScore > uScoreMax)
289 {
290 pDvmFmtOpsMatch = pDvmFmtOps;
291 uScoreMax = uScore;
292 }
293 else if (RT_FAILURE(rc))
294 break;
295 }
296
297 if (RT_SUCCESS(rc))
298 {
299 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED)
300 {
301 AssertPtr(pDvmFmtOpsMatch);
302
303 /* Open the format. */
304 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
305 if (RT_SUCCESS(rc))
306 {
307 uint32_t cVols;
308
309 pThis->pDvmFmtOps = pDvmFmtOpsMatch;
310
311 cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
312
313 /* Construct volume list. */
314 if (cVols)
315 {
316 PRTDVMVOLUMEINTERNAL pVol = NULL;
317 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT;
318
319 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
320 if (RT_SUCCESS(rc))
321 {
322 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol);
323 if (RT_FAILURE(rc))
324 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
325 }
326
327 if (RT_SUCCESS(rc))
328 {
329 cVols--;
330 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode);
331
332 while ( cVols > 0
333 && RT_SUCCESS(rc))
334 {
335 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt);
336 if (RT_SUCCESS(rc))
337 {
338 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol);
339 if (RT_FAILURE(rc))
340 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
341 else
342 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode);
343 cVols--;
344 }
345 }
346 }
347
348 if (RT_FAILURE(rc))
349 {
350 PRTDVMVOLUMEINTERNAL pItNext, pIt;
351
352 /* Remove all entries. */
353 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode)
354 {
355 RTListNodeRemove(&pIt->VolumeNode);
356 rtDvmVolumeDestroy(pIt);
357 }
358 }
359 }
360 }
361 }
362 else
363 rc = VERR_NOT_SUPPORTED;
364 }
365
366 return rc;
367}
368
369RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
370{
371 int rc = VERR_NOT_SUPPORTED;
372 PRTDVMINTERNAL pThis = hVolMgr;
373 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
374 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER);
375 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
376 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);
377
378 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
379 {
380 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
381
382 if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt))
383 {
384 rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
385 if (RT_SUCCESS(rc))
386 pThis->pDvmFmtOps = pDvmFmtOps;
387
388 break;
389 }
390 }
391
392 return rc;
393}
394
395RTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr)
396{
397 PRTDVMINTERNAL pThis = hVolMgr;
398 AssertPtrReturn(pThis, NULL);
399 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
400 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
401
402 return pThis->pDvmFmtOps->pcszFmt;
403}
404
405RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
406{
407 PRTDVMINTERNAL pThis = hVolMgr;
408 AssertPtrReturn(pThis, UINT32_MAX);
409 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
410 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
411
412 return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
413}
414
415RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
416{
417 PRTDVMINTERNAL pThis = hVolMgr;
418 AssertPtrReturn(pThis, UINT32_MAX);
419 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
420 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
421
422 return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
423}
424
425RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
426{
427 int rc = VERR_DVM_MAP_EMPTY;
428 PRTDVMINTERNAL pThis = hVolMgr;
429 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
430 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
431 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
432 AssertPtrReturn(phVol, VERR_INVALID_POINTER);
433
434 PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode);
435 if (pVol)
436 {
437 rc = VINF_SUCCESS;
438 RTDvmVolumeRetain(pVol);
439 *phVol = pVol;
440 }
441
442 return rc;
443}
444
445RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
446{
447 int rc = VERR_DVM_MAP_NO_VOLUME;
448 PRTDVMINTERNAL pThis = hVolMgr;
449 PRTDVMVOLUMEINTERNAL pVol = hVol;
450 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
451 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
452 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
453 AssertPtrReturn(pVol, VERR_INVALID_HANDLE);
454 AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
455 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER);
456
457 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol,
458 RTDVMVOLUMEINTERNAL, VolumeNode);
459 if (pVolNext)
460 {
461 rc = VINF_SUCCESS;
462 RTDvmVolumeRetain(pVolNext);
463 *phVolNext = pVolNext;
464 }
465
466 return rc;
467}
468
469RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb,
470 bool *pfAllocated)
471{
472 int rc = VINF_SUCCESS;
473 PRTDVMINTERNAL pThis = hVolMgr;
474 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
475 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER);
476 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
477 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
478 AssertReturn(off + cb <= pThis->DvmDisk.cbDisk * pThis->DvmDisk.cbSector,
479 VERR_INVALID_PARAMETER);
480
481 /* Check whether the range is inuse by the volume manager metadata first. */
482 rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
483 if (RT_FAILURE(rc))
484 return rc;
485
486 if (!*pfAllocated)
487 {
488 bool fAllocated = false;
489
490 while ( cb > 0
491 && !fAllocated)
492 {
493 PRTDVMVOLUMEINTERNAL pVol;
494 bool fVolFound = false;
495 uint64_t cbIntersect;
496 uint64_t offVol;
497
498 /*
499 * Search through all volumes. It is not possible to
500 * get all start sectors and sizes of all volumes here
501 * because volumes can be scattered around the disk for certain formats.
502 * Linux LVM is one example, extents of logical volumes don't need to be
503 * contigous on the medium.
504 */
505 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
506 {
507 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off,
508 cb, &offVol,
509 &cbIntersect);
510 if (fIntersect)
511 {
512 fVolFound = true;
513 if (pVol->pfnQueryBlockStatus)
514 {
515 bool fVolAllocated = true;
516
517 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect,
518 &fVolAllocated);
519 if (RT_FAILURE(rc))
520 break;
521 else if (fVolAllocated)
522 {
523 fAllocated = true;
524 break;
525 }
526 }
527 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
528 fAllocated = true;
529 /* else, flag is set, continue. */
530
531 cb -= cbIntersect;
532 off += cbIntersect;
533 break;
534 }
535 }
536
537 if (!fVolFound)
538 {
539 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
540 fAllocated = true;
541
542 cb -= pThis->DvmDisk.cbSector;
543 off += pThis->DvmDisk.cbSector;
544 }
545 }
546
547 *pfAllocated = fAllocated;
548 }
549
550 return rc;
551}
552
553RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
554{
555 PRTDVMVOLUMEINTERNAL pThis = hVol;
556 AssertPtrReturn(pThis, UINT32_MAX);
557 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
558
559 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
560 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
561 if (cRefs == 1)
562 RTDvmRetain(pThis->pVolMgr);
563 return cRefs;
564}
565
566RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
567{
568 PRTDVMVOLUMEINTERNAL pThis = hVol;
569 if (pThis == NIL_RTDVMVOLUME)
570 return 0;
571 AssertPtrReturn(pThis, UINT32_MAX);
572 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
573
574 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
575 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
576 if (cRefs == 0)
577 {
578 /* Release the volume manager. */
579 pThis->pfnQueryBlockStatus = NULL;
580 RTDvmRelease(pThis->pVolMgr);
581 }
582 return cRefs;
583}
584
585RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
586 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
587 void *pvUser)
588{
589 PRTDVMVOLUMEINTERNAL pThis = hVol;
590 AssertPtrReturnVoid(pThis);
591 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC);
592
593 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus;
594 pThis->pvUser = pvUser;
595}
596
597RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
598{
599 PRTDVMVOLUMEINTERNAL pThis = hVol;
600 AssertPtrReturn(pThis, 0);
601 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
602
603 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
604}
605
606RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
607{
608 PRTDVMVOLUMEINTERNAL pThis = hVol;
609 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
610 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
611 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
612
613 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
614}
615
616RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
617{
618 PRTDVMVOLUMEINTERNAL pThis = hVol;
619 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
620 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
621
622 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
623}
624
625RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
626{
627 PRTDVMVOLUMEINTERNAL pThis = hVol;
628 AssertPtrReturn(pThis, UINT64_MAX);
629 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
630
631 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
632}
633
634RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
635{
636 PRTDVMVOLUMEINTERNAL pThis = hVol;
637 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
638 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
639 AssertReturn(pvBuf, VERR_INVALID_POINTER);
640 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
641
642 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
643}
644
645RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
646{
647 PRTDVMVOLUMEINTERNAL pThis = hVol;
648 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
649 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
650 AssertReturn(pvBuf, VERR_INVALID_POINTER);
651 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
652
653 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
654}
655
656RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
657{
658 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL);
659
660 return g_apcszDvmVolTypes[enmVolType];
661}
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