VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp@ 33820

Last change on this file since 33820 was 33820, checked in by vboxsync, 15 years ago

iprt/vfs: Hacking in progress.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: vfsstdfile.cpp 33820 2010-11-07 16:33:23Z vboxsync $ */
2/** @file
3 * IPRT - Virtual File System, Standard File Implementation.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/vfs.h>
32#include <iprt/vfslowlevel.h>
33
34#include <iprt/err.h>
35#include <iprt/file.h>
36#include <iprt/poll.h>
37#include <iprt/thread.h>
38
39
40/*******************************************************************************
41* Structures and Typedefs *
42*******************************************************************************/
43/**
44 * Private data of a standard file.
45 */
46typedef struct RTVFSSTDFILE
47{
48 /** The file handle. */
49 RTFILE hFile;
50 /** Whether to leave the handle open when the VFS handle is closed. */
51 bool fLeaveOpen;
52} RTVFSSTDFILE;
53/** Pointer to the private data of a standard file. */
54typedef RTVFSSTDFILE *PRTVFSSTDFILE;
55
56
57/**
58 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
59 */
60static DECLCALLBACK(int) rtVfsStdFile_Close(void *pvThis)
61{
62 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
63
64 int rc;
65 if (!pThis->fLeaveOpen)
66 rc = RTFileClose(pThis->hFile);
67 else
68 rc = VINF_SUCCESS;
69 pThis->hFile = NIL_RTFILE;
70
71 return rc;
72}
73
74
75/**
76 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
77 */
78static DECLCALLBACK(int) rtVfsStdFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
79{
80 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
81 return RTFileQueryInfo(pThis->hFile, pObjInfo, enmAddAttr);
82}
83
84
85/**
86 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
87 */
88static DECLCALLBACK(int) rtVfsStdFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
89{
90 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
91 int rc;
92
93 NOREF(fBlocking);
94 if (pSgBuf->cSegs == 1)
95 {
96 if (off < 0)
97 rc = RTFileRead(pThis->hFile, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbRead);
98 else
99 rc = RTFileReadAt(pThis->hFile, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbRead);
100 }
101 else
102 {
103 size_t cbRead = 0;
104 size_t cbReadSeg;
105 size_t *pcbReadSeg = pcbRead ? &cbReadSeg : NULL;
106
107 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
108 {
109 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
110 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
111
112 cbReadSeg = 0;
113 if (off < 0)
114 rc = RTFileRead(pThis->hFile, pvSeg, cbSeg, pcbReadSeg);
115 else
116 {
117 rc = RTFileReadAt(pThis->hFile, off, pvSeg, cbSeg, pcbReadSeg);
118 off += cbSeg;
119 }
120 if (RT_FAILURE(rc))
121 break;
122 if (pcbRead)
123 {
124 cbRead += cbReadSeg;
125 if (cbReadSeg != cbSeg)
126 break;
127 }
128 }
129
130 if (pcbRead)
131 *pcbRead = cbRead;
132 }
133
134 return rc;
135}
136
137
138/**
139 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
140 */
141static DECLCALLBACK(int) rtVfsStdFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
142{
143 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
144 int rc;
145
146 NOREF(fBlocking);
147 if (pSgBuf->cSegs == 1)
148 {
149 if (off < 0)
150 rc = RTFileWrite(pThis->hFile, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
151 else
152 rc = RTFileWriteAt(pThis->hFile, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
153 }
154 else
155 {
156 size_t cbWritten = 0;
157 size_t cbWrittenSeg;
158 size_t *pcbWrittenSeg = pcbWritten ? &cbWrittenSeg : NULL;
159
160 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
161 {
162 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
163 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
164
165 cbWrittenSeg = 0;
166 if (off < 0)
167 rc = RTFileWrite(pThis->hFile, pvSeg, cbSeg, pcbWrittenSeg);
168 else
169 {
170 rc = RTFileWriteAt(pThis->hFile, off, pvSeg, cbSeg, pcbWrittenSeg);
171 off += cbSeg;
172 }
173 if (RT_FAILURE(rc))
174 break;
175 if (pcbWritten)
176 {
177 cbWritten += cbWrittenSeg;
178 if (cbWrittenSeg != cbSeg)
179 break;
180 }
181 }
182
183 if (pcbWritten)
184 *pcbWritten = cbWritten;
185 }
186
187 return rc;
188}
189
190
191/**
192 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
193 */
194static DECLCALLBACK(int) rtVfsStdFile_Flush(void *pvThis)
195{
196 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
197 return RTFileFlush(pThis->hFile);
198}
199
200
201/**
202 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
203 */
204static DECLCALLBACK(int) rtVfsStdFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
205 uint32_t *pfRetEvents)
206{
207 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
208 int rc;
209
210 if (fEvents != RTPOLL_EVT_ERROR)
211 {
212 *pfRetEvents = fEvents & ~RTPOLL_EVT_ERROR;
213 rc = VINF_SUCCESS;
214 }
215 else if (fIntr)
216 rc = RTThreadSleep(cMillies);
217 else
218 {
219 uint64_t uMsStart = RTTimeMilliTS();
220 do
221 rc = RTThreadSleep(cMillies);
222 while ( rc == VERR_INTERRUPTED
223 && !fIntr
224 && RTTimeMilliTS() - uMsStart < cMillies);
225 if (rc == VERR_INTERRUPTED)
226 rc = VERR_TIMEOUT;
227 }
228 return rc;
229}
230
231
232/**
233 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
234 */
235static DECLCALLBACK(int) rtVfsStdFile_Tell(void *pvThis, PRTFOFF poffActual)
236{
237 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
238 return RTFileTell(pThis->hFile);
239}
240
241
242/**
243 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
244 */
245static DECLCALLBACK(int) rtVfsStdFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
246{
247 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
248 if (fMask != ~RTFS_TYPE_MASK)
249 {
250#if 0
251 RTFMODE fCurMode;
252 int rc = RTFileGetMode(pThis->hFile, &fCurMode);
253 if (RT_FAILURE(rc))
254 return rc;
255 fMode |= ~fMask & fCurMode;
256#else
257 RTFSOBJINFO ObjInfo;
258 int rc = RTFileQueryInfo(pThis->hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
259 if (RT_FAILURE(rc))
260 return rc;
261 fMode |= ~fMask & ObjInfo.Attr.fMode;
262#endif
263 }
264 return RTFileSetMode(pThis->hFile, fMode);
265}
266
267
268/**
269 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
270 */
271static DECLCALLBACK(int) rtVfsStdFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
272 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
273{
274 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
275 return RTFileSetTimes(pThis->hFile, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
276}
277
278
279/**
280 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
281 */
282static DECLCALLBACK(int) rtVfsStdFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
283{
284 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
285#if 0
286 return RTFileSetOwner(pThis->hFile, uid, gid);
287#else
288 return VERR_NOT_IMPLEMENTED;
289#endif
290}
291
292
293/**
294 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
295 */
296static DECLCALLBACK(int) rtVfsStdFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
297{
298 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
299 uint64_t offActual = 0;
300 int rc = RTFileSeek(pThis->hFile, offSeek, uMethod, &offActual);
301 if (RT_SUCCESS(rc))
302 *poffActual = offActual;
303 return rc;
304}
305
306
307/**
308 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
309 */
310static DECLCALLBACK(int) rtVfsStdFile_QuerySize(void *pvThis, uint64_t *pcbFile)
311{
312 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
313 return RTFileGetSize(pThis->hFile, pcbFile);
314}
315
316
317/**
318 * Standard file operations.
319 */
320DECLHIDDEN(const RTVFSFILEOPS) g_rtVfsStdFileOps =
321{
322 { /* Stream */
323 /** The basic object operation. */
324 { /* Obj */
325 RTVFSOBJOPS_VERSION,
326 RTVFSOBJTYPE_FILE,
327 "StdFile",
328 rtVfsStdFile_Close,
329 rtVfsStdFile_QueryInfo,
330 RTVFSOBJOPS_VERSION
331 },
332 RTVFSIOSTREAMOPS_VERSION,
333 0,
334 rtVfsStdFile_Read,
335 rtVfsStdFile_Write,
336 rtVfsStdFile_Flush,
337 rtVfsStdFile_PollOne,
338 rtVfsStdFile_Tell,
339 RTVFSIOSTREAMOPS_VERSION,
340 },
341 RTVFSFILEOPS_VERSION,
342 0,
343 { /* ObjSet */
344 RTVFSOBJSETOPS_VERSION,
345 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
346 rtVfsStdFile_SetMode,
347 rtVfsStdFile_SetTimes,
348 rtVfsStdFile_SetOwner,
349 RTVFSOBJSETOPS_VERSION
350 },
351 rtVfsStdFile_Seek,
352 rtVfsStdFile_QuerySize,
353 RTVFSFILEOPS_VERSION
354};
355
356
357RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint32_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile)
358{
359 /*
360 * Check the handle validity.
361 */
362 RTFSOBJINFO ObjInfo;
363 int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
364 if (RT_FAILURE(rc))
365 return rc;
366
367 /*
368 * Set up some fake fOpen flags.
369 */
370 if (!fOpen)
371 fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN_CREATE;
372
373 /*
374 * Create the handle.
375 */
376 PRTVFSSTDFILE pThis;
377 RTVFSFILE hVfsFile;
378 rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, &hVfsFile, (void **)&pThis);
379 if (RT_FAILURE(rc))
380 return rc;
381
382 pThis->hFile = hFile;
383 pThis->fLeaveOpen = fLeaveOpen;
384 *phVfsFile = hVfsFile;
385 return VINF_SUCCESS;
386}
387
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette