VirtualBox

Changeset 77825 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 21, 2019 12:33:42 PM (6 years ago)
Author:
vboxsync
Message:

IPRT: Split RTFileCopyEx and RTFileCopyByHandlesEx out of r3/fileio.cpp so we can do platform specific implementations of these. bugref:9172

Location:
trunk/src/VBox/Runtime
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r77816 r77825  
    666666        generic/RTEnvDupEx-generic.cpp \
    667667        generic/RTFileCopy-generic.cpp \
     668        generic/RTFileCopyEx-generic.cpp \
     669        generic/RTFileCopyByHandlesEx-generic.cpp \
    668670        generic/RTFileCopyRange-generic.cpp \
    669671        generic/RTFileCopyRangeEx-generic.cpp \
     
    17881790        generic/RTEnvDupEx-generic.cpp \
    17891791        generic/RTFileCopy-generic.cpp \
     1792        generic/RTFileCopyEx-generic.cpp \
     1793        generic/RTFileCopyByHandlesEx-generic.cpp \
    17901794        generic/RTFileQuerySize-generic.cpp \
    17911795        generic/RTFileReadAll-generic.cpp \
  • trunk/src/VBox/Runtime/generic/RTFileCopyByHandlesEx-generic.cpp

    r77822 r77825  
    11/* $Id$ */
    22/** @file
    3  * IPRT - File I/O.
     3 * IPRT - RTFileCopyByHandlesEx, generic implementation.
    44 */
    55
     
    3232#include <iprt/file.h>
    3333
     34#include <iprt/alloca.h>
     35#include <iprt/assert.h>
    3436#include <iprt/mem.h>
    35 #include <iprt/assert.h>
    36 #include <iprt/alloca.h>
    37 #include <iprt/string.h>
    38 #include <iprt/err.h>
    39 #include "internal/file.h"
    40 
    41 
    42 /*********************************************************************************************************************************
    43 *   Global Variables                                                                                                             *
    44 *********************************************************************************************************************************/
    45 /** Set of forced set open flags for files opened read-only. */
    46 static unsigned g_fOpenReadSet = 0;
    47 
    48 /** Set of forced cleared open flags for files opened read-only. */
    49 static unsigned g_fOpenReadMask = 0;
    50 
    51 /** Set of forced set open flags for files opened write-only. */
    52 static unsigned g_fOpenWriteSet = 0;
    53 
    54 /** Set of forced cleared open flags for files opened write-only. */
    55 static unsigned g_fOpenWriteMask = 0;
    56 
    57 /** Set of forced set open flags for files opened read-write. */
    58 static unsigned g_fOpenReadWriteSet = 0;
    59 
    60 /** Set of forced cleared open flags for files opened read-write. */
    61 static unsigned g_fOpenReadWriteMask = 0;
    62 
    63 
    64 /**
    65  * Force the use of open flags for all files opened after the setting is
    66  * changed. The caller is responsible for not causing races with RTFileOpen().
    67  *
    68  * @returns iprt status code.
    69  * @param   fOpenForAccess  Access mode to which the set/mask settings apply.
    70  * @param   fSet            Open flags to be forced set.
    71  * @param   fMask           Open flags to be masked out.
    72  */
    73 RTR3DECL(int)  RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask)
    74 {
    75     /*
    76      * For now allow only RTFILE_O_WRITE_THROUGH. The other flags either
    77      * make no sense in this context or are not useful to apply to all files.
    78      */
    79     if ((fSet | fMask) & ~RTFILE_O_WRITE_THROUGH)
    80         return VERR_INVALID_PARAMETER;
    81     switch (fOpenForAccess)
    82     {
    83         case RTFILE_O_READ:
    84             g_fOpenReadSet = fSet;
    85             g_fOpenReadMask = fMask;
    86             break;
    87         case RTFILE_O_WRITE:
    88             g_fOpenWriteSet = fSet;
    89             g_fOpenWriteMask = fMask;
    90             break;
    91         case RTFILE_O_READWRITE:
    92             g_fOpenReadWriteSet = fSet;
    93             g_fOpenReadWriteMask = fMask;
    94             break;
    95         default:
    96             AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess));
    97             return VERR_INVALID_PARAMETER;
    98     }
    99     return VINF_SUCCESS;
    100 }
    101 
    102 
    103 /**
    104  * Adjusts and validates the flags.
    105  *
    106  * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API.
    107  *
    108  * @returns IPRT status code.
    109  * @param   pfOpen      Pointer to the user specified flags on input.
    110  *                      Updated on successful return.
    111  * @internal
    112  */
    113 int rtFileRecalcAndValidateFlags(uint64_t *pfOpen)
    114 {
    115     /*
    116      * Recalc.
    117      */
    118     uint32_t fOpen = *pfOpen;
    119     switch (fOpen & RTFILE_O_ACCESS_MASK)
    120     {
    121         case RTFILE_O_READ:
    122             fOpen |= g_fOpenReadSet;
    123             fOpen &= ~g_fOpenReadMask;
    124             break;
    125         case RTFILE_O_WRITE:
    126             fOpen |= g_fOpenWriteSet;
    127             fOpen &= ~g_fOpenWriteMask;
    128             break;
    129         case RTFILE_O_READWRITE:
    130             fOpen |= g_fOpenReadWriteSet;
    131             fOpen &= ~g_fOpenReadWriteMask;
    132             break;
    133 #ifdef RT_OS_WINDOWS
    134         case RTFILE_O_ATTR_ONLY:
    135             if (fOpen & RTFILE_O_ACCESS_ATTR_MASK)
    136                 break;
    137 #endif
    138         default:
    139             AssertMsgFailed(("Invalid access mode value, fOpen=%#llx\n", fOpen));
    140             return VERR_INVALID_PARAMETER;
    141     }
    142 
    143     /*
    144      * Validate                                                                                                                                       .
    145      */
    146 #ifdef RT_OS_WINDOWS
    147     AssertMsgReturn((fOpen & RTFILE_O_ACCESS_MASK) || (fOpen & RTFILE_O_ACCESS_ATTR_MASK),
    148                     ("Missing RTFILE_O_READ/WRITE/ACCESS_ATTR: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    149 #else
    150     AssertMsgReturn(fOpen & RTFILE_O_ACCESS_MASK, ("Missing RTFILE_O_READ/WRITE: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    151 #endif
    152 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    153     AssertMsgReturn(!(fOpen & (~(uint64_t)RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK)), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    154 #else
    155     AssertMsgReturn(!(fOpen & ~(uint64_t)RTFILE_O_VALID_MASK), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    156 #endif
    157     AssertMsgReturn((fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) != RTFILE_O_TRUNCATE, ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    158 
    159     switch (fOpen & RTFILE_O_ACTION_MASK)
    160     {
    161         case 0: /* temporarily */
    162             AssertMsgFailed(("Missing RTFILE_O_OPEN/CREATE*! (continuable assertion)\n"));
    163             fOpen |= RTFILE_O_OPEN;
    164             break;
    165         case RTFILE_O_OPEN:
    166             AssertMsgReturn(!(RTFILE_O_NOT_CONTENT_INDEXED & fOpen), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    167         case RTFILE_O_OPEN_CREATE:
    168         case RTFILE_O_CREATE:
    169         case RTFILE_O_CREATE_REPLACE:
    170             break;
    171         default:
    172             AssertMsgFailed(("Invalid action value: fOpen=%#llx\n", fOpen));
    173             return VERR_INVALID_PARAMETER;
    174     }
    175 
    176     switch (fOpen & RTFILE_O_DENY_MASK)
    177     {
    178         case 0: /* temporarily */
    179             AssertMsgFailed(("Missing RTFILE_O_DENY_*! (continuable assertion)\n"));
    180             fOpen |= RTFILE_O_DENY_NONE;
    181             break;
    182         case RTFILE_O_DENY_NONE:
    183         case RTFILE_O_DENY_READ:
    184         case RTFILE_O_DENY_WRITE:
    185         case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
    186         case RTFILE_O_DENY_NOT_DELETE:
    187         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ:
    188         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE:
    189         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
    190             break;
    191         default:
    192             AssertMsgFailed(("Invalid deny value: fOpen=%#llx\n", fOpen));
    193             return VERR_INVALID_PARAMETER;
    194     }
    195 
    196     /* done */
    197     *pfOpen = fOpen;
    198     return VINF_SUCCESS;
    199 }
    200 
    201 
    202 /**
    203  * Gets the current file position.
    204  *
    205  * @returns File offset.
    206  * @returns ~0UUL on failure.
    207  * @param   File        File handle.
    208  */
    209 RTR3DECL(uint64_t)  RTFileTell(RTFILE File)
    210 {
    211     /*
    212      * Call the seek api to query the stuff.
    213      */
    214     uint64_t off = 0;
    215     int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off);
    216     if (RT_SUCCESS(rc))
    217         return off;
    218     AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc));
    219     return ~0ULL;
    220 }
    221 
    222 
    223 /**
    224  * Determine the maximum file size.
    225  *
    226  * @returns The max size of the file.
    227  *          -1 on failure, the file position is undefined.
    228  * @param   File        Handle to the file.
    229  * @see     RTFileGetMaxSizeEx.
    230  */
    231 RTR3DECL(RTFOFF) RTFileGetMaxSize(RTFILE File)
    232 {
    233     RTFOFF cbMax;
    234     int rc = RTFileGetMaxSizeEx(File, &cbMax);
    235     return RT_SUCCESS(rc) ? cbMax : -1;
    236 }
    237 
    238 
    239 RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst)
    240 {
    241     return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL);
    242 }
    243 
    244 
    245 RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    246 {
    247     /*
    248      * Validate input.
    249      */
    250     AssertMsgReturn(VALID_PTR(pszSrc), ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
    251     AssertMsgReturn(*pszSrc, ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
    252     AssertMsgReturn(VALID_PTR(pszDst), ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
    253     AssertMsgReturn(*pszDst, ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
    254     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    255     AssertMsgReturn(!(fFlags & ~RTFILECOPY_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    256 
    257     /*
    258      * Open the files.
    259      */
    260     RTFILE FileSrc;
    261     int rc = RTFileOpen(&FileSrc, pszSrc,
    262                         RTFILE_O_READ | RTFILE_O_OPEN
    263                         | (fFlags & RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    264     if (RT_SUCCESS(rc))
    265     {
    266         RTFILE FileDst;
    267         rc = RTFileOpen(&FileDst, pszDst,
    268                         RTFILE_O_WRITE | RTFILE_O_CREATE
    269                         | (fFlags & RTFILECOPY_FLAGS_NO_DST_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    270         if (RT_SUCCESS(rc))
    271         {
    272             /*
    273              * Call the ByHandles version and let it do the job.
    274              */
    275             rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser);
    276 
    277             /*
    278              * Close the files regardless of the result.
    279              * Don't bother cleaning up or anything like that.
    280              */
    281             int rc2 = RTFileClose(FileDst);
    282             AssertRC(rc2);
    283             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    284                 rc = rc2;
    285         }
    286 
    287         int rc2 = RTFileClose(FileSrc);
    288         AssertRC(rc2);
    289         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    290             rc = rc2;
    291     }
    292     return rc;
    293 }
     37#include <iprt/errcore.h>
    29438
    29539
     
    410154}
    411155
    412 
    413 RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2)
    414 {
    415     return RTFileCompareEx(pszFile1, pszFile2, 0 /*fFlags*/, NULL, NULL);
    416 }
    417 
    418 
    419 RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2)
    420 {
    421     return RTFileCompareByHandlesEx(hFile1, hFile2, 0 /*fFlags*/, NULL, NULL);
    422 }
    423 
    424 
    425 RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    426 {
    427     /*
    428      * Validate input.
    429      */
    430     AssertPtrReturn(pszFile1, VERR_INVALID_POINTER);
    431     AssertReturn(*pszFile1, VERR_INVALID_PARAMETER);
    432     AssertPtrReturn(pszFile2, VERR_INVALID_POINTER);
    433     AssertReturn(*pszFile2, VERR_INVALID_PARAMETER);
    434     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    435     AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    436 
    437     /*
    438      * Open the files.
    439      */
    440     RTFILE hFile1;
    441     int rc = RTFileOpen(&hFile1, pszFile1,
    442                         RTFILE_O_READ | RTFILE_O_OPEN
    443                         | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    444     if (RT_SUCCESS(rc))
    445     {
    446         RTFILE hFile2;
    447         rc = RTFileOpen(&hFile2, pszFile2,
    448                         RTFILE_O_READ | RTFILE_O_OPEN
    449                         | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    450         if (RT_SUCCESS(rc))
    451         {
    452             /*
    453              * Call the ByHandles version and let it do the job.
    454              */
    455             rc = RTFileCompareByHandlesEx(hFile1, hFile2, fFlags,  pfnProgress, pvUser);
    456 
    457             /* Clean up */
    458             int rc2 = RTFileClose(hFile2);
    459             AssertRC(rc2);
    460             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    461                 rc = rc2;
    462         }
    463 
    464         int rc2 = RTFileClose(hFile1);
    465         AssertRC(rc2);
    466         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    467             rc = rc2;
    468     }
    469     return rc;
    470 }
    471 
    472 
    473 RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    474 {
    475     /*
    476      * Validate input.
    477      */
    478     AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
    479     AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
    480     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    481     AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    482 
    483     /*
    484      * Compare the file sizes first.
    485      */
    486     uint64_t cbFile1;
    487     int rc = RTFileGetSize(hFile1, &cbFile1);
    488     if (RT_FAILURE(rc))
    489         return rc;
    490 
    491     uint64_t cbFile2;
    492     rc = RTFileGetSize(hFile1, &cbFile2);
    493     if (RT_FAILURE(rc))
    494         return rc;
    495 
    496     if (cbFile1 != cbFile2)
    497         return VERR_NOT_EQUAL;
    498 
    499 
    500     /*
    501      * Allocate buffer.
    502      */
    503     size_t      cbBuf;
    504     uint8_t    *pbBuf1Free = NULL;
    505     uint8_t    *pbBuf1;
    506     uint8_t    *pbBuf2Free = NULL;
    507     uint8_t    *pbBuf2;
    508     if (cbFile1 < _512K)
    509     {
    510         cbBuf  = 8*_1K;
    511         pbBuf1 = (uint8_t *)alloca(cbBuf);
    512         pbBuf2 = (uint8_t *)alloca(cbBuf);
    513     }
    514     else
    515     {
    516         cbBuf = _128K;
    517         pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
    518         pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
    519     }
    520     if (pbBuf1 && pbBuf2)
    521     {
    522         /*
    523          * Seek to the start of each file
    524          * and set the size of the destination file.
    525          */
    526         rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL);
    527         if (RT_SUCCESS(rc))
    528         {
    529             rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL);
    530             if (RT_SUCCESS(rc) && pfnProgress)
    531                 rc = pfnProgress(0, pvUser);
    532             if (RT_SUCCESS(rc))
    533             {
    534                 /*
    535                  * Compare loop.
    536                  */
    537                 unsigned    uPercentage    = 0;
    538                 RTFOFF      off            = 0;
    539                 RTFOFF      cbPercent      = cbFile1 / 100;
    540                 RTFOFF      offNextPercent = cbPercent;
    541                 while (off < (RTFOFF)cbFile1)
    542                 {
    543                     /* read the blocks */
    544                     RTFOFF cbLeft = cbFile1 - off;
    545                     size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
    546                     rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL);
    547                     if (RT_FAILURE(rc))
    548                         break;
    549                     rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL);
    550                     if (RT_FAILURE(rc))
    551                         break;
    552 
    553                     /* compare */
    554                     if (memcmp(pbBuf1, pbBuf2, cbBlock))
    555                     {
    556                         rc = VERR_NOT_EQUAL;
    557                         break;
    558                     }
    559 
    560                     /* advance */
    561                     off += cbBlock;
    562                     if (pfnProgress && offNextPercent < off)
    563                     {
    564                         while (offNextPercent < off)
    565                         {
    566                             uPercentage++;
    567                             offNextPercent += cbPercent;
    568                         }
    569                         rc = pfnProgress(uPercentage, pvUser);
    570                         if (RT_FAILURE(rc))
    571                             break;
    572                     }
    573                 }
    574 
    575 #if 0
    576                 /*
    577                  * Compare OS specific data (EAs and stuff).
    578                  */
    579                 if (RT_SUCCESS(rc))
    580                     rc = rtFileCompareOSStuff(hFile1, hFile2);
    581 #endif
    582 
    583                 /* 100% */
    584                 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
    585                     rc = pfnProgress(100, pvUser);
    586             }
    587         }
    588     }
    589     else
    590         rc = VERR_NO_MEMORY;
    591     RTMemTmpFree(pbBuf2Free);
    592     RTMemTmpFree(pbBuf1Free);
    593 
    594     return rc;
    595 }
    596 
  • trunk/src/VBox/Runtime/generic/RTFileCopyEx-generic.cpp

    r77822 r77825  
    11/* $Id$ */
    22/** @file
    3  * IPRT - File I/O.
     3 * IPRT - RTFileCopyEx, generic implementation.
    44 */
    55
     
    3232#include <iprt/file.h>
    3333
    34 #include <iprt/mem.h>
    3534#include <iprt/assert.h>
    36 #include <iprt/alloca.h>
    37 #include <iprt/string.h>
    38 #include <iprt/err.h>
    39 #include "internal/file.h"
    40 
    41 
    42 /*********************************************************************************************************************************
    43 *   Global Variables                                                                                                             *
    44 *********************************************************************************************************************************/
    45 /** Set of forced set open flags for files opened read-only. */
    46 static unsigned g_fOpenReadSet = 0;
    47 
    48 /** Set of forced cleared open flags for files opened read-only. */
    49 static unsigned g_fOpenReadMask = 0;
    50 
    51 /** Set of forced set open flags for files opened write-only. */
    52 static unsigned g_fOpenWriteSet = 0;
    53 
    54 /** Set of forced cleared open flags for files opened write-only. */
    55 static unsigned g_fOpenWriteMask = 0;
    56 
    57 /** Set of forced set open flags for files opened read-write. */
    58 static unsigned g_fOpenReadWriteSet = 0;
    59 
    60 /** Set of forced cleared open flags for files opened read-write. */
    61 static unsigned g_fOpenReadWriteMask = 0;
    62 
    63 
    64 /**
    65  * Force the use of open flags for all files opened after the setting is
    66  * changed. The caller is responsible for not causing races with RTFileOpen().
    67  *
    68  * @returns iprt status code.
    69  * @param   fOpenForAccess  Access mode to which the set/mask settings apply.
    70  * @param   fSet            Open flags to be forced set.
    71  * @param   fMask           Open flags to be masked out.
    72  */
    73 RTR3DECL(int)  RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask)
    74 {
    75     /*
    76      * For now allow only RTFILE_O_WRITE_THROUGH. The other flags either
    77      * make no sense in this context or are not useful to apply to all files.
    78      */
    79     if ((fSet | fMask) & ~RTFILE_O_WRITE_THROUGH)
    80         return VERR_INVALID_PARAMETER;
    81     switch (fOpenForAccess)
    82     {
    83         case RTFILE_O_READ:
    84             g_fOpenReadSet = fSet;
    85             g_fOpenReadMask = fMask;
    86             break;
    87         case RTFILE_O_WRITE:
    88             g_fOpenWriteSet = fSet;
    89             g_fOpenWriteMask = fMask;
    90             break;
    91         case RTFILE_O_READWRITE:
    92             g_fOpenReadWriteSet = fSet;
    93             g_fOpenReadWriteMask = fMask;
    94             break;
    95         default:
    96             AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess));
    97             return VERR_INVALID_PARAMETER;
    98     }
    99     return VINF_SUCCESS;
    100 }
    101 
    102 
    103 /**
    104  * Adjusts and validates the flags.
    105  *
    106  * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API.
    107  *
    108  * @returns IPRT status code.
    109  * @param   pfOpen      Pointer to the user specified flags on input.
    110  *                      Updated on successful return.
    111  * @internal
    112  */
    113 int rtFileRecalcAndValidateFlags(uint64_t *pfOpen)
    114 {
    115     /*
    116      * Recalc.
    117      */
    118     uint32_t fOpen = *pfOpen;
    119     switch (fOpen & RTFILE_O_ACCESS_MASK)
    120     {
    121         case RTFILE_O_READ:
    122             fOpen |= g_fOpenReadSet;
    123             fOpen &= ~g_fOpenReadMask;
    124             break;
    125         case RTFILE_O_WRITE:
    126             fOpen |= g_fOpenWriteSet;
    127             fOpen &= ~g_fOpenWriteMask;
    128             break;
    129         case RTFILE_O_READWRITE:
    130             fOpen |= g_fOpenReadWriteSet;
    131             fOpen &= ~g_fOpenReadWriteMask;
    132             break;
    133 #ifdef RT_OS_WINDOWS
    134         case RTFILE_O_ATTR_ONLY:
    135             if (fOpen & RTFILE_O_ACCESS_ATTR_MASK)
    136                 break;
    137 #endif
    138         default:
    139             AssertMsgFailed(("Invalid access mode value, fOpen=%#llx\n", fOpen));
    140             return VERR_INVALID_PARAMETER;
    141     }
    142 
    143     /*
    144      * Validate                                                                                                                                       .
    145      */
    146 #ifdef RT_OS_WINDOWS
    147     AssertMsgReturn((fOpen & RTFILE_O_ACCESS_MASK) || (fOpen & RTFILE_O_ACCESS_ATTR_MASK),
    148                     ("Missing RTFILE_O_READ/WRITE/ACCESS_ATTR: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    149 #else
    150     AssertMsgReturn(fOpen & RTFILE_O_ACCESS_MASK, ("Missing RTFILE_O_READ/WRITE: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    151 #endif
    152 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    153     AssertMsgReturn(!(fOpen & (~(uint64_t)RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK)), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    154 #else
    155     AssertMsgReturn(!(fOpen & ~(uint64_t)RTFILE_O_VALID_MASK), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    156 #endif
    157     AssertMsgReturn((fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) != RTFILE_O_TRUNCATE, ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    158 
    159     switch (fOpen & RTFILE_O_ACTION_MASK)
    160     {
    161         case 0: /* temporarily */
    162             AssertMsgFailed(("Missing RTFILE_O_OPEN/CREATE*! (continuable assertion)\n"));
    163             fOpen |= RTFILE_O_OPEN;
    164             break;
    165         case RTFILE_O_OPEN:
    166             AssertMsgReturn(!(RTFILE_O_NOT_CONTENT_INDEXED & fOpen), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER);
    167         case RTFILE_O_OPEN_CREATE:
    168         case RTFILE_O_CREATE:
    169         case RTFILE_O_CREATE_REPLACE:
    170             break;
    171         default:
    172             AssertMsgFailed(("Invalid action value: fOpen=%#llx\n", fOpen));
    173             return VERR_INVALID_PARAMETER;
    174     }
    175 
    176     switch (fOpen & RTFILE_O_DENY_MASK)
    177     {
    178         case 0: /* temporarily */
    179             AssertMsgFailed(("Missing RTFILE_O_DENY_*! (continuable assertion)\n"));
    180             fOpen |= RTFILE_O_DENY_NONE;
    181             break;
    182         case RTFILE_O_DENY_NONE:
    183         case RTFILE_O_DENY_READ:
    184         case RTFILE_O_DENY_WRITE:
    185         case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
    186         case RTFILE_O_DENY_NOT_DELETE:
    187         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ:
    188         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE:
    189         case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
    190             break;
    191         default:
    192             AssertMsgFailed(("Invalid deny value: fOpen=%#llx\n", fOpen));
    193             return VERR_INVALID_PARAMETER;
    194     }
    195 
    196     /* done */
    197     *pfOpen = fOpen;
    198     return VINF_SUCCESS;
    199 }
    200 
    201 
    202 /**
    203  * Gets the current file position.
    204  *
    205  * @returns File offset.
    206  * @returns ~0UUL on failure.
    207  * @param   File        File handle.
    208  */
    209 RTR3DECL(uint64_t)  RTFileTell(RTFILE File)
    210 {
    211     /*
    212      * Call the seek api to query the stuff.
    213      */
    214     uint64_t off = 0;
    215     int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off);
    216     if (RT_SUCCESS(rc))
    217         return off;
    218     AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc));
    219     return ~0ULL;
    220 }
    221 
    222 
    223 /**
    224  * Determine the maximum file size.
    225  *
    226  * @returns The max size of the file.
    227  *          -1 on failure, the file position is undefined.
    228  * @param   File        Handle to the file.
    229  * @see     RTFileGetMaxSizeEx.
    230  */
    231 RTR3DECL(RTFOFF) RTFileGetMaxSize(RTFILE File)
    232 {
    233     RTFOFF cbMax;
    234     int rc = RTFileGetMaxSizeEx(File, &cbMax);
    235     return RT_SUCCESS(rc) ? cbMax : -1;
    236 }
    237 
    238 
    239 RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst)
    240 {
    241     return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL);
    242 }
     35#include <iprt/errcore.h>
    24336
    24437
     
    29386}
    29487
    295 
    296 RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
    297 {
    298     /*
    299      * Validate input.
    300      */
    301     AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);
    302     AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);
    303     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    304 
    305     /*
    306      * Save file offset.
    307      */
    308     RTFOFF offSrcSaved;
    309     int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);
    310     if (RT_FAILURE(rc))
    311         return rc;
    312 
    313     /*
    314      * Get the file size.
    315      */
    316     RTFOFF cbSrc;
    317     rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);
    318     if (RT_FAILURE(rc))
    319         return rc;
    320 
    321     /*
    322      * Allocate buffer.
    323      */
    324     size_t      cbBuf;
    325     uint8_t    *pbBufFree = NULL;
    326     uint8_t    *pbBuf;
    327     if (cbSrc < _512K)
    328     {
    329         cbBuf = 8*_1K;
    330         pbBuf = (uint8_t *)alloca(cbBuf);
    331     }
    332     else
    333     {
    334         cbBuf = _128K;
    335         pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);
    336     }
    337     if (pbBuf)
    338     {
    339         /*
    340          * Seek to the start of each file
    341          * and set the size of the destination file.
    342          */
    343         rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);
    344         if (RT_SUCCESS(rc))
    345         {
    346             rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);
    347             if (RT_SUCCESS(rc))
    348                 rc = RTFileSetSize(FileDst, cbSrc);
    349             if (RT_SUCCESS(rc) && pfnProgress)
    350                 rc = pfnProgress(0, pvUser);
    351             if (RT_SUCCESS(rc))
    352             {
    353                 /*
    354                  * Copy loop.
    355                  */
    356                 unsigned    uPercentage = 0;
    357                 RTFOFF      off = 0;
    358                 RTFOFF      cbPercent = cbSrc / 100;
    359                 RTFOFF      offNextPercent = cbPercent;
    360                 while (off < cbSrc)
    361                 {
    362                     /* copy block */
    363                     RTFOFF cbLeft = cbSrc - off;
    364                     size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
    365                     rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);
    366                     if (RT_FAILURE(rc))
    367                         break;
    368                     rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);
    369                     if (RT_FAILURE(rc))
    370                         break;
    371 
    372                     /* advance */
    373                     off += cbBlock;
    374                     if (pfnProgress && offNextPercent < off && uPercentage < 100)
    375                     {
    376                         do
    377                         {
    378                             uPercentage++;
    379                             offNextPercent += cbPercent;
    380                         } while (offNextPercent < off && uPercentage < 100);
    381                         rc = pfnProgress(uPercentage, pvUser);
    382                         if (RT_FAILURE(rc))
    383                             break;
    384                     }
    385                 }
    386 
    387 #if 0
    388                 /*
    389                  * Copy OS specific data (EAs and stuff).
    390                  */
    391                 rtFileCopyOSStuff(FileSrc, FileDst);
    392 #endif
    393 
    394                 /* 100% */
    395                 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
    396                     rc = pfnProgress(100, pvUser);
    397             }
    398         }
    399         RTMemTmpFree(pbBufFree);
    400     }
    401     else
    402         rc = VERR_NO_MEMORY;
    403 
    404     /*
    405      * Restore source position.
    406      */
    407     RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);
    408 
    409     return rc;
    410 }
    411 
    412 
    413 RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2)
    414 {
    415     return RTFileCompareEx(pszFile1, pszFile2, 0 /*fFlags*/, NULL, NULL);
    416 }
    417 
    418 
    419 RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2)
    420 {
    421     return RTFileCompareByHandlesEx(hFile1, hFile2, 0 /*fFlags*/, NULL, NULL);
    422 }
    423 
    424 
    425 RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    426 {
    427     /*
    428      * Validate input.
    429      */
    430     AssertPtrReturn(pszFile1, VERR_INVALID_POINTER);
    431     AssertReturn(*pszFile1, VERR_INVALID_PARAMETER);
    432     AssertPtrReturn(pszFile2, VERR_INVALID_POINTER);
    433     AssertReturn(*pszFile2, VERR_INVALID_PARAMETER);
    434     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    435     AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    436 
    437     /*
    438      * Open the files.
    439      */
    440     RTFILE hFile1;
    441     int rc = RTFileOpen(&hFile1, pszFile1,
    442                         RTFILE_O_READ | RTFILE_O_OPEN
    443                         | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    444     if (RT_SUCCESS(rc))
    445     {
    446         RTFILE hFile2;
    447         rc = RTFileOpen(&hFile2, pszFile2,
    448                         RTFILE_O_READ | RTFILE_O_OPEN
    449                         | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    450         if (RT_SUCCESS(rc))
    451         {
    452             /*
    453              * Call the ByHandles version and let it do the job.
    454              */
    455             rc = RTFileCompareByHandlesEx(hFile1, hFile2, fFlags,  pfnProgress, pvUser);
    456 
    457             /* Clean up */
    458             int rc2 = RTFileClose(hFile2);
    459             AssertRC(rc2);
    460             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    461                 rc = rc2;
    462         }
    463 
    464         int rc2 = RTFileClose(hFile1);
    465         AssertRC(rc2);
    466         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    467             rc = rc2;
    468     }
    469     return rc;
    470 }
    471 
    472 
    473 RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    474 {
    475     /*
    476      * Validate input.
    477      */
    478     AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
    479     AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
    480     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    481     AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    482 
    483     /*
    484      * Compare the file sizes first.
    485      */
    486     uint64_t cbFile1;
    487     int rc = RTFileGetSize(hFile1, &cbFile1);
    488     if (RT_FAILURE(rc))
    489         return rc;
    490 
    491     uint64_t cbFile2;
    492     rc = RTFileGetSize(hFile1, &cbFile2);
    493     if (RT_FAILURE(rc))
    494         return rc;
    495 
    496     if (cbFile1 != cbFile2)
    497         return VERR_NOT_EQUAL;
    498 
    499 
    500     /*
    501      * Allocate buffer.
    502      */
    503     size_t      cbBuf;
    504     uint8_t    *pbBuf1Free = NULL;
    505     uint8_t    *pbBuf1;
    506     uint8_t    *pbBuf2Free = NULL;
    507     uint8_t    *pbBuf2;
    508     if (cbFile1 < _512K)
    509     {
    510         cbBuf  = 8*_1K;
    511         pbBuf1 = (uint8_t *)alloca(cbBuf);
    512         pbBuf2 = (uint8_t *)alloca(cbBuf);
    513     }
    514     else
    515     {
    516         cbBuf = _128K;
    517         pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
    518         pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
    519     }
    520     if (pbBuf1 && pbBuf2)
    521     {
    522         /*
    523          * Seek to the start of each file
    524          * and set the size of the destination file.
    525          */
    526         rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL);
    527         if (RT_SUCCESS(rc))
    528         {
    529             rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL);
    530             if (RT_SUCCESS(rc) && pfnProgress)
    531                 rc = pfnProgress(0, pvUser);
    532             if (RT_SUCCESS(rc))
    533             {
    534                 /*
    535                  * Compare loop.
    536                  */
    537                 unsigned    uPercentage    = 0;
    538                 RTFOFF      off            = 0;
    539                 RTFOFF      cbPercent      = cbFile1 / 100;
    540                 RTFOFF      offNextPercent = cbPercent;
    541                 while (off < (RTFOFF)cbFile1)
    542                 {
    543                     /* read the blocks */
    544                     RTFOFF cbLeft = cbFile1 - off;
    545                     size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
    546                     rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL);
    547                     if (RT_FAILURE(rc))
    548                         break;
    549                     rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL);
    550                     if (RT_FAILURE(rc))
    551                         break;
    552 
    553                     /* compare */
    554                     if (memcmp(pbBuf1, pbBuf2, cbBlock))
    555                     {
    556                         rc = VERR_NOT_EQUAL;
    557                         break;
    558                     }
    559 
    560                     /* advance */
    561                     off += cbBlock;
    562                     if (pfnProgress && offNextPercent < off)
    563                     {
    564                         while (offNextPercent < off)
    565                         {
    566                             uPercentage++;
    567                             offNextPercent += cbPercent;
    568                         }
    569                         rc = pfnProgress(uPercentage, pvUser);
    570                         if (RT_FAILURE(rc))
    571                             break;
    572                     }
    573                 }
    574 
    575 #if 0
    576                 /*
    577                  * Compare OS specific data (EAs and stuff).
    578                  */
    579                 if (RT_SUCCESS(rc))
    580                     rc = rtFileCompareOSStuff(hFile1, hFile2);
    581 #endif
    582 
    583                 /* 100% */
    584                 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
    585                     rc = pfnProgress(100, pvUser);
    586             }
    587         }
    588     }
    589     else
    590         rc = VERR_NO_MEMORY;
    591     RTMemTmpFree(pbBuf2Free);
    592     RTMemTmpFree(pbBuf1Free);
    593 
    594     return rc;
    595 }
    596 
  • trunk/src/VBox/Runtime/r3/fileio.cpp

    r77209 r77825  
    240240{
    241241    return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL);
    242 }
    243 
    244 
    245 RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    246 {
    247     /*
    248      * Validate input.
    249      */
    250     AssertMsgReturn(VALID_PTR(pszSrc), ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
    251     AssertMsgReturn(*pszSrc, ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);
    252     AssertMsgReturn(VALID_PTR(pszDst), ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
    253     AssertMsgReturn(*pszDst, ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);
    254     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    255     AssertMsgReturn(!(fFlags & ~RTFILECOPY_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    256 
    257     /*
    258      * Open the files.
    259      */
    260     RTFILE FileSrc;
    261     int rc = RTFileOpen(&FileSrc, pszSrc,
    262                         RTFILE_O_READ | RTFILE_O_OPEN
    263                         | (fFlags & RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    264     if (RT_SUCCESS(rc))
    265     {
    266         RTFILE FileDst;
    267         rc = RTFileOpen(&FileDst, pszDst,
    268                         RTFILE_O_WRITE | RTFILE_O_CREATE
    269                         | (fFlags & RTFILECOPY_FLAGS_NO_DST_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
    270         if (RT_SUCCESS(rc))
    271         {
    272             /*
    273              * Call the ByHandles version and let it do the job.
    274              */
    275             rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser);
    276 
    277             /*
    278              * Close the files regardless of the result.
    279              * Don't bother cleaning up or anything like that.
    280              */
    281             int rc2 = RTFileClose(FileDst);
    282             AssertRC(rc2);
    283             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    284                 rc = rc2;
    285         }
    286 
    287         int rc2 = RTFileClose(FileSrc);
    288         AssertRC(rc2);
    289         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    290             rc = rc2;
    291     }
    292     return rc;
    293 }
    294 
    295 
    296 RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
    297 {
    298     /*
    299      * Validate input.
    300      */
    301     AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);
    302     AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);
    303     AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    304 
    305     /*
    306      * Save file offset.
    307      */
    308     RTFOFF offSrcSaved;
    309     int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);
    310     if (RT_FAILURE(rc))
    311         return rc;
    312 
    313     /*
    314      * Get the file size.
    315      */
    316     RTFOFF cbSrc;
    317     rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);
    318     if (RT_FAILURE(rc))
    319         return rc;
    320 
    321     /*
    322      * Allocate buffer.
    323      */
    324     size_t      cbBuf;
    325     uint8_t    *pbBufFree = NULL;
    326     uint8_t    *pbBuf;
    327     if (cbSrc < _512K)
    328     {
    329         cbBuf = 8*_1K;
    330         pbBuf = (uint8_t *)alloca(cbBuf);
    331     }
    332     else
    333     {
    334         cbBuf = _128K;
    335         pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);
    336     }
    337     if (pbBuf)
    338     {
    339         /*
    340          * Seek to the start of each file
    341          * and set the size of the destination file.
    342          */
    343         rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);
    344         if (RT_SUCCESS(rc))
    345         {
    346             rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);
    347             if (RT_SUCCESS(rc))
    348                 rc = RTFileSetSize(FileDst, cbSrc);
    349             if (RT_SUCCESS(rc) && pfnProgress)
    350                 rc = pfnProgress(0, pvUser);
    351             if (RT_SUCCESS(rc))
    352             {
    353                 /*
    354                  * Copy loop.
    355                  */
    356                 unsigned    uPercentage = 0;
    357                 RTFOFF      off = 0;
    358                 RTFOFF      cbPercent = cbSrc / 100;
    359                 RTFOFF      offNextPercent = cbPercent;
    360                 while (off < cbSrc)
    361                 {
    362                     /* copy block */
    363                     RTFOFF cbLeft = cbSrc - off;
    364                     size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
    365                     rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);
    366                     if (RT_FAILURE(rc))
    367                         break;
    368                     rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);
    369                     if (RT_FAILURE(rc))
    370                         break;
    371 
    372                     /* advance */
    373                     off += cbBlock;
    374                     if (pfnProgress && offNextPercent < off && uPercentage < 100)
    375                     {
    376                         do
    377                         {
    378                             uPercentage++;
    379                             offNextPercent += cbPercent;
    380                         } while (offNextPercent < off && uPercentage < 100);
    381                         rc = pfnProgress(uPercentage, pvUser);
    382                         if (RT_FAILURE(rc))
    383                             break;
    384                     }
    385                 }
    386 
    387 #if 0
    388                 /*
    389                  * Copy OS specific data (EAs and stuff).
    390                  */
    391                 rtFileCopyOSStuff(FileSrc, FileDst);
    392 #endif
    393 
    394                 /* 100% */
    395                 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
    396                     rc = pfnProgress(100, pvUser);
    397             }
    398         }
    399         RTMemTmpFree(pbBufFree);
    400     }
    401     else
    402         rc = VERR_NO_MEMORY;
    403 
    404     /*
    405      * Restore source position.
    406      */
    407     RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);
    408 
    409     return rc;
    410242}
    411243
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette