VirtualBox

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

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

iprt/vfs: more code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: vfsstdfile.cpp 33859 2010-11-08 16:15:07Z 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 rc = VINF_SUCCESS;
107
108 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
109 {
110 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
111 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
112
113 cbReadSeg = 0;
114 if (off < 0)
115 rc = RTFileRead(pThis->hFile, pvSeg, cbSeg, pcbReadSeg);
116 else
117 {
118 rc = RTFileReadAt(pThis->hFile, off, pvSeg, cbSeg, pcbReadSeg);
119 off += cbSeg;
120 }
121 if (RT_FAILURE(rc))
122 break;
123 if (pcbRead)
124 {
125 cbRead += cbReadSeg;
126 if (cbReadSeg != cbSeg)
127 break;
128 }
129 }
130
131 if (pcbRead)
132 *pcbRead = cbRead;
133 }
134
135 return rc;
136}
137
138
139/**
140 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
141 */
142static DECLCALLBACK(int) rtVfsStdFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
143{
144 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
145 int rc;
146
147 NOREF(fBlocking);
148 if (pSgBuf->cSegs == 1)
149 {
150 if (off < 0)
151 rc = RTFileWrite(pThis->hFile, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
152 else
153 rc = RTFileWriteAt(pThis->hFile, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
154 }
155 else
156 {
157 size_t cbWritten = 0;
158 size_t cbWrittenSeg;
159 size_t *pcbWrittenSeg = pcbWritten ? &cbWrittenSeg : NULL;
160 rc = VINF_SUCCESS;
161
162 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
163 {
164 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
165 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
166
167 cbWrittenSeg = 0;
168 if (off < 0)
169 rc = RTFileWrite(pThis->hFile, pvSeg, cbSeg, pcbWrittenSeg);
170 else
171 {
172 rc = RTFileWriteAt(pThis->hFile, off, pvSeg, cbSeg, pcbWrittenSeg);
173 off += cbSeg;
174 }
175 if (RT_FAILURE(rc))
176 break;
177 if (pcbWritten)
178 {
179 cbWritten += cbWrittenSeg;
180 if (cbWrittenSeg != cbSeg)
181 break;
182 }
183 }
184
185 if (pcbWritten)
186 *pcbWritten = cbWritten;
187 }
188
189 return rc;
190}
191
192
193/**
194 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
195 */
196static DECLCALLBACK(int) rtVfsStdFile_Flush(void *pvThis)
197{
198 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
199 return RTFileFlush(pThis->hFile);
200}
201
202
203/**
204 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
205 */
206static DECLCALLBACK(int) rtVfsStdFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
207 uint32_t *pfRetEvents)
208{
209 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
210 int rc;
211
212 if (fEvents != RTPOLL_EVT_ERROR)
213 {
214 *pfRetEvents = fEvents & ~RTPOLL_EVT_ERROR;
215 rc = VINF_SUCCESS;
216 }
217 else if (fIntr)
218 rc = RTThreadSleep(cMillies);
219 else
220 {
221 uint64_t uMsStart = RTTimeMilliTS();
222 do
223 rc = RTThreadSleep(cMillies);
224 while ( rc == VERR_INTERRUPTED
225 && !fIntr
226 && RTTimeMilliTS() - uMsStart < cMillies);
227 if (rc == VERR_INTERRUPTED)
228 rc = VERR_TIMEOUT;
229 }
230 return rc;
231}
232
233
234/**
235 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
236 */
237static DECLCALLBACK(int) rtVfsStdFile_Tell(void *pvThis, PRTFOFF poffActual)
238{
239 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
240 return RTFileTell(pThis->hFile);
241}
242
243
244/**
245 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnSkip}
246 */
247static DECLCALLBACK(int) rtVfsStdFile_Skip(void *pvThis, RTFOFF cb)
248{
249 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
250 uint64_t offIgnore;
251 return RTFileSeek(pThis->hFile, cb, RTFILE_SEEK_CURRENT, &offIgnore);
252}
253
254
255/**
256 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
257 */
258static DECLCALLBACK(int) rtVfsStdFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
259{
260 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
261 if (fMask != ~RTFS_TYPE_MASK)
262 {
263#if 0
264 RTFMODE fCurMode;
265 int rc = RTFileGetMode(pThis->hFile, &fCurMode);
266 if (RT_FAILURE(rc))
267 return rc;
268 fMode |= ~fMask & fCurMode;
269#else
270 RTFSOBJINFO ObjInfo;
271 int rc = RTFileQueryInfo(pThis->hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
272 if (RT_FAILURE(rc))
273 return rc;
274 fMode |= ~fMask & ObjInfo.Attr.fMode;
275#endif
276 }
277 return RTFileSetMode(pThis->hFile, fMode);
278}
279
280
281/**
282 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
283 */
284static DECLCALLBACK(int) rtVfsStdFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
285 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
286{
287 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
288 return RTFileSetTimes(pThis->hFile, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
289}
290
291
292/**
293 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
294 */
295static DECLCALLBACK(int) rtVfsStdFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
296{
297 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
298#if 0
299 return RTFileSetOwner(pThis->hFile, uid, gid);
300#else
301 return VERR_NOT_IMPLEMENTED;
302#endif
303}
304
305
306/**
307 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
308 */
309static DECLCALLBACK(int) rtVfsStdFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
310{
311 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
312 uint64_t offActual = 0;
313 int rc = RTFileSeek(pThis->hFile, offSeek, uMethod, &offActual);
314 if (RT_SUCCESS(rc))
315 *poffActual = offActual;
316 return rc;
317}
318
319
320/**
321 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
322 */
323static DECLCALLBACK(int) rtVfsStdFile_QuerySize(void *pvThis, uint64_t *pcbFile)
324{
325 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
326 return RTFileGetSize(pThis->hFile, pcbFile);
327}
328
329
330/**
331 * Standard file operations.
332 */
333DECLHIDDEN(const RTVFSFILEOPS) g_rtVfsStdFileOps =
334{
335 { /* Stream */
336 /** The basic object operation. */
337 { /* Obj */
338 RTVFSOBJOPS_VERSION,
339 RTVFSOBJTYPE_FILE,
340 "StdFile",
341 rtVfsStdFile_Close,
342 rtVfsStdFile_QueryInfo,
343 RTVFSOBJOPS_VERSION
344 },
345 RTVFSIOSTREAMOPS_VERSION,
346 0,
347 rtVfsStdFile_Read,
348 rtVfsStdFile_Write,
349 rtVfsStdFile_Flush,
350 rtVfsStdFile_PollOne,
351 rtVfsStdFile_Tell,
352 rtVfsStdFile_Skip,
353 NULL /*ZeroFill*/,
354 RTVFSIOSTREAMOPS_VERSION,
355 },
356 RTVFSFILEOPS_VERSION,
357 0,
358 { /* ObjSet */
359 RTVFSOBJSETOPS_VERSION,
360 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
361 rtVfsStdFile_SetMode,
362 rtVfsStdFile_SetTimes,
363 rtVfsStdFile_SetOwner,
364 RTVFSOBJSETOPS_VERSION
365 },
366 rtVfsStdFile_Seek,
367 rtVfsStdFile_QuerySize,
368 RTVFSFILEOPS_VERSION
369};
370
371
372RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint32_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile)
373{
374 /*
375 * Check the handle validity.
376 */
377 RTFSOBJINFO ObjInfo;
378 int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
379 if (RT_FAILURE(rc))
380 return rc;
381
382 /*
383 * Set up some fake fOpen flags.
384 */
385 if (!fOpen)
386 fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN_CREATE;
387
388 /*
389 * Create the handle.
390 */
391 PRTVFSSTDFILE pThis;
392 RTVFSFILE hVfsFile;
393 rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, &hVfsFile, (void **)&pThis);
394 if (RT_FAILURE(rc))
395 return rc;
396
397 pThis->hFile = hFile;
398 pThis->fLeaveOpen = fLeaveOpen;
399 *phVfsFile = hVfsFile;
400 return VINF_SUCCESS;
401}
402
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