fileio.cpp revision e7e59dc21d2ebdef0056dda548193a5e2c2f6952
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * innotek Portable Runtime - File I/O.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copyright (C) 2006-2007 innotek GmbH
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * available from http://www.virtualbox.org. This file is free software;
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * General Public License (GPL) as published by the Free Software
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
010ad423d45c61ef874fa1602d46459a798b54d2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * The contents of this file may alternatively be used under the terms
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * of the Common Development and Distribution License Version 1.0
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * VirtualBox OSE distribution, in which case the provisions of the
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * CDDL are applicable instead of those of the GPL.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * You may elect to license modified versions of this file under the
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * terms and conditions of either the GPL or the CDDL or both.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/*******************************************************************************
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync* Header Files *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync*******************************************************************************/
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/*******************************************************************************
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync* Global Variables *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync*******************************************************************************/
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced set open flags for files opened read-only. */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsyncstatic unsigned g_fOpenReadSet = 0;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced cleared open flags for files opened read-only. */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncstatic unsigned g_fOpenReadMask = 0;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced set open flags for files opened write-only. */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncstatic unsigned g_fOpenWriteSet = 0;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced cleared open flags for files opened write-only. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenWriteMask = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced set open flags for files opened read-write. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenReadWriteSet = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced cleared open flags for files opened read-write. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenReadWriteMask = 0;
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * Force the use of open flags for all files opened after the setting is
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * changed. The caller is responsible for not causing races with RTFileOpen().
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @returns iprt status code.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @param fOpenForAccess Access mode to which the set/mask settings apply.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @param fSet Open flags to be forced set.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @param fMask Open flags to be masked out.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncRTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * For now allow only RTFILE_O_WRITE_THROUGH. The other flags either
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * make no sense in this context or are not useful to apply to all files.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess));
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Adjusts and validates the flags.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns IPRT status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param pfOpen Pointer to the user specified flags on input.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Updated on successful return.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @internal
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * Validate .
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & (~RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) == RTFILE_O_TRUNCATE
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync && !( (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE))
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync AssertMsgFailed(("Invalid parameters! fOpen=%#x\n", fOpen));
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Read bytes from a file at a given offset.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * This function may modify the file position.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * @returns iprt status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param File Handle to the file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param off Where to read.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param pvBuf Where to put the bytes we read.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param cbToRead How much to read.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param *pcbRead How much we actually read.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * If NULL an error will be returned for a partial read.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL);
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Write bytes to a file at a given offset.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * This function may modify the file position.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @returns iprt status code.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @param File Handle to the file.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * @param off Where to write.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param pvBuf What to write.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param cbToWrite How much to write.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param *pcbWritten How much we actually wrote.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * If NULL an error will be returned for a partial write.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileWrite(File, pvBuf, cbToWrite, pcbWritten);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Gets the current file position.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @returns File offset.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns ~0UUL on failure.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param File File handle.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Call the seek api to query the stuff.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc));
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Determine the maximum file size.
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync * @returns The max size of the file.
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync * -1 on failure, the file position is undefined.
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync * @param File Handle to the file.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @see RTFileGetMaxSizeEx.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Determine the maximum file size.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns IPRT status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param File Handle to the file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param pcbMax Where to store the max file size.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @see RTFileGetMaxSize.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileGetMaxSizeEx(RTFILE File, PRTFOFF pcbMax)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Save the current location
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &offOld);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * Perform a binary search for the max file size.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uint64_t offHigh = 8 * _1T; /* we don't need bigger files */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /** @todo r=bird: This isn't doing the trick for windows (at least not vista).
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Close to offHigh is returned regardless of NTFS or FAT32.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * We might have to make this code OS specific...
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * In the worse case, we'll have to try GetVolumeInformationByHandle on vista and fall
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * back on NtQueryVolumeInformationFile(,,,, FileFsAttributeInformation) else where, and
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * check for known file system names. (For LAN shares we'll have to figure out the remote
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * file system.) */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync //uint64_t offHigh = INT64_MAX;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return RTFileSeek(File, offOld, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(File, offLow + cbInterval, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copies a file given the handles to both files.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns VBox Status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param FileSrc The source file. The file position is unaltered.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param FileDst The destination file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * On successful returns the file position is at the end of the file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * On failures the file position and size is undefined.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst)
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL);
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * Copies a file.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @returns VERR_ALREADY_EXISTS if the destination file exists.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @returns VBox Status code.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @param pszSrc The path to the source file.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @param pszDst The path to the destination file.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * This file will be created.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @param pfnProgress Pointer to callback function for reporting progress.
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync * @param pvUser User argument to pass to pfnProgress along with the completion precentage.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, PFNRTPROGRESS pfnProgress, void *pvUser)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Validate input.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgReturn(VALID_PTR(pszSrc), ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgReturn(*pszSrc, ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgReturn(VALID_PTR(pszDst), ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgReturn(*pszDst, ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Open the files.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileOpen(&FileSrc, pszSrc, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileOpen(&FileDst, pszDst, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Call the ByHandles version and let it do the job.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Close the files regardless of the result.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Don't bother cleaning up or anything like that.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Copies a file given the handles to both files and
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * provide progress callbacks.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns VBox Status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param FileSrc The source file. The file position is unaltered.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param FileDst The destination file.
eac18a2a75654a71176720265be9d2e77658481fvboxsync * On successful returns the file position is at the end of the file.
eac18a2a75654a71176720265be9d2e77658481fvboxsync * On failures the file position and size is undefined.
eac18a2a75654a71176720265be9d2e77658481fvboxsync * @param pfnProgress Pointer to callback function for reporting progress.
eac18a2a75654a71176720265be9d2e77658481fvboxsync * @param pvUser User argument to pass to pfnProgress along with the completion precentage.
eac18a2a75654a71176720265be9d2e77658481fvboxsyncRTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
eac18a2a75654a71176720265be9d2e77658481fvboxsync * Validate input.
eac18a2a75654a71176720265be9d2e77658481fvboxsync AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);
eac18a2a75654a71176720265be9d2e77658481fvboxsync AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Save file offset.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Get the file size.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Allocate buffer.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Seek to the start of each file
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * and set the size of the destination file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copy loop.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync unsigned uPercentage = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /* copy block */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /* advance */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copy OS specific data (EAs and stuff).
return rc;