VirtualBox

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

Last change on this file since 106129 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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