VirtualBox

Ignore:
Timestamp:
Mar 21, 2019 12:33:42 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129505
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.

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