fileio-posix.cpp revision aa3a3139e2c5edb3469513f5b07cdd39fc89a053
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * IPRT - File I/O, POSIX, Part 1.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2010 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The contents of this file may alternatively be used under the terms
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of the Common Development and Distribution License Version 1.0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * CDDL are applicable instead of those of the GPL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * You may elect to license modified versions of this file under the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* RT_OS_SOLARIS */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Defined Constants And Macros *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Default file permissions for newly created files. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fRc = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LogFlow(("RTFileExists(%p={%s}): returns %RTbool\n", pszPath, pszPath, fRc));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Validate input.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Merge forced open flags and validate them.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertMsgFailed(("Invalid parameters! fOpen=%#llx\n", fOpen));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calculate open mode flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static int s_fHave_O_CLOEXEC = 0; /* {-1,0,1}; since Linux 2.6.23 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!(fOpen & RTFILE_O_INHERIT) && s_fHave_O_CLOEXEC >= 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* O_DIRECT is mandatory to get async I/O working on Linux. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(O_DIRECT) && (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Disable the kernel cache. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_OPEN_CREATE: fOpenMode |= O_CREAT; break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_CREATE: fOpenMode |= O_CREAT | O_EXCL; break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_CREATE_REPLACE: fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fOpenMode |= O_RDONLY; /* RTFILE_O_APPEND is ignored. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_WRONLY : O_WRONLY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_RDWR : O_RDWR;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#llx\n", fOpen));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* File mode. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ? (fOpen & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo sharing! */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtPathToNative(&pszNativeFilename, pszFilename, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* XXX Darwin? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtPathOpenPathNoFollowFh(pszNativeFilename, &fhDir, &pszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fh = openat(fhDir, pszName, fOpenMode, fMode | O_NOFOLLOW);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (fh >= 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_fHave_O_CLOEXEC = fcntl(fh, F_GETFD, 0) > 0 ? 1 : -1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Mark the file handle close on exec, unless inherit is specified.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !(fOpenMode & O_NOINHERIT) /* Take care since it might be a zero value dummy. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync iErr = fcntl(fh, F_SETFD, FD_CLOEXEC) >= 0 ? 0 : errno;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Switch direct I/O on now if requested and required.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(RT_OS_DARWIN) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Implement / emulate file sharing.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We need another mode which allows skipping this stuff completely
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and do things the UNIX way. So for the present this is just a debug
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * aid that can be enabled by developers too lazy to test on Windows.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 && defined(RT_OS_LINUX)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* This approach doesn't work because only knfsd checks for these
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync buggers. :-( */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* 0 && RT_OS_LINUX */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* This emulation is incomplete but useful. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo Use fshare_t and associates, it's a perfect match. see sys/fcntl.h */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We're done.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LogFlow(("RTFileOpen(%p:{%RTfile}, %p:{%s}, %#llx): returns %Rrc\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pFile, *pFile, pszFilename, pszFilename, fOpen, rc));
return VINF_SUCCESS;
return VINF_SUCCESS;
if (uNative < 0)
return VERR_INVALID_HANDLE;
return VINF_SUCCESS;
int fd;
switch (enmStdHandle)
return NIL_RTFILE;
char const *pszNativeFilename;
return rc;
static const unsigned aSeekRecode[] =
return VERR_INVALID_PARAMETER;
return VERR_NOT_SUPPORTED;
if (offCurrent != ~0)
if (poffActual)
return VINF_SUCCESS;
if (cbToRead <= 0)
return VINF_SUCCESS;
if (cbRead >= 0)
if (pcbRead)
if (cbReadPart <= 0)
if (cbReadPart == 0)
return VERR_EOF;
return VINF_SUCCESS;
if (cbToWrite <= 0)
return VINF_SUCCESS;
if (cbWritten >= 0)
if (pcbWritten)
ssize_t cbWrittenPart = write(RTFileToNative(hFile), (const char *)pvBuf + cbWritten, cbToWrite - cbWritten);
if (cbWrittenPart <= 0)
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
#if defined(_MSC_VER) || (defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006))
return VINF_SUCCESS;
#if defined(RT_OS_SOLARIS)
return VINF_SUCCESS;
#ifdef RT_OS_DARWIN
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc2;
return rc;
if (cbInterval == 0)
if (pcbMax)
if (fFlags >= 0)
return VINF_SUCCESS;
RTR3DECL(int) RTFileIoCtl(RTFILE hFile, unsigned long ulRequest, void *pvData, unsigned cbData, int *piRet)
if (piRet)
return VERR_INVALID_PARAMETER;
return rc;
return VINF_SUCCESS;
AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
return rc;