VirtualBox

Changeset 49033 in vbox


Ignore:
Timestamp:
Oct 10, 2013 4:43:04 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
89809
Message:

IPRT: Added RTFileCompare* methods a la RTFileCopy*.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/file.h

    r48820 r49033  
    512512 * Copies a file.
    513513 *
    514  * @returns VERR_ALREADY_EXISTS if the destination file exists.
    515  * @returns VBox Status code.
     514 * @returns IPRT status code
     515 * @retval VERR_ALREADY_EXISTS if the destination file exists.
    516516 *
    517517 * @param   pszSrc      The path to the source file.
     
    524524 * Copies a file given the handles to both files.
    525525 *
    526  * @returns VBox Status code.
     526 * @returns IPRT status code
    527527 *
    528528 * @param   FileSrc     The source file. The file position is unaltered.
     
    548548 * Copies a file.
    549549 *
    550  * @returns VERR_ALREADY_EXISTS if the destination file exists.
    551  * @returns VBox Status code.
     550 * @returns IPRT status code
     551 * @retval  VERR_ALREADY_EXISTS if the destination file exists.
    552552 *
    553553 * @param   pszSrc      The path to the source file.
     
    574574 */
    575575RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser);
     576
     577
     578/**
     579 * Compares two file given the paths to both files.
     580 *
     581 * @returns IPRT status code.
     582 * @retval  VINF_SUCCESS if equal.
     583 * @retval  VERR_NOT_EQUAL if not equal.
     584 *
     585 * @param   pszFile1    The path to the first file.
     586 * @param   pszFile2    The path to the second file.
     587 */
     588RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2);
     589
     590/**
     591 * Compares two file given the handles to both files.
     592 *
     593 * @returns IPRT status code.
     594 * @retval  VINF_SUCCESS if equal.
     595 * @retval  VERR_NOT_EQUAL if not equal.
     596 *
     597 * @param   hFile1      The first file.  Undefined return position.
     598 * @param   hFile2      The second file.  Undefined return position.
     599 */
     600RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2);
     601
     602/** Flags for RTFileCompareEx().
     603 * @{ */
     604/** Do not use RTFILE_O_DENY_WRITE on the first file. */
     605#define RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1  RT_BIT(0)
     606/** Do not use RTFILE_O_DENY_WRITE on the second file. */
     607#define RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2  RT_BIT(1)
     608/** Do not use RTFILE_O_DENY_WRITE on either of the two files. */
     609#define RTFILECOMP_FLAGS_NO_DENY_WRITE      ( RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 | RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 )
     610/** */
     611#define RTFILECOMP_FLAGS_MASK               UINT32_C(0x00000003)
     612/** @} */
     613
     614/**
     615 * Compares two files, extended version with progress callback.
     616 *
     617 * @returns IPRT status code.
     618 * @retval  VINF_SUCCESS if equal.
     619 * @retval  VERR_NOT_EQUAL if not equal.
     620 *
     621 * @param   pszFile1    The path to the source file.
     622 * @param   pszFile2    The path to the destination file. This file will be
     623 *                      created.
     624 * @param   fFlags      Flags, any of the RTFILECOMP_FLAGS_ \#defines.
     625 * @param   pfnProgress Pointer to callback function for reporting progress.
     626 * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
     627 */
     628RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);
     629
     630/**
     631 * Compares two files given their handles, extended version with progress
     632 * callback.
     633 *
     634 * @returns IPRT status code.
     635 * @retval  VINF_SUCCESS if equal.
     636 * @retval  VERR_NOT_EQUAL if not equal.
     637 *
     638 * @param   hFile1      The first file.  Undefined return position.
     639 * @param   hFile2      The second file.  Undefined return position.
     640 *
     641 * @param   fFlags      Flags, any of the RTFILECOMP_FLAGS_ \#defines, flags
     642 *                      related to opening of the files will be ignored.
     643 * @param   pfnProgress Pointer to callback function for reporting progress.
     644 * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
     645 */
     646RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);
    576647
    577648/**
  • trunk/src/VBox/Runtime/r3/fileio.cpp

    r48935 r49033  
    2828*   Header Files                                                               *
    2929*******************************************************************************/
     30#include "internal/iprt.h"
    3031#include <iprt/file.h>
    31 #include <iprt/alloc.h>
     32
     33#include <iprt/mem.h>
    3234#include <iprt/assert.h>
    3335#include <iprt/alloca.h>
     36#include <iprt/string.h>
    3437#include <iprt/err.h>
    3538#include "internal/file.h"
     
    352355
    353356
    354 /**
    355  * Copies a file given the handles to both files.
    356  *
    357  * @returns VBox Status code.
    358  *
    359  * @param   FileSrc     The source file. The file position is unaltered.
    360  * @param   FileDst     The destination file.
    361  *                      On successful returns the file position is at the end of the file.
    362  *                      On failures the file position and size is undefined.
    363  */
    364357RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst)
    365358{
     
    368361
    369362
    370 /**
    371  * Copies a file.
    372  *
    373  * @returns VERR_ALREADY_EXISTS if the destination file exists.
    374  * @returns VBox Status code.
    375  *
    376  * @param   pszSrc      The path to the source file.
    377  * @param   pszDst      The path to the destination file.
    378  *                      This file will be created.
    379  * @param   fFlags      Flags, any of the RTFILECOPY_FLAGS_ \#defines.
    380  * @param   pfnProgress Pointer to callback function for reporting progress.
    381  * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
    382  */
    383363RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
    384364{
     
    432412
    433413
    434 /**
    435  * Copies a file given the handles to both files and
    436  * provide progress callbacks.
    437  *
    438  * @returns VBox Status code.
    439  *
    440  * @param   FileSrc     The source file. The file position is unaltered.
    441  * @param   FileDst     The destination file.
    442  *                      On successful returns the file position is at the end of the file.
    443  *                      On failures the file position and size is undefined.
    444  * @param   pfnProgress Pointer to callback function for reporting progress.
    445  * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
    446  */
    447414RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)
    448415{
     
    561528}
    562529
     530
     531RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2)
     532{
     533    return RTFileCompareEx(pszFile1, pszFile2, 0 /*fFlags*/, NULL, NULL);
     534}
     535
     536
     537RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2)
     538{
     539    return RTFileCompareByHandlesEx(hFile1, hFile2, 0 /*fFlags*/, NULL, NULL);
     540}
     541
     542
     543RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
     544{
     545    /*
     546     * Validate input.
     547     */
     548    AssertPtrReturn(pszFile1, VERR_INVALID_POINTER);
     549    AssertReturn(*pszFile1, VERR_INVALID_PARAMETER);
     550    AssertPtrReturn(pszFile2, VERR_INVALID_POINTER);
     551    AssertReturn(*pszFile2, VERR_INVALID_PARAMETER);
     552    AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
     553    AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     554
     555    /*
     556     * Open the files.
     557     */
     558    RTFILE hFile1;
     559    int rc = RTFileOpen(&hFile1, pszFile1,
     560                        RTFILE_O_READ | RTFILE_O_OPEN
     561                        | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
     562    if (RT_SUCCESS(rc))
     563    {
     564        RTFILE hFile2;
     565        rc = RTFileOpen(&hFile2, pszFile2,
     566                        RTFILE_O_WRITE | RTFILE_O_CREATE
     567                        | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));
     568        if (RT_SUCCESS(rc))
     569        {
     570            /*
     571             * Call the ByHandles version and let it do the job.
     572             */
     573            rc = RTFileCompareByHandlesEx(hFile1, hFile2, fFlags,  pfnProgress, pvUser);
     574
     575            /* Clean up */
     576            int rc2 = RTFileClose(hFile2);
     577            AssertRC(rc2);
     578            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     579                rc = rc2;
     580        }
     581
     582        int rc2 = RTFileClose(hFile2);
     583        AssertRC(rc2);
     584        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     585            rc = rc2;
     586    }
     587    return rc;
     588}
     589
     590
     591RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)
     592{
     593    /*
     594     * Validate input.
     595     */
     596    AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
     597    AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);
     598    AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);
     599    AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     600
     601    /*
     602     * Compare the file sizes first.
     603     */
     604    uint64_t cbFile1;
     605    int rc = RTFileGetSize(hFile1, &cbFile1);
     606    if (RT_FAILURE(rc))
     607        return rc;
     608
     609    uint64_t cbFile2;
     610    rc = RTFileGetSize(hFile1, &cbFile2);
     611    if (RT_FAILURE(rc))
     612        return rc;
     613
     614    if (cbFile1 != cbFile2)
     615        return VERR_NOT_EQUAL;
     616
     617
     618    /*
     619     * Allocate buffer.
     620     */
     621    size_t      cbBuf;
     622    uint8_t    *pbBuf1Free = NULL;
     623    uint8_t    *pbBuf1;
     624    uint8_t    *pbBuf2Free = NULL;
     625    uint8_t    *pbBuf2;
     626    if (cbFile1 < _512K)
     627    {
     628        cbBuf  = 8*_1K;
     629        pbBuf1 = (uint8_t *)alloca(cbBuf);
     630        pbBuf2 = (uint8_t *)alloca(cbBuf);
     631    }
     632    else
     633    {
     634        cbBuf = _128K;
     635        pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
     636        pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf);
     637    }
     638    if (pbBuf1 && pbBuf2)
     639    {
     640        /*
     641         * Seek to the start of each file
     642         * and set the size of the destination file.
     643         */
     644        rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL);
     645        if (RT_SUCCESS(rc))
     646        {
     647            rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL);
     648            if (RT_SUCCESS(rc) && pfnProgress)
     649                rc = pfnProgress(0, pvUser);
     650            if (RT_SUCCESS(rc))
     651            {
     652                /*
     653                 * Compare loop.
     654                 */
     655                unsigned    uPercentage    = 0;
     656                RTFOFF      off            = 0;
     657                RTFOFF      cbPercent      = cbFile1 / 100;
     658                RTFOFF      offNextPercent = cbPercent;
     659                while (off < (RTFOFF)cbFile1)
     660                {
     661                    /* read the blocks */
     662                    RTFOFF cbLeft = cbFile1 - off;
     663                    size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;
     664                    rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL);
     665                    if (RT_FAILURE(rc))
     666                        break;
     667                    rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL);
     668                    if (RT_FAILURE(rc))
     669                        break;
     670
     671                    /* compare */
     672                    if (memcmp(pbBuf1, pbBuf2, cbBlock))
     673                    {
     674                        rc = VERR_NOT_EQUAL;
     675                        break;
     676                    }
     677
     678                    /* advance */
     679                    off += cbBlock;
     680                    if (pfnProgress && offNextPercent < off)
     681                    {
     682                        while (offNextPercent < off)
     683                        {
     684                            uPercentage++;
     685                            offNextPercent += cbPercent;
     686                        }
     687                        rc = pfnProgress(uPercentage, pvUser);
     688                        if (RT_FAILURE(rc))
     689                            break;
     690                    }
     691                }
     692
     693#if 0
     694                /*
     695                 * Compare OS specific data (EAs and stuff).
     696                 */
     697                if (RT_SUCCESS(rc))
     698                    rc = rtFileCompareOSStuff(hFile1, hFile2);
     699#endif
     700
     701                /* 100% */
     702                if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))
     703                    rc = pfnProgress(100, pvUser);
     704            }
     705        }
     706    }
     707    else
     708        rc = VERR_NO_MEMORY;
     709    RTMemTmpFree(pbBuf2Free);
     710    RTMemTmpFree(pbBuf1Free);
     711
     712    return rc;
     713}
     714
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