fileio.cpp revision e7e59dc21d2ebdef0056dda548193a5e2c2f6952
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/* $Id$ */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** @file
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * innotek Portable Runtime - File I/O.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copyright (C) 2006-2007 innotek GmbH
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
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 *
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.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
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 */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/*******************************************************************************
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync* Header Files *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync*******************************************************************************/
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#include <iprt/file.h>
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#include <iprt/alloc.h>
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync#include <iprt/assert.h>
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync#include <iprt/alloca.h>
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync#include <iprt/err.h>
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync#include "internal/file.h"
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/*******************************************************************************
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync* Global Variables *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync*******************************************************************************/
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced set open flags for files opened read-only. */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsyncstatic unsigned g_fOpenReadSet = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced cleared open flags for files opened read-only. */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncstatic unsigned g_fOpenReadMask = 0;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced set open flags for files opened write-only. */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncstatic unsigned g_fOpenWriteSet = 0;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync/** Set of forced cleared open flags for files opened write-only. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenWriteMask = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced set open flags for files opened read-write. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenReadWriteSet = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/** Set of forced cleared open flags for files opened read-write. */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncstatic unsigned g_fOpenReadWriteMask = 0;
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync/**
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 *
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.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsyncRTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync{
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync /*
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.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync if ((fSet | fMask) & ~RTFILE_O_WRITE_THROUGH)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync return VERR_INVALID_PARAMETER;
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync switch (fOpenForAccess)
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync case RTFILE_O_READ:
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync g_fOpenReadSet = fSet;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync g_fOpenReadMask = fMask;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync case RTFILE_O_WRITE:
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync g_fOpenWriteSet = fSet;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync g_fOpenWriteMask = fMask;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync case RTFILE_O_READWRITE:
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync g_fOpenReadWriteSet = fSet;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync g_fOpenReadWriteMask = fMask;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync default:
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess));
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return VERR_INVALID_PARAMETER;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync }
c83b72ede860a1be6bdd520f7d13619b0791c1advboxsync return VINF_SUCCESS;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync}
c83b72ede860a1be6bdd520f7d13619b0791c1advboxsync
c83b72ede860a1be6bdd520f7d13619b0791c1advboxsync
c83b72ede860a1be6bdd520f7d13619b0791c1advboxsync/**
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Adjusts and validates the flags.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns IPRT status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param pfOpen Pointer to the user specified flags on input.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Updated on successful return.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @internal
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncint rtFileRecalcAndValidateFlags(unsigned *pfOpen)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Recalc.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync unsigned fOpen = *pfOpen;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync switch (fOpen & RTFILE_O_ACCESS_MASK)
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync {
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync case RTFILE_O_READ:
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync fOpen |= g_fOpenReadSet;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync fOpen &= ~g_fOpenReadMask;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync case RTFILE_O_WRITE:
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync fOpen |= g_fOpenWriteSet;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync fOpen &= ~g_fOpenWriteMask;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync case RTFILE_O_READWRITE:
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync fOpen |= g_fOpenReadWriteSet;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync fOpen &= ~g_fOpenReadWriteMask;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync break;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync default:
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return VERR_INVALID_PARAMETER;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync /*
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * Validate .
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if ( !(fOpen & RTFILE_O_ACCESS_MASK)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & (~RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#else
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & ~RTFILE_O_VALID_MASK)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#endif
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) == RTFILE_O_TRUNCATE
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync || ( fOpen & RTFILE_O_NOT_CONTENT_INDEXED
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))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync )
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync {
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync AssertMsgFailed(("Invalid parameters! fOpen=%#x\n", fOpen));
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync return VERR_INVALID_PARAMETER;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync }
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync /* done */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync *pfOpen = fOpen;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync return VINF_SUCCESS;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync}
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync/**
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Read bytes from a file at a given offset.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * This function may modify the file position.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync *
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.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileRead(File, pvBuf, cbToRead, pcbRead);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return rc;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync}
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync/**
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Write bytes to a file at a given offset.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * This function may modify the file position.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync *
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.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileWrite(File, pvBuf, cbToWrite, pcbWritten);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return rc;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync}
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/**
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Gets the current file position.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * @returns File offset.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns ~0UUL on failure.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @param File File handle.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(uint64_t) RTFileTell(RTFILE File)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Call the seek api to query the stuff.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync uint64_t off = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return off;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc));
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return ~0ULL;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync}
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/**
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Determine the maximum file size.
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync *
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 */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(RTFOFF) RTFileGetMaxSize(RTFILE File)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF cbMax;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileGetMaxSizeEx(File, &cbMax);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return RT_SUCCESS(rc) ? cbMax : -1;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync}
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/**
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Determine the maximum file size.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
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.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTR3DECL(int) RTFileGetMaxSizeEx(RTFILE File, PRTFOFF pcbMax)
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync{
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Save the current location
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uint64_t offOld;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &offOld);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync if (RT_FAILURE(rc))
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync return rc;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync /*
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync * Perform a binary search for the max file size.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync uint64_t offLow = 0;
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 for (;;)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uint64_t cbInterval = (offHigh - offLow) >> 1;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (cbInterval == 0)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (pcbMax)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *pcbMax = offLow;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return RTFileSeek(File, offOld, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(File, offLow + cbInterval, RTFILE_SEEK_BEGIN, NULL);
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync if (RT_FAILURE(rc))
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync offHigh = offLow + cbInterval;
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync else
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync offLow = offLow + cbInterval;
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync }
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync}
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync/**
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copies a file given the handles to both files.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns VBox Status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
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.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst)
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync{
a1e68eac9a1478fd1957826cb4bd631f808b7cc0vboxsync return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL);
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync}
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync/**
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * Copies a file.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync *
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @returns VERR_ALREADY_EXISTS if the destination file exists.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync * @returns VBox Status code.
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync *
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.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsyncRTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, PFNRTPROGRESS pfnProgress, void *pvUser)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync{
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Validate input.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
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
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Open the files.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFILE FileSrc;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc = RTFileOpen(&FileSrc, pszSrc, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFILE FileDst;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileOpen(&FileDst, pszDst, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Call the ByHandles version and let it do the job.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Close the files regardless of the result.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Don't bother cleaning up or anything like that.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync int rc2 = RTFileClose(FileDst);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertRC(rc2);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = rc2;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync int rc2 = RTFileClose(FileSrc);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync AssertRC(rc2);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = rc2;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return rc;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync}
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync/**
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Copies a file given the handles to both files and
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * provide progress callbacks.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * @returns VBox Status code.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync *
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.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
eac18a2a75654a71176720265be9d2e77658481fvboxsyncRTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync{
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync /*
eac18a2a75654a71176720265be9d2e77658481fvboxsync * Validate input.
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync */
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);
eac18a2a75654a71176720265be9d2e77658481fvboxsync
eac18a2a75654a71176720265be9d2e77658481fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Save file offset.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
eac18a2a75654a71176720265be9d2e77658481fvboxsync RTFOFF offSrcSaved;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync return rc;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Get the file size.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF cbSrc;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync if (RT_FAILURE(rc))
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync return rc;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync /*
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync * Allocate buffer.
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync */
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync size_t cbBuf;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uint8_t *pbBufFree = NULL;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uint8_t *pbBuf;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync if (cbSrc < _512K)
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync {
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync cbBuf = 8*_1K;
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync pbBuf = (uint8_t *)alloca(cbBuf);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
1acf60ed9c490056043f7bfa524f2de1a431ab10vboxsync else
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync {
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync cbBuf = _128K;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (pbBuf)
a05a2534a4aeaed368d626a462d856c0d352c97dvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Seek to the start of each file
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * and set the size of the destination file.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileSetSize(FileDst, cbSrc);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc) && pfnProgress)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = pfnProgress(0, pvUser);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_SUCCESS(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copy loop.
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync unsigned uPercentage = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF off = 0;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF cbPercent = cbSrc / 100;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF offNextPercent = cbPercent;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync while (off < cbSrc)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /* copy block */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync RTFOFF cbLeft = cbSrc - off;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /* advance */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync off += cbBlock;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (pfnProgress && offNextPercent < off)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync while (offNextPercent < off)
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync {
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync uPercentage++;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync offNextPercent += cbPercent;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rc = pfnProgress(uPercentage, pvUser);
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync if (RT_FAILURE(rc))
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync break;
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync }
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync#if 0
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync /*
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync * Copy OS specific data (EAs and stuff).
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync */
d0eec04539061d14a7e51f492aea90fa5394615fvboxsync rtFileCopyOSStuff(FileSrc, FileDst);
#endif
/* 100% */
if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
rc = pfnProgress(100, pvUser);
}
}
RTMemTmpFree(pbBufFree);
}
else
rc = VERR_NO_MEMORY;
/*
* Restore source position.
*/
RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);
return rc;
}