111
RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, unsigned fOpen)
114
RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint32_t fOpen)
114
117
* Validate input.
116
if (!VALID_PTR(pFile))
118
AssertMsgFailed(("Invalid pFile %p\n", pFile));
119
return VERR_INVALID_PARAMETER;
119
AssertPtrReturn(pFile, VERR_INVALID_POINTER);
121
120
*pFile = NIL_RTFILE;
122
if (!VALID_PTR(pszFilename))
124
AssertMsgFailed(("Invalid pszFilename %p\n", pszFilename));
125
return VERR_INVALID_PARAMETER;
121
AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
129
124
* Merge forced open flags and validate them.
181
181
switch (fOpen & RTFILE_O_ACCESS_MASK)
183
case RTFILE_O_READ: fOpenMode |= O_RDONLY; break;
184
case RTFILE_O_WRITE: fOpenMode |= O_WRONLY; break;
185
case RTFILE_O_READWRITE: fOpenMode |= O_RDWR; break;
184
fOpenMode |= O_RDONLY; /* RTFILE_O_APPEND is ignored. */
187
fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_WRONLY : O_WRONLY;
189
case RTFILE_O_READWRITE:
190
fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_RDWR : O_RDWR;
187
193
AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
188
194
return VERR_INVALID_PARAMETER;
217
225
* Mark the file handle close on exec, unless inherit is specified.
219
if ( !(fOpen & RTFILE_O_INHERIT)
227
if ( (fOpen & RTFILE_O_INHERIT)
220
228
#ifdef O_NOINHERIT
221
|| (fOpenMode & O_NOINHERIT) /* careful since it could be a dummy. */
223
|| fcntl(fh, F_SETFD, FD_CLOEXEC) >= 0)
229
&& !(fOpenMode & O_NOINHERIT) /* Take care since it might be a zero value dummy. */
232
iErr = fcntl(fh, F_SETFD, FD_CLOEXEC) >= 0 ? 0 : errno;
235
* Switch direct I/O on now if requested and required.
237
#if defined(RT_OS_DARWIN) \
238
|| (defined(RT_OS_SOLARIS) && !defined(IN_GUEST))
239
if (iErr == 0 && (fOpen & RTFILE_O_NO_CACHE))
241
# if defined(RT_OS_DARWIN)
242
iErr = fcntl(fh, F_NOCACHE, 1) >= 0 ? 0 : errno;
244
iErr = directio(fh, DIRECTIO_ON) >= 0 ? 0 : errno;
250
* Implement / emulate file sharing.
252
* We need another mode which allows skipping this stuff completely
253
* and do things the UNIX way. So for the present this is just a debug
254
* aid that can be enabled by developers too lazy to test on Windows.
256
#if 0 && defined(RT_OS_LINUX)
259
/* This approach doesn't work because only knfsd checks for these
262
switch (fOpen & RTFILE_O_DENY_MASK)
266
case RTFILE_O_DENY_NONE:
267
case RTFILE_O_DENY_NOT_DELETE:
268
iLockOp = LOCK_MAND | LOCK_READ | LOCK_WRITE;
270
case RTFILE_O_DENY_READ:
271
case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
272
iLockOp = LOCK_MAND | LOCK_WRITE;
274
case RTFILE_O_DENY_WRITE:
275
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
276
iLockOp = LOCK_MAND | LOCK_READ;
278
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
279
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
283
iErr = flock(fh, iLockOp | LOCK_NB);
285
iErr = errno == EAGAIN ? ETXTBSY : 0;
287
#endif /* 0 && RT_OS_LINUX */
291
/* This emulation is incomplete but useful. */
292
switch (fOpen & RTFILE_O_DENY_MASK)
296
case RTFILE_O_DENY_NONE:
297
case RTFILE_O_DENY_NOT_DELETE:
298
case RTFILE_O_DENY_READ:
299
case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
301
case RTFILE_O_DENY_WRITE:
302
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
303
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
304
case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
305
if (fOpen & RTFILE_O_WRITE)
307
iErr = flock(fh, LOCK_EX | LOCK_NB);
309
iErr = errno == EAGAIN ? ETXTBSY : 0;
316
/** @todo Use fshare_t and associates, it's a perfect match. see sys/fcntl.h */
225
324
*pFile = (RTFILE)fh;
226
325
Assert((int)*pFile == fh);