VirtualBox

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

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

vfsstdfile.cpp: warnings

  • 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 33821 2010-11-07 16:36:20Z 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{RTVFSOBJSETOPS,pfnMode}
246 */
247static DECLCALLBACK(int) rtVfsStdFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
248{
249 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
250 if (fMask != ~RTFS_TYPE_MASK)
251 {
252#if 0
253 RTFMODE fCurMode;
254 int rc = RTFileGetMode(pThis->hFile, &fCurMode);
255 if (RT_FAILURE(rc))
256 return rc;
257 fMode |= ~fMask & fCurMode;
258#else
259 RTFSOBJINFO ObjInfo;
260 int rc = RTFileQueryInfo(pThis->hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
261 if (RT_FAILURE(rc))
262 return rc;
263 fMode |= ~fMask & ObjInfo.Attr.fMode;
264#endif
265 }
266 return RTFileSetMode(pThis->hFile, fMode);
267}
268
269
270/**
271 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
272 */
273static DECLCALLBACK(int) rtVfsStdFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
274 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
275{
276 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
277 return RTFileSetTimes(pThis->hFile, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
278}
279
280
281/**
282 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
283 */
284static DECLCALLBACK(int) rtVfsStdFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
285{
286 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
287#if 0
288 return RTFileSetOwner(pThis->hFile, uid, gid);
289#else
290 return VERR_NOT_IMPLEMENTED;
291#endif
292}
293
294
295/**
296 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
297 */
298static DECLCALLBACK(int) rtVfsStdFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
299{
300 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
301 uint64_t offActual = 0;
302 int rc = RTFileSeek(pThis->hFile, offSeek, uMethod, &offActual);
303 if (RT_SUCCESS(rc))
304 *poffActual = offActual;
305 return rc;
306}
307
308
309/**
310 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
311 */
312static DECLCALLBACK(int) rtVfsStdFile_QuerySize(void *pvThis, uint64_t *pcbFile)
313{
314 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
315 return RTFileGetSize(pThis->hFile, pcbFile);
316}
317
318
319/**
320 * Standard file operations.
321 */
322DECLHIDDEN(const RTVFSFILEOPS) g_rtVfsStdFileOps =
323{
324 { /* Stream */
325 /** The basic object operation. */
326 { /* Obj */
327 RTVFSOBJOPS_VERSION,
328 RTVFSOBJTYPE_FILE,
329 "StdFile",
330 rtVfsStdFile_Close,
331 rtVfsStdFile_QueryInfo,
332 RTVFSOBJOPS_VERSION
333 },
334 RTVFSIOSTREAMOPS_VERSION,
335 0,
336 rtVfsStdFile_Read,
337 rtVfsStdFile_Write,
338 rtVfsStdFile_Flush,
339 rtVfsStdFile_PollOne,
340 rtVfsStdFile_Tell,
341 RTVFSIOSTREAMOPS_VERSION,
342 },
343 RTVFSFILEOPS_VERSION,
344 0,
345 { /* ObjSet */
346 RTVFSOBJSETOPS_VERSION,
347 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
348 rtVfsStdFile_SetMode,
349 rtVfsStdFile_SetTimes,
350 rtVfsStdFile_SetOwner,
351 RTVFSOBJSETOPS_VERSION
352 },
353 rtVfsStdFile_Seek,
354 rtVfsStdFile_QuerySize,
355 RTVFSFILEOPS_VERSION
356};
357
358
359RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint32_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile)
360{
361 /*
362 * Check the handle validity.
363 */
364 RTFSOBJINFO ObjInfo;
365 int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
366 if (RT_FAILURE(rc))
367 return rc;
368
369 /*
370 * Set up some fake fOpen flags.
371 */
372 if (!fOpen)
373 fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN_CREATE;
374
375 /*
376 * Create the handle.
377 */
378 PRTVFSSTDFILE pThis;
379 RTVFSFILE hVfsFile;
380 rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, &hVfsFile, (void **)&pThis);
381 if (RT_FAILURE(rc))
382 return rc;
383
384 pThis->hFile = hFile;
385 pThis->fLeaveOpen = fLeaveOpen;
386 *phVfsFile = hVfsFile;
387 return VINF_SUCCESS;
388}
389
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