VirtualBox

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

Last change on this file since 69609 was 69609, checked in by vboxsync, 7 years ago

iprt/dvm: Some API adjusting to VFS - work in progress.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1/* $Id: dvm.cpp 69609 2017-11-07 18:59:38Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - generic code.
4 */
5
6/*
7 * Copyright (C) 2011-2017 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 const 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 * const g_apszDvmVolTypes[] =
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};
132AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END);
133
134
135/**
136 * Creates a new volume.
137 *
138 * @returns IPRT status code.
139 * @param pThis The DVM map instance.
140 * @param hVolFmt The format specific volume handle.
141 * @param phVol Where to store the generic volume handle on success.
142 */
143static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUME phVol)
144{
145 PRTDVMVOLUMEINTERNAL 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 return VINF_SUCCESS;
155 }
156 return VERR_NO_MEMORY;
157}
158
159/**
160 * Destroys a volume handle.
161 *
162 * @param pThis The volume to destroy.
163 */
164static void rtDvmVolumeDestroy(PRTDVMVOLUMEINTERNAL pThis)
165{
166 PRTDVMINTERNAL pVolMgr = pThis->pVolMgr;
167
168 AssertPtr(pVolMgr);
169
170 /* Close the volume. */
171 pVolMgr->pDvmFmtOps->pfnVolumeClose(pThis->hVolFmt);
172
173 pThis->u32Magic = RTDVMVOLUME_MAGIC_DEAD;
174 pThis->pVolMgr = NULL;
175 pThis->hVolFmt = NIL_RTDVMVOLUMEFMT;
176 RTMemFree(pThis);
177
178 /* Release the reference of the volume manager. */
179 RTDvmRelease(pVolMgr);
180}
181
182
183RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags)
184{
185 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_VALID_MASK), ("Invalid flags given %#x\n", fFlags), VERR_INVALID_FLAGS);
186 uint32_t cRefs = RTVfsFileRetain(hVfsFile);
187 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
188
189 uint64_t cbDisk;
190 int rc = RTVfsFileGetSize(hVfsFile, &cbDisk);
191 if (RT_SUCCESS(rc))
192 {
193 PRTDVMINTERNAL pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));
194 if (pThis)
195 {
196 pThis->u32Magic = RTDVM_MAGIC;
197 pThis->DvmDisk.cbDisk = cbDisk;
198 pThis->DvmDisk.cbSector = cbSector;
199 pThis->DvmDisk.hVfsFile = hVfsFile;
200
201 pThis->pDvmFmtOps = NULL;
202 pThis->hVolMgrFmt = NIL_RTDVMFMT;
203 pThis->fFlags = fFlags;
204 pThis->cRefs = 1;
205 RTListInit(&pThis->VolumeList);
206
207 *phVolMgr = pThis;
208 return VINF_SUCCESS;
209 }
210 rc = VERR_NO_MEMORY;
211 }
212 RTVfsFileRelease(hVfsFile);
213 return rc;
214}
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 pThis->u32Magic = RTDVM_MAGIC_DEAD;
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 pThis->pDvmFmtOps = NULL;
245 }
246
247 pThis->DvmDisk.cbDisk = 0;
248 pThis->DvmDisk.cbSector = 0;
249 if (pThis->DvmDisk.hVfsFile != NIL_RTVFSFILE)
250 {
251 RTVfsFileRelease(pThis->DvmDisk.hVfsFile);
252 pThis->DvmDisk.hVfsFile = NIL_RTVFSFILE;
253 }
254 RTMemFree(pThis);
255}
256
257RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr)
258{
259 PRTDVMINTERNAL pThis = hVolMgr;
260 if (pThis == NIL_RTDVM)
261 return 0;
262 AssertPtrReturn(pThis, UINT32_MAX);
263 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
264
265 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
266 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
267 if (cRefs == 0)
268 rtDvmDestroy(pThis);
269 return cRefs;
270}
271
272RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr)
273{
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_WRONG_ORDER);
278
279 Assert(!pThis->pDvmFmtOps);
280
281 /*
282 * Let each format backend have a go at the disk, pick the one which scores the highest.
283 */
284 int rc = VINF_SUCCESS;
285 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED;
286 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL;
287 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
288 {
289 uint32_t uScore = 0;
290 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
291
292 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore);
293 if (RT_SUCCESS(rc))
294 {
295 if (uScore > uScoreMax)
296 {
297 pDvmFmtOpsMatch = pDvmFmtOps;
298 uScoreMax = uScore;
299 }
300 }
301 else
302 return rc;
303 }
304 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED)
305 {
306 AssertPtr(pDvmFmtOpsMatch);
307
308 /*
309 * Open the format.
310 */
311 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt);
312 if (RT_SUCCESS(rc))
313 {
314 pThis->pDvmFmtOps = pDvmFmtOpsMatch;
315
316 /*
317 * Construct volume list (we're done if none).
318 */
319 uint32_t cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
320 if (cVols == 0)
321 return VINF_SUCCESS;
322
323 /* First volume. */
324 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT;
325 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt);
326 if (RT_SUCCESS(rc))
327 {
328 for (;;)
329 {
330 PRTDVMVOLUMEINTERNAL pVol = NULL;
331 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol);
332 if (RT_FAILURE(rc))
333 {
334 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt);
335 break;
336 }
337 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode);
338
339 /* Done?*/
340 cVols--;
341 if (cVols < 1)
342 return VINF_SUCCESS;
343
344 /* Next volume. */
345 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt);
346 if (RT_FAILURE(rc))
347 break;
348 }
349
350 /* Bail out. */
351 PRTDVMVOLUMEINTERNAL pItNext, pIt;
352 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode)
353 {
354 RTListNodeRemove(&pIt->VolumeNode);
355 rtDvmVolumeDestroy(pIt);
356 }
357 }
358
359 /** @todo shouldn't we close the format too here? */
360 }
361 }
362 else
363 rc = VERR_NOT_SUPPORTED;
364 return rc;
365}
366
367RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt)
368{
369 PRTDVMINTERNAL pThis = hVolMgr;
370 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
371 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER);
372 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
373 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER);
374
375 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++)
376 {
377 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
378 if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt))
379 {
380 int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
381 if (RT_SUCCESS(rc))
382 pThis->pDvmFmtOps = pDvmFmtOps;
383 return rc;
384 }
385 }
386 return VERR_NOT_SUPPORTED;
387}
388
389RTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr)
390{
391 PRTDVMINTERNAL pThis = hVolMgr;
392 AssertPtrReturn(pThis, NULL);
393 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, NULL);
394 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
395
396 return pThis->pDvmFmtOps->pcszFmt;
397}
398
399RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr)
400{
401 PRTDVMINTERNAL pThis = hVolMgr;
402 AssertPtrReturn(pThis, UINT32_MAX);
403 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
404 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
405
406 return pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt);
407}
408
409RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr)
410{
411 PRTDVMINTERNAL pThis = hVolMgr;
412 AssertPtrReturn(pThis, UINT32_MAX);
413 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, UINT32_MAX);
414 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, UINT32_MAX);
415
416 return pThis->pDvmFmtOps->pfnGetMaxVolumes(pThis->hVolMgrFmt);
417}
418
419RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
420{
421 int rc = VERR_DVM_MAP_EMPTY;
422 PRTDVMINTERNAL pThis = hVolMgr;
423 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
424 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
425 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
426 AssertPtrReturn(phVol, VERR_INVALID_POINTER);
427
428 PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode);
429 if (pVol)
430 {
431 rc = VINF_SUCCESS;
432 RTDvmVolumeRetain(pVol);
433 *phVol = pVol;
434 }
435
436 return rc;
437}
438
439RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext)
440{
441 PRTDVMINTERNAL pThis = hVolMgr;
442 PRTDVMVOLUMEINTERNAL pVol = hVol;
443 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
444 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
445 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
446 AssertPtrReturn(pVol, VERR_INVALID_HANDLE);
447 AssertReturn(pVol->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
448 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER);
449
450 int rc = VERR_DVM_MAP_NO_VOLUME;
451 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode);
452 if (pVolNext)
453 {
454 rc = VINF_SUCCESS;
455 RTDvmVolumeRetain(pVolNext);
456 *phVolNext = pVolNext;
457 }
458
459 return rc;
460}
461
462RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated)
463{
464 PRTDVMINTERNAL pThis = hVolMgr;
465 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
466 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER);
467 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
468 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER);
469 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk
470 || cb <= pThis->DvmDisk.cbDisk
471 || off + cb <= pThis->DvmDisk.cbDisk,
472 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk),
473 VERR_OUT_OF_RANGE);
474
475 /* Check whether the range is inuse by the volume manager metadata first. */
476 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
477 if (RT_FAILURE(rc))
478 return rc;
479
480 if (!*pfAllocated)
481 {
482 bool fAllocated = false;
483
484 while ( cb > 0
485 && !fAllocated)
486 {
487 bool fVolFound = false;
488 uint64_t cbIntersect;
489 uint64_t offVol;
490
491 /*
492 * Search through all volumes. It is not possible to
493 * get all start sectors and sizes of all volumes here
494 * because volumes can be scattered around the disk for certain formats.
495 * Linux LVM is one example, extents of logical volumes don't need to be
496 * contigous on the medium.
497 */
498 PRTDVMVOLUMEINTERNAL pVol;
499 RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
500 {
501 bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off,
502 cb, &offVol,
503 &cbIntersect);
504 if (fIntersect)
505 {
506 fVolFound = true;
507 if (pVol->pfnQueryBlockStatus)
508 {
509 bool fVolAllocated = true;
510 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated);
511 if (RT_FAILURE(rc))
512 break;
513 if (fVolAllocated)
514 {
515 fAllocated = true;
516 break;
517 }
518 }
519 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
520 fAllocated = true;
521 /* else, flag is set, continue. */
522
523 cb -= cbIntersect;
524 off += cbIntersect;
525 break;
526 }
527 }
528
529 if (!fVolFound)
530 {
531 if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
532 fAllocated = true;
533
534 cb -= pThis->DvmDisk.cbSector;
535 off += pThis->DvmDisk.cbSector;
536 }
537 }
538
539 *pfAllocated = fAllocated;
540 }
541
542 return rc;
543}
544
545RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol)
546{
547 PRTDVMVOLUMEINTERNAL pThis = hVol;
548 AssertPtrReturn(pThis, UINT32_MAX);
549 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
550
551 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
552 AssertMsg(cRefs >= 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
553 if (cRefs == 1)
554 RTDvmRetain(pThis->pVolMgr);
555 return cRefs;
556}
557
558RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol)
559{
560 PRTDVMVOLUMEINTERNAL pThis = hVol;
561 if (pThis == NIL_RTDVMVOLUME)
562 return 0;
563 AssertPtrReturn(pThis, UINT32_MAX);
564 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
565
566 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
567 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
568 if (cRefs == 0)
569 {
570 /* Release the volume manager. */
571 pThis->pfnQueryBlockStatus = NULL;
572 RTDvmRelease(pThis->pVolMgr);
573 }
574 return cRefs;
575}
576
577RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
578 PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
579 void *pvUser)
580{
581 PRTDVMVOLUMEINTERNAL pThis = hVol;
582 AssertPtrReturnVoid(pThis);
583 AssertReturnVoid(pThis->u32Magic == RTDVMVOLUME_MAGIC);
584
585 pThis->pfnQueryBlockStatus = pfnQueryBlockStatus;
586 pThis->pvUser = pvUser;
587}
588
589RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol)
590{
591 PRTDVMVOLUMEINTERNAL pThis = hVol;
592 AssertPtrReturn(pThis, 0);
593 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, 0);
594
595 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetSize(pThis->hVolFmt);
596}
597
598RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName)
599{
600 PRTDVMVOLUMEINTERNAL pThis = hVol;
601 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
602 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
603 AssertReturn(ppszVolName, VERR_INVALID_POINTER);
604
605 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryName(pThis->hVolFmt, ppszVolName);
606}
607
608RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol)
609{
610 PRTDVMVOLUMEINTERNAL pThis = hVol;
611 AssertPtrReturn(pThis, RTDVMVOLTYPE_INVALID);
612 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, RTDVMVOLTYPE_INVALID);
613
614 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetType(pThis->hVolFmt);
615}
616
617RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol)
618{
619 PRTDVMVOLUMEINTERNAL pThis = hVol;
620 AssertPtrReturn(pThis, UINT64_MAX);
621 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT64_MAX);
622
623 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetFlags(pThis->hVolFmt);
624}
625
626RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
627{
628 PRTDVMVOLUMEINTERNAL pThis = hVol;
629 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
630 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
631 AssertReturn(pvBuf, VERR_INVALID_POINTER);
632 AssertReturn(cbRead > 0, VERR_INVALID_PARAMETER);
633
634 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeRead(pThis->hVolFmt, off, pvBuf, cbRead);
635}
636
637RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite)
638{
639 PRTDVMVOLUMEINTERNAL pThis = hVol;
640 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
641 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
642 AssertReturn(pvBuf, VERR_INVALID_POINTER);
643 AssertReturn(cbWrite > 0, VERR_INVALID_PARAMETER);
644
645 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeWrite(pThis->hVolFmt, off, pvBuf, cbWrite);
646}
647
648RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType)
649{
650 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL);
651
652 return g_apszDvmVolTypes[enmVolType];
653}
654
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