VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/darwin/fileio-r0drv-darwin.cpp@ 85546

Last change on this file since 85546 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: fileio-r0drv-darwin.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * IPRT - File I/O, R0 Driver, Darwin.
4 */
5
6/*
7 * Copyright (C) 2011-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.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 "the-darwin-kernel.h"
32
33#include <iprt/file.h>
34#include "internal/iprt.h"
35
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/err.h>
39#include <iprt/log.h>
40#include <iprt/mem.h>
41#include <iprt/string.h>
42#include "internal/magics.h"
43
44
45/*********************************************************************************************************************************
46* Global Variables *
47*********************************************************************************************************************************/
48/** Default file permissions for newly created files. */
49#if defined(S_IRUSR) && defined(S_IWUSR)
50# define RT_FILE_PERMISSION (S_IRUSR | S_IWUSR)
51#else
52# define RT_FILE_PERMISSION (00600)
53#endif
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/**
60 * Darwin kernel file handle data.
61 */
62typedef struct RTFILEINT
63{
64 /** Magic value (RTFILE_MAGIC). */
65 uint32_t u32Magic;
66 /** The open mode flags passed to the kernel API. */
67 int fOpenMode;
68 /** The open flags passed to RTFileOpen. */
69 uint64_t fOpen;
70 /** The VFS context in which the file was opened. */
71 vfs_context_t hVfsCtx;
72 /** The vnode returned by vnode_open. */
73 vnode_t hVnode;
74 /** The current file offset. */
75 uint64_t offFile;
76} RTFILEINT;
77/** Magic number for RTFILEINT::u32Magic (To Be Determined). */
78#define RTFILE_MAGIC UINT32_C(0x01020304)
79
80
81RTDECL(int) RTFileOpen(PRTFILE phFile, const char *pszFilename, uint64_t fOpen)
82{
83 RTFILEINT *pThis = (RTFILEINT *)RTMemAllocZ(sizeof(*pThis));
84 if (!pThis)
85 return VERR_NO_MEMORY;
86 IPRT_DARWIN_SAVE_EFL_AC();
87
88 errno_t rc;
89 pThis->u32Magic = RTFILE_MAGIC;
90 pThis->fOpen = fOpen;
91 pThis->hVfsCtx = vfs_context_current();
92 if (pThis->hVfsCtx != NULL)
93 {
94 int fCMode = (fOpen & RTFILE_O_CREATE_MODE_MASK)
95 ? (fOpen & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT
96 : RT_FILE_PERMISSION;
97 int fVnFlags = 0; /* VNODE_LOOKUP_XXX */
98 int fOpenMode = 0;
99 if (fOpen & RTFILE_O_NON_BLOCK)
100 fOpenMode |= O_NONBLOCK;
101 if (fOpen & RTFILE_O_WRITE_THROUGH)
102 fOpenMode |= O_SYNC;
103
104 /* create/truncate file */
105 switch (fOpen & RTFILE_O_ACTION_MASK)
106 {
107 case RTFILE_O_OPEN: break;
108 case RTFILE_O_OPEN_CREATE: fOpenMode |= O_CREAT; break;
109 case RTFILE_O_CREATE: fOpenMode |= O_CREAT | O_EXCL; break;
110 case RTFILE_O_CREATE_REPLACE: fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */
111 }
112 if (fOpen & RTFILE_O_TRUNCATE)
113 fOpenMode |= O_TRUNC;
114
115 switch (fOpen & RTFILE_O_ACCESS_MASK)
116 {
117 case RTFILE_O_READ:
118 fOpenMode |= FREAD;
119 break;
120 case RTFILE_O_WRITE:
121 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE : FWRITE;
122 break;
123 case RTFILE_O_READWRITE:
124 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE | FREAD : FWRITE | FREAD;
125 break;
126 default:
127 AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
128 IPRT_DARWIN_RESTORE_EFL_AC();
129 return VERR_INVALID_PARAMETER;
130 }
131
132 pThis->fOpenMode = fOpenMode;
133 rc = vnode_open(pszFilename, fOpenMode, fCMode, fVnFlags, &pThis->hVnode, pThis->hVfsCtx);
134 if (rc == 0)
135 {
136 *phFile = pThis;
137 IPRT_DARWIN_RESTORE_EFL_AC();
138 return VINF_SUCCESS;
139 }
140
141 rc = RTErrConvertFromErrno(rc);
142 }
143 else
144 rc = VERR_INTERNAL_ERROR_5;
145 RTMemFree(pThis);
146
147 IPRT_DARWIN_RESTORE_EFL_AC();
148 return rc;
149}
150
151
152RTDECL(int) RTFileClose(RTFILE hFile)
153{
154 if (hFile == NIL_RTFILE)
155 return VINF_SUCCESS;
156
157 RTFILEINT *pThis = hFile;
158 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
159 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
160 pThis->u32Magic = ~RTFILE_MAGIC;
161
162 IPRT_DARWIN_SAVE_EFL_AC();
163 errno_t rc = vnode_close(pThis->hVnode, pThis->fOpenMode & (FREAD | FWRITE), pThis->hVfsCtx);
164 IPRT_DARWIN_RESTORE_EFL_AC();
165
166 RTMemFree(pThis);
167 return RTErrConvertFromErrno(rc);
168}
169
170
171RTDECL(int) RTFileReadAt(RTFILE hFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
172{
173 RTFILEINT *pThis = hFile;
174 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
175 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
176
177 off_t offNative = (off_t)off;
178 AssertReturn((RTFOFF)offNative == off, VERR_OUT_OF_RANGE);
179 IPRT_DARWIN_SAVE_EFL_AC();
180
181#if 0 /* Added in 10.6, grr. */
182 errno_t rc;
183 if (!pcbRead)
184 rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
185 vfs_context_ucred(pThis->hVfsCtx), NULL, vfs_context_proc(pThis->hVfsCtx));
186 else
187 {
188 int cbLeft = 0;
189 rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
190 vfs_context_ucred(pThis->hVfsCtx), &cbLeft, vfs_context_proc(pThis->hVfsCtx));
191 *pcbRead = cbToRead - cbLeft;
192 }
193 IPRT_DARWIN_RESTORE_EFL_AC();
194 return !rc ? VINF_SUCCESS : RTErrConvertFromErrno(rc);
195
196#else
197 uio_t hUio = uio_create(1, offNative, UIO_SYSSPACE, UIO_READ);
198 if (!hUio)
199 {
200 IPRT_DARWIN_RESTORE_EFL_AC();
201 return VERR_NO_MEMORY;
202 }
203 errno_t rc;
204 if (uio_addiov(hUio, (user_addr_t)(uintptr_t)pvBuf, cbToRead) == 0)
205 {
206 rc = VNOP_READ(pThis->hVnode, hUio, 0 /*ioflg*/, pThis->hVfsCtx);
207 off_t const cbActual = cbToRead - uio_resid(hUio);
208 if (pcbRead)
209 *pcbRead = cbActual;
210 if (rc == 0)
211 {
212 pThis->offFile += (uint64_t)cbActual;
213 if (cbToRead != (uint64_t)cbActual)
214 rc = VERR_FILE_IO_ERROR;
215 }
216 else
217 rc = RTErrConvertFromErrno(rc);
218 }
219 else
220 rc = VERR_INTERNAL_ERROR_3;
221 uio_free(hUio);
222 IPRT_DARWIN_RESTORE_EFL_AC();
223 return rc;
224#endif
225}
226
227
228RTDECL(int) RTFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
229{
230 RTFILEINT *pThis = hFile;
231 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
232 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
233
234 return RTFileReadAt(hFile, pThis->offFile, pvBuf, cbToRead, pcbRead);
235}
236
237
238RTDECL(int) RTFileQuerySize(RTFILE hFile, uint64_t *pcbSize)
239{
240 RTFILEINT *pThis = hFile;
241 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
242 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
243
244 /*
245 * Query the data size attribute.
246 * Note! Allocate extra attribute buffer space to be on the safe side.
247 */
248 union
249 {
250 struct vnode_attr VAttr;
251 uint8_t abPadding[sizeof(struct vnode_attr) * 2];
252 } uBuf;
253 RT_ZERO(uBuf);
254 struct vnode_attr *pVAttr = &uBuf.VAttr;
255
256 VATTR_INIT(pVAttr);
257 VATTR_WANTED(pVAttr, va_data_size);
258
259 errno_t rc = vnode_getattr(pThis->hVnode, pVAttr, pThis->hVfsCtx);
260 if (!rc)
261 {
262 *pcbSize = pVAttr->va_data_size;
263 return VINF_SUCCESS;
264 }
265 return RTErrConvertFromErrno(rc);
266}
267
268
269RTDECL(int) RTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
270{
271 RTFILEINT *pThis = hFile;
272 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
273 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
274
275 uint64_t offNew;
276 switch (uMethod)
277 {
278 case RTFILE_SEEK_BEGIN:
279 AssertReturn(offSeek >= 0, VERR_NEGATIVE_SEEK);
280 offNew = offSeek;
281 break;
282
283 case RTFILE_SEEK_CURRENT:
284 offNew = pThis->offFile + offSeek;
285 break;
286
287 case RTFILE_SEEK_END:
288 {
289 uint64_t cbFile = 0;
290 int rc = RTFileQuerySize(hFile, &cbFile);
291 if (RT_SUCCESS(rc))
292 offNew = cbFile + offSeek;
293 else
294 return rc;
295 break;
296 }
297
298 default:
299 return VERR_INVALID_PARAMETER;
300 }
301
302 if ((RTFOFF)offNew >= 0)
303 {
304 pThis->offFile = offNew;
305 if (poffActual)
306 *poffActual = offNew;
307 return VINF_SUCCESS;
308 }
309 return VERR_NEGATIVE_SEEK;
310}
311
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