[41576] | 1 | /* $Id: VDIfVfs.cpp 100908 2023-08-19 02:57:05Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
[47345] | 3 | * Virtual Disk Image (VDI), I/O interface to IPRT VFS I/O stream glue.
|
---|
[41576] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2012-2023 Oracle and/or its affiliates.
|
---|
[41576] | 8 | *
|
---|
[96407] | 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
|
---|
[41576] | 26 | */
|
---|
| 27 |
|
---|
| 28 |
|
---|
[57358] | 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
[41576] | 32 | #include <iprt/types.h>
|
---|
| 33 | #include <iprt/assert.h>
|
---|
| 34 | #include <iprt/mem.h>
|
---|
| 35 | #include <iprt/err.h>
|
---|
| 36 | #include <iprt/asm.h>
|
---|
| 37 | #include <iprt/string.h>
|
---|
| 38 | #include <iprt/file.h>
|
---|
| 39 | #include <iprt/sg.h>
|
---|
| 40 | #include <iprt/vfslowlevel.h>
|
---|
| 41 | #include <iprt/poll.h>
|
---|
| 42 | #include <VBox/vd.h>
|
---|
[48854] | 43 | #include <VBox/vd-ifs-internal.h>
|
---|
[41576] | 44 |
|
---|
| 45 |
|
---|
[57358] | 46 | /*********************************************************************************************************************************
|
---|
| 47 | * Structures and Typedefs *
|
---|
| 48 | *********************************************************************************************************************************/
|
---|
| 49 |
|
---|
[41576] | 50 | /**
|
---|
[48849] | 51 | * The internal data of an VD I/O to VFS file or I/O stream wrapper.
|
---|
[41576] | 52 | */
|
---|
[48849] | 53 | typedef struct VDIFVFSIOSFILE
|
---|
[41576] | 54 | {
|
---|
[48854] | 55 | /** The VD I/O interface we prefer wrap.
|
---|
| 56 | * Can be NULL, in which case pVDIfsIoInt must be valid. */
|
---|
| 57 | PVDINTERFACEIO pVDIfsIo;
|
---|
| 58 | /** The VD I/O interface we alternatively can wrap.
|
---|
| 59 | Can be NULL, in which case pVDIfsIo must be valid. */
|
---|
| 60 | PVDINTERFACEIOINT pVDIfsIoInt;
|
---|
[47345] | 61 | /** User pointer to pass to the VD I/O interface methods. */
|
---|
[48854] | 62 | PVDIOSTORAGE pStorage;
|
---|
[48849] | 63 | /** The current stream position. */
|
---|
[48854] | 64 | RTFOFF offCurPos;
|
---|
[48849] | 65 | } VDIFVFSIOSFILE;
|
---|
[41576] | 66 | /** Pointer to a the internal data of a DVM volume file. */
|
---|
[48849] | 67 | typedef VDIFVFSIOSFILE *PVDIFVFSIOSFILE;
|
---|
[41576] | 68 |
|
---|
| 69 |
|
---|
| 70 |
|
---|
| 71 | /**
|
---|
| 72 | * @interface_method_impl{RTVFSOBJOPS,pfnClose}
|
---|
| 73 | */
|
---|
[47345] | 74 | static DECLCALLBACK(int) vdIfVfsIos_Close(void *pvThis)
|
---|
[41576] | 75 | {
|
---|
[47345] | 76 | /* We don't close anything. */
|
---|
[62729] | 77 | RT_NOREF1(pvThis);
|
---|
[41576] | 78 | return VINF_SUCCESS;
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 |
|
---|
| 82 | /**
|
---|
| 83 | * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
|
---|
| 84 | */
|
---|
[47345] | 85 | static DECLCALLBACK(int) vdIfVfsIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
|
---|
[41576] | 86 | {
|
---|
| 87 | NOREF(pvThis);
|
---|
| 88 | NOREF(pObjInfo);
|
---|
| 89 | NOREF(enmAddAttr);
|
---|
| 90 | return VERR_NOT_SUPPORTED;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 |
|
---|
| 94 | /**
|
---|
| 95 | * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
|
---|
| 96 | */
|
---|
[100908] | 97 | static DECLCALLBACK(int) vdIfVfsIos_Read(void *pvThis, RTFOFF off, PRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
|
---|
[41576] | 98 | {
|
---|
[48849] | 99 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
[47345] | 100 | Assert(pSgBuf->cSegs == 1); NOREF(fBlocking);
|
---|
[48849] | 101 | Assert(off >= -1);
|
---|
[41576] | 102 |
|
---|
[100908] | 103 | size_t cbSeg = 0;
|
---|
| 104 | void * const pvSeg = RTSgBufGetCurrentSegment(pSgBuf, ~(size_t)0, &cbSeg);
|
---|
| 105 |
|
---|
[41576] | 106 | /*
|
---|
[47345] | 107 | * This may end up being a little more complicated, esp. wrt VERR_EOF.
|
---|
[41576] | 108 | */
|
---|
[47665] | 109 | if (off == -1)
|
---|
| 110 | off = pThis->offCurPos;
|
---|
[48854] | 111 | int rc;
|
---|
| 112 | if (pThis->pVDIfsIo)
|
---|
[100908] | 113 | rc = vdIfIoFileReadSync(pThis->pVDIfsIo, pThis->pStorage, off, pvSeg, cbSeg, pcbRead);
|
---|
[48854] | 114 | else
|
---|
| 115 | {
|
---|
[100908] | 116 | rc = vdIfIoIntFileReadSync(pThis->pVDIfsIoInt, (PVDIOSTORAGE)pThis->pStorage, off, pvSeg, cbSeg);
|
---|
[48854] | 117 | if (pcbRead)
|
---|
[100908] | 118 | *pcbRead = RT_SUCCESS(rc) ? cbSeg : 0;
|
---|
[48854] | 119 | }
|
---|
[47345] | 120 | if (RT_SUCCESS(rc))
|
---|
[48176] | 121 | {
|
---|
[100908] | 122 | size_t const cbAdvance = pcbRead ? *pcbRead : cbSeg;
|
---|
[48176] | 123 | pThis->offCurPos = off + cbAdvance;
|
---|
[100908] | 124 | RTSgBufAdvance(pSgBuf, cbAdvance);
|
---|
[48176] | 125 | if (pcbRead && !cbAdvance)
|
---|
| 126 | rc = VINF_EOF;
|
---|
| 127 | }
|
---|
[41576] | 128 | return rc;
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 |
|
---|
| 132 | /**
|
---|
| 133 | * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
|
---|
| 134 | */
|
---|
[100908] | 135 | static DECLCALLBACK(int) vdIfVfsIos_Write(void *pvThis, RTFOFF off, PRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
|
---|
[41576] | 136 | {
|
---|
[48849] | 137 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
[47345] | 138 | Assert(pSgBuf->cSegs == 1); NOREF(fBlocking);
|
---|
[48849] | 139 | Assert(off >= -1);
|
---|
[41576] | 140 |
|
---|
[100908] | 141 | size_t cbSeg = 0;
|
---|
| 142 | void const * const pvSeg = RTSgBufGetCurrentSegment(pSgBuf, ~(size_t)0, &cbSeg);
|
---|
| 143 |
|
---|
[41576] | 144 | /*
|
---|
[100908] | 145 | * Do the writing.
|
---|
[41576] | 146 | */
|
---|
[47665] | 147 | if (off == -1)
|
---|
| 148 | off = pThis->offCurPos;
|
---|
[48854] | 149 | int rc;
|
---|
| 150 | if (pThis->pVDIfsIo)
|
---|
[100908] | 151 | rc = vdIfIoFileWriteSync(pThis->pVDIfsIo, pThis->pStorage, off, pvSeg, cbSeg, pcbWritten);
|
---|
[48854] | 152 | else
|
---|
| 153 | {
|
---|
[100908] | 154 | rc = vdIfIoIntFileWriteSync(pThis->pVDIfsIoInt, pThis->pStorage, off, pvSeg, cbSeg);
|
---|
[48854] | 155 | if (pcbWritten)
|
---|
[100908] | 156 | *pcbWritten = RT_SUCCESS(rc) ? cbSeg : 0;
|
---|
[48854] | 157 | }
|
---|
[47345] | 158 | if (RT_SUCCESS(rc))
|
---|
[100908] | 159 | {
|
---|
| 160 | size_t const cbAdvance = pcbWritten ? *pcbWritten : cbSeg;
|
---|
| 161 | pThis->offCurPos = off + cbAdvance;
|
---|
| 162 | RTSgBufAdvance(pSgBuf, cbAdvance);
|
---|
| 163 | }
|
---|
[41576] | 164 | return rc;
|
---|
| 165 | }
|
---|
| 166 |
|
---|
| 167 |
|
---|
| 168 | /**
|
---|
| 169 | * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
|
---|
| 170 | */
|
---|
[47345] | 171 | static DECLCALLBACK(int) vdIfVfsIos_Flush(void *pvThis)
|
---|
[41576] | 172 | {
|
---|
[48849] | 173 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
[48854] | 174 | int rc;
|
---|
| 175 | if (pThis->pVDIfsIo)
|
---|
| 176 | rc = vdIfIoFileFlushSync(pThis->pVDIfsIo, pThis->pStorage);
|
---|
| 177 | else
|
---|
| 178 | rc = vdIfIoIntFileFlushSync(pThis->pVDIfsIoInt, pThis->pStorage);
|
---|
| 179 | return rc;
|
---|
[41576] | 180 | }
|
---|
| 181 |
|
---|
| 182 |
|
---|
| 183 | /**
|
---|
| 184 | * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
|
---|
| 185 | */
|
---|
[47345] | 186 | static DECLCALLBACK(int) vdIfVfsIos_Tell(void *pvThis, PRTFOFF poffActual)
|
---|
[41576] | 187 | {
|
---|
[48849] | 188 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
[41576] | 189 | *poffActual = pThis->offCurPos;
|
---|
| 190 | return VINF_SUCCESS;
|
---|
| 191 | }
|
---|
| 192 |
|
---|
[48849] | 193 |
|
---|
[41576] | 194 | /**
|
---|
[48849] | 195 | * VFS I/O stream operations for a VD file or stream.
|
---|
[41576] | 196 | */
|
---|
[48849] | 197 | DECL_HIDDEN_CONST(const RTVFSIOSTREAMOPS) g_vdIfVfsIosOps =
|
---|
[41576] | 198 | {
|
---|
[47345] | 199 | { /* Obj */
|
---|
| 200 | RTVFSOBJOPS_VERSION,
|
---|
[47716] | 201 | RTVFSOBJTYPE_IO_STREAM,
|
---|
[47345] | 202 | "VDIfIos",
|
---|
| 203 | vdIfVfsIos_Close,
|
---|
| 204 | vdIfVfsIos_QueryInfo,
|
---|
[94291] | 205 | NULL,
|
---|
[47345] | 206 | RTVFSOBJOPS_VERSION
|
---|
[41576] | 207 | },
|
---|
[47345] | 208 | RTVFSIOSTREAMOPS_VERSION,
|
---|
| 209 | RTVFSIOSTREAMOPS_FEAT_NO_SG,
|
---|
| 210 | vdIfVfsIos_Read,
|
---|
| 211 | vdIfVfsIos_Write,
|
---|
| 212 | vdIfVfsIos_Flush,
|
---|
[69942] | 213 | NULL /*PollOne*/,
|
---|
[47345] | 214 | vdIfVfsIos_Tell,
|
---|
| 215 | NULL /*Skip*/,
|
---|
| 216 | NULL /*ZeroFill*/,
|
---|
| 217 | RTVFSIOSTREAMOPS_VERSION,
|
---|
[47716] | 218 |
|
---|
[41576] | 219 | };
|
---|
| 220 |
|
---|
[47345] | 221 | VBOXDDU_DECL(int) VDIfCreateVfsStream(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos)
|
---|
[41576] | 222 | {
|
---|
[47345] | 223 | AssertPtrReturn(pVDIfsIo, VERR_INVALID_HANDLE);
|
---|
| 224 | AssertPtrReturn(phVfsIos, VERR_INVALID_POINTER);
|
---|
[41576] | 225 |
|
---|
| 226 | /*
|
---|
| 227 | * Create the volume file.
|
---|
| 228 | */
|
---|
[47345] | 229 | RTVFSIOSTREAM hVfsIos;
|
---|
[48849] | 230 | PVDIFVFSIOSFILE pThis;
|
---|
| 231 | int rc = RTVfsNewIoStream(&g_vdIfVfsIosOps, sizeof(*pThis), fFlags,
|
---|
[47345] | 232 | NIL_RTVFS, NIL_RTVFSLOCK, &hVfsIos, (void **)&pThis);
|
---|
[41576] | 233 | if (RT_SUCCESS(rc))
|
---|
| 234 | {
|
---|
[48854] | 235 | pThis->pVDIfsIo = pVDIfsIo;
|
---|
| 236 | pThis->pVDIfsIoInt = NULL;
|
---|
| 237 | pThis->pStorage = (PVDIOSTORAGE)pvStorage;
|
---|
| 238 | pThis->offCurPos = 0;
|
---|
[41576] | 239 |
|
---|
[47345] | 240 | *phVfsIos = hVfsIos;
|
---|
[41576] | 241 | return VINF_SUCCESS;
|
---|
| 242 | }
|
---|
| 243 |
|
---|
| 244 | return rc;
|
---|
| 245 | }
|
---|
| 246 |
|
---|
[48849] | 247 |
|
---|
| 248 |
|
---|
| 249 | /**
|
---|
[58132] | 250 | * @interface_method_impl{RTVFSOBJSETOPS,pfnSetMode}
|
---|
[48849] | 251 | */
|
---|
| 252 | static DECLCALLBACK(int) vdIfVfsFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
|
---|
| 253 | {
|
---|
| 254 | NOREF(pvThis);
|
---|
| 255 | NOREF(fMode);
|
---|
| 256 | NOREF(fMask);
|
---|
| 257 | return VERR_NOT_SUPPORTED;
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 |
|
---|
| 261 | /**
|
---|
| 262 | * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
|
---|
| 263 | */
|
---|
| 264 | static DECLCALLBACK(int) vdIfVfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
|
---|
| 265 | PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
|
---|
| 266 | {
|
---|
| 267 | NOREF(pvThis);
|
---|
| 268 | NOREF(pAccessTime);
|
---|
| 269 | NOREF(pModificationTime);
|
---|
| 270 | NOREF(pChangeTime);
|
---|
| 271 | NOREF(pBirthTime);
|
---|
| 272 | return VERR_NOT_SUPPORTED;
|
---|
| 273 | }
|
---|
| 274 |
|
---|
| 275 |
|
---|
| 276 | /**
|
---|
| 277 | * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
|
---|
| 278 | */
|
---|
| 279 | static DECLCALLBACK(int) vdIfVfsFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
|
---|
| 280 | {
|
---|
| 281 | NOREF(pvThis);
|
---|
| 282 | NOREF(uid);
|
---|
| 283 | NOREF(gid);
|
---|
| 284 | return VERR_NOT_SUPPORTED;
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 |
|
---|
| 288 | /**
|
---|
| 289 | * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
|
---|
| 290 | */
|
---|
| 291 | static DECLCALLBACK(int) vdIfVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
|
---|
| 292 | {
|
---|
| 293 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
| 294 |
|
---|
| 295 | uint64_t cbFile;
|
---|
[48854] | 296 | int rc;
|
---|
| 297 | if (pThis->pVDIfsIo)
|
---|
| 298 | rc = vdIfIoFileGetSize(pThis->pVDIfsIo, pThis->pStorage, &cbFile);
|
---|
| 299 | else
|
---|
| 300 | rc = vdIfIoIntFileGetSize(pThis->pVDIfsIoInt, pThis->pStorage, &cbFile);
|
---|
[48849] | 301 | if (RT_FAILURE(rc))
|
---|
| 302 | return rc;
|
---|
| 303 | if (cbFile >= (uint64_t)RTFOFF_MAX)
|
---|
| 304 | cbFile = RTFOFF_MAX;
|
---|
| 305 |
|
---|
| 306 | /* Recalculate the request to RTFILE_SEEK_BEGIN. */
|
---|
| 307 | switch (uMethod)
|
---|
| 308 | {
|
---|
| 309 | case RTFILE_SEEK_BEGIN:
|
---|
| 310 | break;
|
---|
| 311 | case RTFILE_SEEK_CURRENT:
|
---|
| 312 | offSeek += pThis->offCurPos;
|
---|
| 313 | break;
|
---|
| 314 | case RTFILE_SEEK_END:
|
---|
| 315 | offSeek = cbFile + offSeek;
|
---|
| 316 | break;
|
---|
| 317 | default:
|
---|
| 318 | AssertFailedReturn(VERR_INVALID_PARAMETER);
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | /* Do limit checks. */
|
---|
| 322 | if (offSeek < 0)
|
---|
| 323 | offSeek = 0;
|
---|
| 324 | else if (offSeek > (RTFOFF)cbFile)
|
---|
| 325 | offSeek = cbFile;
|
---|
| 326 |
|
---|
| 327 | /* Apply and return. */
|
---|
| 328 | pThis->offCurPos = offSeek;
|
---|
| 329 | if (poffActual)
|
---|
| 330 | *poffActual = offSeek;
|
---|
| 331 |
|
---|
| 332 | return VINF_SUCCESS;
|
---|
| 333 | }
|
---|
| 334 |
|
---|
| 335 |
|
---|
| 336 | /**
|
---|
| 337 | * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
|
---|
| 338 | */
|
---|
| 339 | static DECLCALLBACK(int) vdIfVfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)
|
---|
| 340 | {
|
---|
| 341 | PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
|
---|
[48854] | 342 | int rc;
|
---|
| 343 | if (pThis->pVDIfsIo)
|
---|
| 344 | rc = vdIfIoFileGetSize(pThis->pVDIfsIo, pThis->pStorage, pcbFile);
|
---|
| 345 | else
|
---|
| 346 | rc = vdIfIoIntFileGetSize(pThis->pVDIfsIoInt, pThis->pStorage, pcbFile);
|
---|
| 347 | return rc;
|
---|
[48849] | 348 | }
|
---|
| 349 |
|
---|
| 350 |
|
---|
| 351 |
|
---|
| 352 | /**
|
---|
| 353 | * VFS file operations for a VD file.
|
---|
| 354 | */
|
---|
| 355 | DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_vdIfVfsFileOps =
|
---|
| 356 | {
|
---|
| 357 | { /* I/O stream */
|
---|
| 358 | { /* Obj */
|
---|
| 359 | RTVFSOBJOPS_VERSION,
|
---|
| 360 | RTVFSOBJTYPE_FILE,
|
---|
| 361 | "VDIfFile",
|
---|
| 362 | vdIfVfsIos_Close,
|
---|
| 363 | vdIfVfsIos_QueryInfo,
|
---|
[94291] | 364 | NULL,
|
---|
[48849] | 365 | RTVFSOBJOPS_VERSION
|
---|
| 366 | },
|
---|
| 367 | RTVFSIOSTREAMOPS_VERSION,
|
---|
| 368 | RTVFSIOSTREAMOPS_FEAT_NO_SG,
|
---|
| 369 | vdIfVfsIos_Read,
|
---|
| 370 | vdIfVfsIos_Write,
|
---|
| 371 | vdIfVfsIos_Flush,
|
---|
[69942] | 372 | NULL /*PollOne*/,
|
---|
[48849] | 373 | vdIfVfsIos_Tell,
|
---|
| 374 | NULL /*Skip*/,
|
---|
| 375 | NULL /*ZeroFill*/,
|
---|
| 376 | RTVFSIOSTREAMOPS_VERSION,
|
---|
| 377 | },
|
---|
| 378 | RTVFSFILEOPS_VERSION,
|
---|
| 379 | 0,
|
---|
| 380 | { /* ObjSet */
|
---|
| 381 | RTVFSOBJSETOPS_VERSION,
|
---|
[73097] | 382 | RT_UOFFSETOF(RTVFSFILEOPS, ObjSet) - RT_UOFFSETOF(RTVFSFILEOPS, Stream.Obj),
|
---|
[48849] | 383 | vdIfVfsFile_SetMode,
|
---|
| 384 | vdIfVfsFile_SetTimes,
|
---|
| 385 | vdIfVfsFile_SetOwner,
|
---|
| 386 | RTVFSOBJSETOPS_VERSION
|
---|
| 387 | },
|
---|
| 388 | vdIfVfsFile_Seek,
|
---|
| 389 | vdIfVfsFile_QuerySize,
|
---|
[69977] | 390 | NULL /*SetSize*/,
|
---|
| 391 | NULL /*QueryMaxSize*/,
|
---|
[48849] | 392 | RTVFSFILEOPS_VERSION,
|
---|
| 393 | };
|
---|
| 394 |
|
---|
| 395 |
|
---|
[48871] | 396 | VBOXDDU_DECL(int) VDIfCreateVfsFile(PVDINTERFACEIO pVDIfs, struct VDINTERFACEIOINT *pVDIfsInt, void *pvStorage, uint32_t fFlags, PRTVFSFILE phVfsFile)
|
---|
[48849] | 397 | {
|
---|
[48871] | 398 | AssertReturn((pVDIfs != NULL) != (pVDIfsInt != NULL), VERR_INVALID_PARAMETER); /* Exactly one needs to be specified. */
|
---|
[48849] | 399 | AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
|
---|
| 400 |
|
---|
| 401 | /*
|
---|
| 402 | * Create the volume file.
|
---|
| 403 | */
|
---|
| 404 | RTVFSFILE hVfsFile;
|
---|
| 405 | PVDIFVFSIOSFILE pThis;
|
---|
| 406 | int rc = RTVfsNewFile(&g_vdIfVfsFileOps, sizeof(*pThis), fFlags,
|
---|
| 407 | NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
|
---|
| 408 | if (RT_SUCCESS(rc))
|
---|
| 409 | {
|
---|
[48871] | 410 | pThis->pVDIfsIo = pVDIfs;
|
---|
| 411 | pThis->pVDIfsIoInt = pVDIfsInt;
|
---|
[48854] | 412 | pThis->pStorage = (PVDIOSTORAGE)pvStorage;
|
---|
| 413 | pThis->offCurPos = 0;
|
---|
[48849] | 414 |
|
---|
| 415 | *phVfsFile = hVfsFile;
|
---|
| 416 | return VINF_SUCCESS;
|
---|
| 417 | }
|
---|
| 418 |
|
---|
| 419 | return rc;
|
---|
| 420 | }
|
---|
| 421 |
|
---|