VirtualBox

source: vbox/trunk/src/VBox/Storage/VDIfVfs2.cpp@ 65919

Last change on this file since 65919 was 64272, checked in by vboxsync, 8 years ago

Storage: Doxygen fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1/* $Id: VDIfVfs2.cpp 64272 2016-10-14 08:25:05Z 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-2016 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#include <VBox/vd-ifs-internal.h>
34
35#include <VBox/log.h>
36
37
38/*********************************************************************************************************************************
39* Structures and Typedefs *
40*********************************************************************************************************************************/
41/**
42 * Extended VD I/O interface structure that vdIfFromVfs_xxx uses.
43 *
44 * It's passed as pvUser to each call.
45 */
46typedef struct VDIFFROMVFS
47{
48 VDINTERFACEIO CoreIo;
49
50 /** Magic. */
51 uint32_t u32Magic;
52 /** The stream access mode (RTFILE_O_ACCESS_MASK), possibly others. */
53 uint32_t fAccessMode;
54 /** The I/O stream. This is NIL after it's been closed. */
55 RTVFSIOSTREAM hVfsIos;
56 /** Completion callback. */
57 PFNVDCOMPLETED pfnCompleted;
58 /** User parameter for the completion callback. */
59 void *pvCompletedUser;
60 /** Set if hVfsIos has been opened. */
61 bool fOpened;
62} VDIFFROMVFS;
63/** Magic value for VDIFFROMVFS::u32Magic. */
64#define VDIFFROMVFS_MAGIC UINT32_C(0x11223344)
65
66/** Pointer to the instance data for the vdIfFromVfs_ methods. */
67typedef struct VDIFFROMVFS *PVDIFFROMVFS;
68
69
70typedef struct FILESTORAGEINTERNAL
71{
72 /** File handle. */
73 RTFILE file;
74} FILESTORAGEINTERNAL, *PFILESTORAGEINTERNAL;
75
76
77/*********************************************************************************************************************************
78* Defined Constants And Macros *
79*********************************************************************************************************************************/
80
81#define STATUS_WAIT UINT32_C(0)
82#define STATUS_WRITE UINT32_C(1)
83#define STATUS_WRITING UINT32_C(2)
84#define STATUS_READ UINT32_C(3)
85#define STATUS_READING UINT32_C(4)
86#define STATUS_END UINT32_C(5)
87
88/* Enable for getting some flow history. */
89#if 0
90# define DEBUG_PRINT_FLOW() RTPrintf("%s\n", __FUNCTION__)
91#else
92# define DEBUG_PRINT_FLOW() do {} while (0)
93#endif
94
95
96/*********************************************************************************************************************************
97* Internal Functions *
98*********************************************************************************************************************************/
99
100
101/** @name VDINTERFACEIO stubs returning not-implemented.
102 * @{
103 */
104
105/** @interface_method_impl{VDINTERFACEIO,pfnDelete} */
106static DECLCALLBACK(int) notImpl_Delete(void *pvUser, const char *pcszFilename)
107{
108 NOREF(pvUser); NOREF(pcszFilename);
109 Log(("%s\n", __FUNCTION__));
110 return VERR_NOT_IMPLEMENTED;
111}
112
113/** @interface_method_impl{VDINTERFACEIO,pfnMove} */
114static DECLCALLBACK(int) notImpl_Move(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)
115{
116 NOREF(pvUser); NOREF(pcszSrc); NOREF(pcszDst); NOREF(fMove);
117 Log(("%s\n", __FUNCTION__));
118 return VERR_NOT_IMPLEMENTED;
119}
120
121/** @interface_method_impl{VDINTERFACEIO,pfnGetFreeSpace} */
122static DECLCALLBACK(int) notImpl_GetFreeSpace(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)
123{
124 NOREF(pvUser); NOREF(pcszFilename); NOREF(pcbFreeSpace);
125 Log(("%s\n", __FUNCTION__));
126 return VERR_NOT_IMPLEMENTED;
127}
128
129/** @interface_method_impl{VDINTERFACEIO,pfnGetModificationTime} */
130static DECLCALLBACK(int) notImpl_GetModificationTime(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)
131{
132 NOREF(pvUser); NOREF(pcszFilename); NOREF(pModificationTime);
133 Log(("%s\n", __FUNCTION__));
134 return VERR_NOT_IMPLEMENTED;
135}
136
137/** @interface_method_impl{VDINTERFACEIO,pfnSetSize} */
138static DECLCALLBACK(int) notImpl_SetSize(void *pvUser, void *pvStorage, uint64_t cb)
139{
140 NOREF(pvUser); NOREF(pvStorage); NOREF(cb);
141 Log(("%s\n", __FUNCTION__));
142 return VERR_NOT_IMPLEMENTED;
143}
144
145#if 0 /* unused */
146/** @interface_method_impl{VDINTERFACEIO,pfnWriteSync} */
147static DECLCALLBACK(int) notImpl_WriteSync(void *pvUser, void *pvStorage, uint64_t off, const void *pvBuf,
148 size_t cbWrite, size_t *pcbWritten)
149{
150 RT_NOREF6(pvUser, pvStorage, off, pvBuf, cbWrite, pcbWritten)
151 Log(("%s\n", __FUNCTION__));
152 return VERR_NOT_IMPLEMENTED;
153}
154#endif
155
156/** @interface_method_impl{VDINTERFACEIO,pfnFlushSync} */
157static DECLCALLBACK(int) notImpl_FlushSync(void *pvUser, void *pvStorage)
158{
159 NOREF(pvUser); NOREF(pvStorage);
160 Log(("%s\n", __FUNCTION__));
161 return VERR_NOT_IMPLEMENTED;
162}
163
164/** @} */
165
166
167/** @interface_method_impl{VDINTERFACEIO,pfnOpen} */
168static DECLCALLBACK(int) vdIfFromVfs_Open(void *pvUser, const char *pszLocation, uint32_t fOpen,
169 PFNVDCOMPLETED pfnCompleted, void **ppvStorage)
170{
171 RT_NOREF1(pszLocation);
172 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pvUser;
173
174 /*
175 * Validate input.
176 */
177 AssertPtrReturn(ppvStorage, VERR_INVALID_POINTER);
178 AssertPtrNullReturn(pfnCompleted, VERR_INVALID_PARAMETER);
179
180 /*
181 * We ignore the name, assuming the caller is opening the stream/file we're .
182 * serving. Thus, after close, all open calls fail.
183 */
184 AssertReturn(!pThis->fOpened, VERR_FILE_NOT_FOUND);
185 AssertReturn(pThis->hVfsIos != NIL_RTVFSIOSTREAM, VERR_FILE_NOT_FOUND); /* paranoia */
186 AssertMsgReturn((pThis->fAccessMode & fOpen & RTFILE_O_ACCESS_MASK) == (fOpen & RTFILE_O_ACCESS_MASK),
187 ("fAccessMode=%#x fOpen=%#x\n", pThis->fAccessMode, fOpen), VERR_ACCESS_DENIED);
188
189 pThis->fAccessMode = fOpen & RTFILE_O_ACCESS_MASK;
190 pThis->fOpened = true;
191 pThis->pfnCompleted = pfnCompleted;
192 pThis->pvCompletedUser = pvUser;
193
194 *ppvStorage = pThis->hVfsIos;
195 return VINF_SUCCESS;
196}
197
198/** @interface_method_impl{VDINTERFACEIO,pfnClose} */
199static DECLCALLBACK(int) vdIfFromVfs_Close(void *pvUser, void *pvStorage)
200{
201 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pvUser;
202 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
203 AssertReturn(pThis->hVfsIos == (RTVFSIOSTREAM)pvStorage, VERR_INVALID_HANDLE);
204 AssertReturn(pThis->fOpened, VERR_INVALID_HANDLE);
205
206 RTVfsIoStrmRelease(pThis->hVfsIos);
207 pThis->hVfsIos = NIL_RTVFSIOSTREAM;
208
209 return VINF_SUCCESS;
210}
211
212
213/** @interface_method_impl{VDINTERFACEIO,pfnGetSize} */
214static DECLCALLBACK(int) vdIfFromVfs_GetSize(void *pvUser, void *pvStorage, uint64_t *pcb)
215{
216 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pvUser;
217 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
218 AssertReturn(pThis->hVfsIos == (RTVFSIOSTREAM)pvStorage, VERR_INVALID_HANDLE);
219 AssertReturn(pThis->fOpened, VERR_INVALID_HANDLE);
220
221 RTFSOBJINFO ObjInfo;
222 int rc = RTVfsIoStrmQueryInfo(pThis->hVfsIos, &ObjInfo, RTFSOBJATTRADD_NOTHING);
223 if (RT_SUCCESS(rc))
224 *pcb = ObjInfo.cbObject;
225 return rc;
226}
227
228/** @interface_method_impl{VDINTERFACEIO,pfnReadSync} */
229static DECLCALLBACK(int) vdIfFromVfs_ReadSync(void *pvUser, void *pvStorage, uint64_t off, void *pvBuf,
230 size_t cbToRead, size_t *pcbRead)
231{
232 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pvUser;
233 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
234 AssertReturn(pThis->hVfsIos == (RTVFSIOSTREAM)pvStorage, VERR_INVALID_HANDLE);
235 AssertReturn(pThis->fOpened, VERR_INVALID_HANDLE);
236 AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
237 AssertReturn(pThis->fAccessMode & RTFILE_O_READ, VERR_ACCESS_DENIED);
238
239 return RTVfsIoStrmReadAt(pThis->hVfsIos, off, pvBuf, cbToRead, true /*fBlocking*/, pcbRead);
240}
241
242
243/** @interface_method_impl{VDINTERFACEIO,pfnWriteSync} */
244static DECLCALLBACK(int) vdIfFromVfs_WriteSync(void *pvUser, void *pvStorage, uint64_t off, void const *pvBuf,
245 size_t cbToWrite, size_t *pcbWritten)
246{
247 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pvUser;
248 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
249 AssertReturn(pThis->hVfsIos == (RTVFSIOSTREAM)pvStorage, VERR_INVALID_HANDLE);
250 AssertReturn(pThis->fOpened, VERR_INVALID_HANDLE);
251 AssertPtrNullReturn(pcbWritten, VERR_INVALID_POINTER);
252 AssertReturn(pThis->fAccessMode & RTFILE_O_WRITE, VERR_ACCESS_DENIED);
253
254 return RTVfsIoStrmWriteAt(pThis->hVfsIos, off, pvBuf, cbToWrite, true /*fBlocking*/, pcbWritten);
255}
256
257
258VBOXDDU_DECL(int) VDIfCreateFromVfsStream(RTVFSIOSTREAM hVfsIos, uint32_t fAccessMode, PVDINTERFACEIO *ppIoIf)
259{
260 /*
261 * Validate input.
262 */
263 AssertPtrReturn(ppIoIf, VERR_INVALID_POINTER);
264 *ppIoIf = NULL;
265 AssertReturn(hVfsIos != NIL_RTVFSIOSTREAM, VERR_INVALID_HANDLE);
266 AssertReturn(fAccessMode & RTFILE_O_ACCESS_MASK, VERR_INVALID_FLAGS);
267
268 uint32_t cRefs = RTVfsIoStrmRetain(hVfsIos);
269 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
270
271 /*
272 * Allocate and init a callback + instance data structure.
273 */
274 int rc;
275 PVDIFFROMVFS pThis = (PVDIFFROMVFS)RTMemAllocZ(sizeof(*pThis));
276 if (pThis)
277 {
278 pThis->CoreIo.pfnOpen = vdIfFromVfs_Open;
279 pThis->CoreIo.pfnClose = vdIfFromVfs_Close;
280 pThis->CoreIo.pfnDelete = notImpl_Delete;
281 pThis->CoreIo.pfnMove = notImpl_Move;
282 pThis->CoreIo.pfnGetFreeSpace = notImpl_GetFreeSpace;
283 pThis->CoreIo.pfnGetModificationTime = notImpl_GetModificationTime;
284 pThis->CoreIo.pfnGetSize = vdIfFromVfs_GetSize;
285 pThis->CoreIo.pfnSetSize = notImpl_SetSize;
286 pThis->CoreIo.pfnReadSync = vdIfFromVfs_ReadSync;
287 pThis->CoreIo.pfnWriteSync = vdIfFromVfs_WriteSync;
288 pThis->CoreIo.pfnFlushSync = notImpl_FlushSync;
289
290 pThis->hVfsIos = hVfsIos;
291 pThis->fAccessMode = fAccessMode;
292 pThis->fOpened = false;
293 pThis->u32Magic = VDIFFROMVFS_MAGIC;
294
295 PVDINTERFACE pFakeList = NULL;
296 rc = VDInterfaceAdd(&pThis->CoreIo.Core, "FromVfsStream", VDINTERFACETYPE_IO, pThis, sizeof(pThis->CoreIo), &pFakeList);
297 if (RT_SUCCESS(rc))
298 {
299 *ppIoIf = &pThis->CoreIo;
300 return VINF_SUCCESS;
301 }
302
303 RTMemFree(pThis);
304 }
305 else
306 rc = VERR_NO_MEMORY;
307 RTVfsIoStrmRelease(hVfsIos);
308 return rc;
309}
310
311
312VBOXDDU_DECL(int) VDIfDestroyFromVfsStream(PVDINTERFACEIO pIoIf)
313{
314 if (pIoIf)
315 {
316 PVDIFFROMVFS pThis = (PVDIFFROMVFS)pIoIf;
317 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
318 AssertReturn(pThis->u32Magic == VDIFFROMVFS_MAGIC, VERR_INVALID_MAGIC);
319
320 if (pThis->hVfsIos != NIL_RTVFSIOSTREAM)
321 {
322 RTVfsIoStrmRelease(pThis->hVfsIos);
323 pThis->hVfsIos = NIL_RTVFSIOSTREAM;
324 }
325 pThis->u32Magic = ~VDIFFROMVFS_MAGIC;
326 }
327 return VINF_SUCCESS;
328}
329
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