VirtualBox

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

Last change on this file since 45395 was 44529, checked in by vboxsync, 12 years ago

header (C) fixes

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