VirtualBox

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

最後變更 在這個檔案從39032是 39032,由 vboxsync 提交於 13 年 前

IPRT: Fixed unused variable warnings.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.9 KB
 
1/* $Id: vfsstdfile.cpp 39032 2011-10-19 11:08:50Z 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.alldomusa.eu.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 * 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 * RTFileRead and RTFileReadAt does not return VINF_EOF or VINF_TRY_AGAIN, this
87 * function tries to fix this as best as it can.
88 *
89 * This fixing can be subject to races if some other thread or process is
90 * modifying the file size between the read and our size query here.
91 *
92 * @returns VINF_SUCCESS, VINF_EOF or VINF_TRY_AGAIN.
93 * @param pThis The instance data.
94 * @param off The offset parameter.
95 * @param cbToRead The number of bytes attempted read .
96 * @param cbActuallyRead The number of bytes actually read.
97 */
98DECLINLINE(int) rtVfsStdFile_ReadFixRC(PRTVFSSTDFILE pThis, RTFOFF off, size_t cbToRead, size_t cbActuallyRead)
99{
100 /* If the read returned less bytes than requested, it means the end of the
101 file has been reached. */
102 if (cbToRead > cbActuallyRead)
103 return VINF_EOF;
104
105 /* The other case here is the very special zero byte read at the end of the
106 file, where we're supposed to indicate EOF. */
107 if (cbToRead > 0)
108 return VINF_SUCCESS;
109
110 uint64_t cbFile;
111 int rc = RTFileGetSize(pThis->hFile, &cbFile);
112 if (RT_FAILURE(rc))
113 return rc;
114
115 uint64_t off2;
116 if (off >= 0)
117 off2 = off;
118 else
119 {
120 rc = RTFileSeek(pThis->hFile, 0, RTFILE_SEEK_CURRENT, &off2);
121 if (RT_FAILURE(rc))
122 return rc;
123 }
124
125 return off2 >= cbFile ? VINF_EOF : VINF_SUCCESS;
126}
127
128
129/**
130 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
131 */
132static DECLCALLBACK(int) rtVfsStdFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
133{
134 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
135 int rc;
136
137 NOREF(fBlocking);
138 if (pSgBuf->cSegs == 1)
139 {
140 if (off < 0)
141 rc = RTFileRead( pThis->hFile, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbRead);
142 else
143 rc = RTFileReadAt(pThis->hFile, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbRead);
144 if (rc == VINF_SUCCESS && pcbRead)
145 rc = rtVfsStdFile_ReadFixRC(pThis, off, pSgBuf->paSegs[0].cbSeg, *pcbRead);
146 }
147 else
148 {
149 size_t cbSeg = 0;
150 size_t cbRead = 0;
151 size_t cbReadSeg = 0;
152 rc = VINF_SUCCESS;
153
154 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
155 {
156 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
157 cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
158
159 cbReadSeg = cbSeg;
160 if (off < 0)
161 rc = RTFileRead( pThis->hFile, pvSeg, cbSeg, pcbRead ? &cbReadSeg : NULL);
162 else
163 rc = RTFileReadAt(pThis->hFile, off, pvSeg, cbSeg, pcbRead ? &cbReadSeg : NULL);
164 if (RT_FAILURE(rc))
165 break;
166 if (off >= 0)
167 off += cbReadSeg;
168 cbRead += cbReadSeg;
169 if ((pcbRead && cbReadSeg != cbSeg) || rc != VINF_SUCCESS)
170 break;
171 }
172
173 if (pcbRead)
174 {
175 *pcbRead = cbRead;
176 if (rc == VINF_SUCCESS)
177 rc = rtVfsStdFile_ReadFixRC(pThis, off, cbSeg, cbReadSeg);
178 }
179 }
180
181 return rc;
182}
183
184
185/**
186 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
187 */
188static DECLCALLBACK(int) rtVfsStdFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
189{
190 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
191 int rc;
192
193 NOREF(fBlocking);
194 if (pSgBuf->cSegs == 1)
195 {
196 if (off < 0)
197 rc = RTFileWrite(pThis->hFile, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
198 else
199 rc = RTFileWriteAt(pThis->hFile, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, pcbWritten);
200 }
201 else
202 {
203 size_t cbWritten = 0;
204 size_t cbWrittenSeg;
205 size_t *pcbWrittenSeg = pcbWritten ? &cbWrittenSeg : NULL;
206 rc = VINF_SUCCESS;
207
208 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
209 {
210 void *pvSeg = pSgBuf->paSegs[iSeg].pvSeg;
211 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
212
213 cbWrittenSeg = 0;
214 if (off < 0)
215 rc = RTFileWrite(pThis->hFile, pvSeg, cbSeg, pcbWrittenSeg);
216 else
217 {
218 rc = RTFileWriteAt(pThis->hFile, off, pvSeg, cbSeg, pcbWrittenSeg);
219 off += cbSeg;
220 }
221 if (RT_FAILURE(rc))
222 break;
223 if (pcbWritten)
224 {
225 cbWritten += cbWrittenSeg;
226 if (cbWrittenSeg != cbSeg)
227 break;
228 }
229 }
230
231 if (pcbWritten)
232 *pcbWritten = cbWritten;
233 }
234
235 return rc;
236}
237
238
239/**
240 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
241 */
242static DECLCALLBACK(int) rtVfsStdFile_Flush(void *pvThis)
243{
244 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
245 return RTFileFlush(pThis->hFile);
246}
247
248
249/**
250 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
251 */
252static DECLCALLBACK(int) rtVfsStdFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
253 uint32_t *pfRetEvents)
254{
255 int rc;
256 if (fEvents != RTPOLL_EVT_ERROR)
257 {
258 *pfRetEvents = fEvents & ~RTPOLL_EVT_ERROR;
259 rc = VINF_SUCCESS;
260 }
261 else if (fIntr)
262 rc = RTThreadSleep(cMillies);
263 else
264 {
265 uint64_t uMsStart = RTTimeMilliTS();
266 do
267 rc = RTThreadSleep(cMillies);
268 while ( rc == VERR_INTERRUPTED
269 && !fIntr
270 && RTTimeMilliTS() - uMsStart < cMillies);
271 if (rc == VERR_INTERRUPTED)
272 rc = VERR_TIMEOUT;
273 }
274 return rc;
275}
276
277
278/**
279 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
280 */
281static DECLCALLBACK(int) rtVfsStdFile_Tell(void *pvThis, PRTFOFF poffActual)
282{
283 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
284 uint64_t offActual;
285 int rc = RTFileSeek(pThis->hFile, 0, RTFILE_SEEK_CURRENT, &offActual);
286 if (RT_SUCCESS(rc))
287 *poffActual = (RTFOFF)offActual;
288 return rc;
289}
290
291
292/**
293 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnSkip}
294 */
295static DECLCALLBACK(int) rtVfsStdFile_Skip(void *pvThis, RTFOFF cb)
296{
297 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
298 uint64_t offIgnore;
299 return RTFileSeek(pThis->hFile, cb, RTFILE_SEEK_CURRENT, &offIgnore);
300}
301
302
303/**
304 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
305 */
306static DECLCALLBACK(int) rtVfsStdFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
307{
308 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
309 if (fMask != ~RTFS_TYPE_MASK)
310 {
311#if 0
312 RTFMODE fCurMode;
313 int rc = RTFileGetMode(pThis->hFile, &fCurMode);
314 if (RT_FAILURE(rc))
315 return rc;
316 fMode |= ~fMask & fCurMode;
317#else
318 RTFSOBJINFO ObjInfo;
319 int rc = RTFileQueryInfo(pThis->hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
320 if (RT_FAILURE(rc))
321 return rc;
322 fMode |= ~fMask & ObjInfo.Attr.fMode;
323#endif
324 }
325 return RTFileSetMode(pThis->hFile, fMode);
326}
327
328
329/**
330 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
331 */
332static DECLCALLBACK(int) rtVfsStdFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
333 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
334{
335 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
336 return RTFileSetTimes(pThis->hFile, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
337}
338
339
340/**
341 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
342 */
343static DECLCALLBACK(int) rtVfsStdFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
344{
345#if 0
346 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
347 return RTFileSetOwner(pThis->hFile, uid, gid);
348#else
349 return VERR_NOT_IMPLEMENTED;
350#endif
351}
352
353
354/**
355 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
356 */
357static DECLCALLBACK(int) rtVfsStdFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
358{
359 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
360 uint64_t offActual = 0;
361 int rc = RTFileSeek(pThis->hFile, offSeek, uMethod, &offActual);
362 if (RT_SUCCESS(rc))
363 *poffActual = offActual;
364 return rc;
365}
366
367
368/**
369 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
370 */
371static DECLCALLBACK(int) rtVfsStdFile_QuerySize(void *pvThis, uint64_t *pcbFile)
372{
373 PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
374 return RTFileGetSize(pThis->hFile, pcbFile);
375}
376
377
378/**
379 * Standard file operations.
380 */
381DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtVfsStdFileOps =
382{
383 { /* Stream */
384 { /* Obj */
385 RTVFSOBJOPS_VERSION,
386 RTVFSOBJTYPE_FILE,
387 "StdFile",
388 rtVfsStdFile_Close,
389 rtVfsStdFile_QueryInfo,
390 RTVFSOBJOPS_VERSION
391 },
392 RTVFSIOSTREAMOPS_VERSION,
393 0,
394 rtVfsStdFile_Read,
395 rtVfsStdFile_Write,
396 rtVfsStdFile_Flush,
397 rtVfsStdFile_PollOne,
398 rtVfsStdFile_Tell,
399 rtVfsStdFile_Skip,
400 NULL /*ZeroFill*/,
401 RTVFSIOSTREAMOPS_VERSION,
402 },
403 RTVFSFILEOPS_VERSION,
404 0,
405 { /* ObjSet */
406 RTVFSOBJSETOPS_VERSION,
407 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
408 rtVfsStdFile_SetMode,
409 rtVfsStdFile_SetTimes,
410 rtVfsStdFile_SetOwner,
411 RTVFSOBJSETOPS_VERSION
412 },
413 rtVfsStdFile_Seek,
414 rtVfsStdFile_QuerySize,
415 RTVFSFILEOPS_VERSION
416};
417
418
419RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile)
420{
421 /*
422 * Check the handle validity.
423 */
424 RTFSOBJINFO ObjInfo;
425 int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
426 if (RT_FAILURE(rc))
427 return rc;
428
429 /*
430 * Set up some fake fOpen flags.
431 */
432 if (!fOpen)
433 fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN_CREATE;
434
435 /*
436 * Create the handle.
437 */
438 PRTVFSSTDFILE pThis;
439 RTVFSFILE hVfsFile;
440 rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
441 if (RT_FAILURE(rc))
442 return rc;
443
444 pThis->hFile = hFile;
445 pThis->fLeaveOpen = fLeaveOpen;
446 *phVfsFile = hVfsFile;
447 return VINF_SUCCESS;
448}
449
450
451RTDECL(int) RTVfsIoStrmFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSIOSTREAM phVfsIos)
452{
453 RTVFSFILE hVfsFile;
454 int rc = RTVfsFileFromRTFile(hFile, fOpen, fLeaveOpen, &hVfsFile);
455 if (RT_SUCCESS(rc))
456 *phVfsIos = RTVfsFileToIoStream(hVfsFile);
457 return rc;
458}
459
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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