VirtualBox

Changeset 77830 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 21, 2019 6:07:40 PM (6 years ago)
Author:
vboxsync
Message:

IPRT: Reimplemented RTFileCopyByHandlesEx against RTFileCopyPartEx, adding RTFileCopyAttributes for copying attributes. bugref:9172

Location:
trunk/src/VBox/Runtime
Files:
1 added
2 edited
2 moved

Legend:

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

    r77825 r77830  
    666666        generic/RTEnvDupEx-generic.cpp \
    667667        generic/RTFileCopy-generic.cpp \
     668        generic/RTFileCopyAttributes-generic.cpp \
    668669        generic/RTFileCopyEx-generic.cpp \
    669670        generic/RTFileCopyByHandlesEx-generic.cpp \
    670         generic/RTFileCopyRange-generic.cpp \
    671         generic/RTFileCopyRangeEx-generic.cpp \
     671        generic/RTFileCopyPart-generic.cpp \
     672        generic/RTFileCopyPartEx-generic.cpp \
    672673        generic/RTFileQuerySize-generic.cpp \
    673674        generic/RTFileReadAll-generic.cpp \
     
    17901791        generic/RTEnvDupEx-generic.cpp \
    17911792        generic/RTFileCopy-generic.cpp \
     1793        generic/RTFileCopyAttributes-generic.cpp \
    17921794        generic/RTFileCopyEx-generic.cpp \
    17931795        generic/RTFileCopyByHandlesEx-generic.cpp \
     1796        generic/RTFileCopyPartEx-generic.cpp \
    17941797        generic/RTFileQuerySize-generic.cpp \
    17951798        generic/RTFileReadAll-generic.cpp \
  • trunk/src/VBox/Runtime/generic/RTFileCopyByHandlesEx-generic.cpp

    r77825 r77830  
    3838
    3939
    40 RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
     40RTDECL(int) RTFileCopyByHandlesEx(RTFILE hFileSrc, RTFILE hFileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
    4141{
    4242    /*
    4343     * Validate input.
    4444     */
    45     AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);
    46     AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);
     45    AssertMsgReturn(RTFileIsValid(hFileSrc), ("hFileSrc=%RTfile\n", hFileSrc), VERR_INVALID_PARAMETER);
     46    AssertMsgReturn(RTFileIsValid(hFileDst), ("hFileDst=%RTfile\n", hFileDst), VERR_INVALID_PARAMETER);
    4747    AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
    4848
     
    5050     * Save file offset.
    5151     */
    52     RTFOFF offSrcSaved;
    53     int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);
     52    uint64_t offSrcSaved;
     53    int rc = RTFileSeek(hFileSrc, 0, RTFILE_SEEK_CURRENT, &offSrcSaved);
    5454    if (RT_FAILURE(rc))
    5555        return rc;
    5656
    5757    /*
    58      * Get the file size.
     58     * Get the file size and figure out how much we'll copy at a time.
    5959     */
    60     RTFOFF cbSrc;
    61     rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);
     60    uint64_t cbSrc;
     61    rc = RTFileGetSize(hFileSrc, &cbSrc);
    6262    if (RT_FAILURE(rc))
    6363        return rc;
    6464
     65    uint64_t cbChunk = cbSrc;
     66    if (pfnProgress && cbSrc > _1M)
     67    {
     68        cbChunk /= 100;
     69        if (cbChunk > _64M)
     70            cbChunk = RT_ALIGN_64(cbChunk, _2M);
     71        else
     72            cbChunk = RT_ALIGN_64(cbChunk, _128K);
     73    }
     74
    6575    /*
    66      * Allocate buffer.
     76     * Prepare buffers.
    6777     */
    68     size_t      cbBuf;
    69     uint8_t    *pbBufFree = NULL;
    70     uint8_t    *pbBuf;
    71     if (cbSrc < _512K)
    72     {
    73         cbBuf = 8*_1K;
    74         pbBuf = (uint8_t *)alloca(cbBuf);
    75     }
    76     else
    77     {
    78         cbBuf = _128K;
    79         pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);
    80     }
    81     if (pbBuf)
     78    RTFILECOPYPARTBUFSTATE BufState;
     79    rc = RTFileCopyPartPrep(&BufState, cbChunk);
     80    if (RT_SUCCESS(rc))
    8281    {
    8382        /*
    84          * Seek to the start of each file
    85          * and set the size of the destination file.
     83         * Prepare the destination file.
    8684         */
    87         rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);
     85        uint64_t cbDst;
     86        rc = RTFileGetSize(hFileDst, &cbDst);
     87        if (RT_SUCCESS(rc) && cbDst > cbSrc)
     88            rc = RTFileSetSize(hFileDst, cbSrc);
     89        if (RT_SUCCESS(rc) && cbDst < cbSrc)
     90        {
     91            rc = RTFileSetAllocationSize(hFileDst, cbSrc, RTFILE_ALLOC_SIZE_F_DEFAULT);
     92            if (rc == VERR_NOT_SUPPORTED)
     93                rc = RTFileSetSize(hFileDst, cbSrc);
     94        }
    8895        if (RT_SUCCESS(rc))
    8996        {
    90             rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);
    91             if (RT_SUCCESS(rc))
    92                 rc = RTFileSetSize(FileDst, cbSrc);
    93             if (RT_SUCCESS(rc) && pfnProgress)
    94                 rc = pfnProgress(0, pvUser);
    95             if (RT_SUCCESS(rc))
     97            /*
     98             * Copy loop that works till we reach EOF.
     99             */
     100            RTFOFF      off            = 0;
     101            RTFOFF      cbPercent      = cbSrc / 100;
     102            RTFOFF      offNextPercent = pfnProgress ? cbPercent : RTFOFF_MAX;
     103            unsigned    uPercentage    = pfnProgress ? 0         : 100;
     104            for (;;)
    96105            {
    97106                /*
    98                  * Copy loop.
     107                 * Copy a block.
    99108                 */
    100                 unsigned    uPercentage = 0;
    101                 RTFOFF      off = 0;
    102                 RTFOFF      cbPercent = cbSrc / 100;
    103                 RTFOFF      offNextPercent = cbPercent;
    104                 while (off < cbSrc)
     109                uint64_t cbCopied = 0;
     110                rc = RTFileCopyPartEx(hFileSrc, off, hFileDst, off, cbChunk, 0 /*fFlags*/, &BufState, &cbCopied);
     111                if (RT_FAILURE(rc))
     112                    break;
     113                if (cbCopied == 0)
    105114                {
    106                     /* copy block */
    107                     RTFOFF cbLeft = cbSrc - off;
    108                     size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
    109                     rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);
     115                    /*
     116                     * We reached the EOF.  Complete the copy operation.
     117                     */
     118                    rc = RTFileSetSize(hFileDst, off);
     119                    if (RT_SUCCESS(rc))
     120                        rc = RTFileCopyAttributes(hFileSrc, hFileDst, 0);
     121                    break;
     122                }
     123
     124                /*
     125                 * Advance and work the progress callback.
     126                 */
     127                off += cbCopied;
     128                if (   off >= offNextPercent
     129                    && pfnProgress
     130                    && uPercentage < 99)
     131                {
     132                    do
     133                    {
     134                        uPercentage++;
     135                        offNextPercent += cbPercent;
     136                    } while (   offNextPercent <= off
     137                             && uPercentage < 99);
     138                    rc = pfnProgress(uPercentage, pvUser);
    110139                    if (RT_FAILURE(rc))
    111140                        break;
    112                     rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);
    113                     if (RT_FAILURE(rc))
    114                         break;
    115 
    116                     /* advance */
    117                     off += cbBlock;
    118                     if (pfnProgress && offNextPercent < off && uPercentage < 100)
    119                     {
    120                         do
    121                         {
    122                             uPercentage++;
    123                             offNextPercent += cbPercent;
    124                         } while (offNextPercent < off && uPercentage < 100);
    125                         rc = pfnProgress(uPercentage, pvUser);
    126                         if (RT_FAILURE(rc))
    127                             break;
    128                     }
    129141                }
    130 
    131 #if 0
    132                 /*
    133                  * Copy OS specific data (EAs and stuff).
    134                  */
    135                 rtFileCopyOSStuff(FileSrc, FileDst);
    136 #endif
    137 
    138                 /* 100% */
    139                 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
    140                     rc = pfnProgress(100, pvUser);
    141142            }
    142143        }
    143         RTMemTmpFree(pbBufFree);
     144
     145        RTFileCopyPartCleanup(&BufState);
     146
     147        /*
     148         * 100%.
     149         */
     150        if (   pfnProgress
     151            && RT_SUCCESS(rc))
     152            rc = pfnProgress(100, pvUser);
    144153    }
    145     else
    146         rc = VERR_NO_MEMORY;
    147154
    148155    /*
    149156     * Restore source position.
    150157     */
    151     RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);
    152 
     158    RTFileSeek(hFileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);
    153159    return rc;
    154160}
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