VirtualBox

source: vbox/trunk/src/VBox/Storage/VDIfVfs.cpp@ 67954

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

Storage: warnings.

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