VirtualBox

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

Last change on this file since 48849 was 48849, checked in by vboxsync, 11 years ago

VDIfVfs.cpp: Added file interface wrapper - VDIfCreateVfsFile.

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