VirtualBox

Changeset 21810 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jul 27, 2009 1:01:15 PM (15 years ago)
Author:
vboxsync
Message:

IPRT: r=bird: RTZip - dunno if anything works after my changes because there isn't any testcase. Please add one.

  • Fixed numerous allocation related issues (missing checks for success and leaks).
  • RTTarList wouldn't set *pcFiles and *ppapszFiles if no files were found.
  • Don't pass pcbRead and pcbWritten to RTFileRead/Write if it is unacceptable to do partial reads and writes.
  • for (;;) instead of do while (0).
  • Always specify all three flag categories for RTFileOpen calls!
  • Adding > 4GB files to a tar file on 32-bit would fill up the disk.
  • Missing rc check in rtTarCheckheader when converting the checksum.
  • Don't override errors with VERR_FILE_IO_ERROR, VERR_FILE_NOT_FOUND or in one case VINF_SUCCESS.
  • Use RT_ZERO instead of memset.
  • Use Assert*Return for input validation. The if (bad) {AssertMsgFailed(); return failure; } style checking found around IPRT is from before the Assert*Return macro was added.
  • Added todos for inefficient 512 bytes at a time copying.
  • Added todos for interface renaming to conform with IPRT conventions.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/tar.cpp

    r21784 r21810  
    2929 */
    3030
    31 #include "iprt/tar.h"
    32 
     31
     32/*******************************************************************************
     33*   Header Files                                                               *
     34*******************************************************************************/
     35#include "internal/iprt.h"
     36#include <iprt/tar.h>
     37
     38#include <iprt/asm.h>
    3339#include <iprt/assert.h>
     40#include <iprt/err.h>
    3441#include <iprt/file.h>
     42#include <iprt/mem.h>
    3543#include <iprt/path.h>
    36 #include <iprt/err.h>
    37 #include <iprt/mem.h>
    38 #include <iprt/asm.h>
    3944#include <iprt/string.h>
     45
    4046
    4147/*******************************************************************************
     
    4349*******************************************************************************/
    4450
    45 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */
    46 #define LF_NORMAL    '0'  /* Normal disk file */
    47 #define LF_LINK      '1'  /* Link to previously dumped file */
    48 #define LF_SYMLINK   '2'  /* Symbolic link */
    49 #define LF_CHR       '3'  /* Character special file */
    50 #define LF_BLK       '4'  /* Block special file */
    51 #define LF_DIR       '5'  /* Directory */
    52 #define LF_FIFO      '6'  /* FIFO special file */
    53 #define LF_CONTIG    '7'  /* Contiguous file */
     51/** @name RTTARRECORD::h::linkflag
     52 * @{  */
     53#define LF_OLDNORMAL '\0' /**< Normal disk file, Unix compatible */
     54#define LF_NORMAL    '0'  /**< Normal disk file */
     55#define LF_LINK      '1'  /**< Link to previously dumped file */
     56#define LF_SYMLINK   '2'  /**< Symbolic link */
     57#define LF_CHR       '3'  /**< Character special file */
     58#define LF_BLK       '4'  /**< Block special file */
     59#define LF_DIR       '5'  /**< Directory */
     60#define LF_FIFO      '6'  /**< FIFO special file */
     61#define LF_CONTIG    '7'  /**< Contiguous file */
     62/** @} */
    5463
    5564typedef union RTTARRECORD
     
    7584} RTTARRECORD;
    7685typedef RTTARRECORD *PRTTARRECORD;
    77 
     86AssertCompileSize(RTTARRECORD, 512);
     87AssertCompileMemberOffset(RTTARRECORD, h.size, 100+8*3);
     88
     89#if 0 /* not currently used */
    7890typedef struct RTTARFILELIST
    7991{
     
    8294} RTTARFILELIST;
    8395typedef RTTARFILELIST *PRTTARFILELIST;
     96#endif
     97
    8498
    8599/*******************************************************************************
    86 *   Private RTTar helper                                                       *
     100*   Internal Functions                                                         *
    87101*******************************************************************************/
    88102
     
    91105    uint32_t check = 0;
    92106    uint32_t zero = 0;
    93     for (size_t i=0; i < sizeof(RTTARRECORD); ++i)
     107    for (size_t i = 0; i < sizeof(RTTARRECORD); ++i)
    94108    {
    95109        /* Calculate the sum of every byte from the header. The checksum field
    96110         * itself is counted as all blanks. */
    97         if (i < RT_UOFFSETOF(RTTARRECORD, h.chksum) ||
    98             i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))
     111        if (   i <  RT_UOFFSETOF(RTTARRECORD, h.chksum)
     112            || i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))
    99113            check += pRecord->d[i];
    100114        else
     
    123137    uint32_t sum;
    124138    rc = RTStrToUInt32Full(pRecord->h.chksum, 8, &sum);
    125     if (sum == check)
     139    if (RT_SUCCESS(rc) && sum == check)
    126140        return VINF_SUCCESS;
    127     else
    128         return VERR_TAR_CHKSUM_MISMATCH;
    129 }
    130 
    131 static int rtTarCopyFileFrom(RTFILE hFile, const char* pszTargetName, PRTTARRECORD pRecord)
     141    return VERR_TAR_CHKSUM_MISMATCH;
     142}
     143
     144static int rtTarCopyFileFrom(RTFILE hFile, const char *pszTargetName, PRTTARRECORD pRecord)
    132145{
    133146    RTFILE hNewFile;
    134147    /* Open the target file */
    135     int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE);
    136     if (RT_FAILURE(rc))
    137         return rc;
     148    int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
     149    if (RT_FAILURE(rc))
     150        return rc;
     151
     152/**@todo r=bird: Use a bigger buffer here, see comment in rtTarCopyFileTo. */
    138153
    139154    uint64_t cbToCopy = RTStrToUInt64(pRecord->h.size);
    140     size_t cbRead = 0;
    141     size_t cbWritten = 0;
    142155    size_t cbAllWritten = 0;
    143156    RTTARRECORD record;
     
    146159     * a 512 byte boundary, regardless if the file copied is 512 byte size
    147160     * aligned. */
    148     do
     161    for (;;)
    149162    {
    150163        /* Finished already? */
     
    152165            break;
    153166        /* Read one block */
    154         rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);
    155         if (RT_FAILURE(rc) ||
    156             cbRead != sizeof(record))
    157         {
    158             rc = VERR_FILE_IO_ERROR;
    159             break;
    160         }
     167        rc = RTFileRead(hFile, &record, sizeof(record), NULL);
     168        if (RT_FAILURE(rc))
     169            break;
    161170        size_t cbToWrite = sizeof(record);
    162171        /* Check for the last block which has not to be 512 bytes in size. */
     
    164173            cbToWrite = cbToCopy - cbAllWritten;
    165174        /* Write the block */
    166         rc = RTFileWrite(hNewFile, &record, cbToWrite, &cbWritten);
    167         if (RT_FAILURE(rc) ||
    168             cbWritten != cbToWrite)
    169         {
    170             rc = VERR_FILE_IO_ERROR;
    171             break;
    172         }
     175        rc = RTFileWrite(hNewFile, &record, cbToWrite, NULL);
     176        if (RT_FAILURE(rc))
     177            break;
    173178        /* Count how many bytes are written already */
    174         cbAllWritten += cbWritten;
    175     }
    176     while(1);
     179        cbAllWritten += cbToWrite;
     180    }
    177181
    178182    /* Now set all file attributes */
     
    188192        }
    189193    }
     194    /* Make sure the called doesn't mix trunacted tar files with the official
     195     * end indicated by rtTarCalcChkSum. */
     196    else if (rc == VERR_EOF)
     197        rc = VERR_FILE_IO_ERROR;
    190198
    191199    RTFileClose(hNewFile);
     
    198206}
    199207
    200 static int rtTarCopyFileTo(RTFILE hFile, const char* pszSrcName)
     208static int rtTarCopyFileTo(RTFILE hFile, const char *pszSrcName)
    201209{
    202210    RTFILE hOldFile;
    203211    /* Open the source file */
    204     int rc = RTFileOpen(&hOldFile, pszSrcName, RTFILE_O_READ);
     212    int rc = RTFileOpen(&hOldFile, pszSrcName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
    205213    if (RT_FAILURE(rc))
    206214        return rc;
     
    232240    /* Fill the header record */
    233241    RTTARRECORD record;
    234     ASMMemFill32(&record, sizeof(record), 0); /* Initialize with zeros */
     242    RT_ZERO(record);
    235243    RTStrPrintf(record.h.name,  sizeof(record.h.name),  "%s",     RTPathFilename(pszSrcName));
    236244    RTStrPrintf(record.h.mode,  sizeof(record.h.mode),  "%0.7o",  fmode);
     
    252260    if (RT_SUCCESS(rc))
    253261    {
    254         size_t cbToRead = 0;
    255         size_t cbWritten = 0;
    256         size_t cbAllWritten = 0;
     262/** @todo r=bird: using a 64KB buffer here instead of 0.5KB would probably be
     263 *        a good thing. */
     264        uint64_t cbAllWritten = 0;
    257265        /* Copy the content from pszSrcName over to hFile. This is done block
    258266         * wise in 512 byte steps. After this copying is finished hFile will be
    259267         * on a 512 byte boundary, regardless if the file copied is 512 byte
    260268         * size aligned. */
    261         do
     269        for (;;)
    262270        {
    263271            if (cbAllWritten >= cbSize)
    264272                break;
    265             cbToRead = sizeof(record);
     273            size_t cbToRead = sizeof(record);
    266274            /* Last record? */
    267275            if (cbAllWritten + cbToRead > cbSize)
    268276            {
    269277                /* Initialize with zeros */
    270                 ASMMemFill32(&record, sizeof(record), 0);
     278                RT_ZERO(record);
    271279                cbToRead = cbSize - cbAllWritten;
    272280            }
     
    276284                break;
    277285            /* Write one block */
    278             rc = RTFileWrite(hFile, &record, sizeof(record), &cbWritten);
     286            rc = RTFileWrite(hFile, &record, sizeof(record), NULL);
    279287            if (RT_FAILURE(rc))
    280288                break;
    281289            /* Count how many bytes are written already */
    282             cbAllWritten += cbWritten;
     290            cbAllWritten += sizeof(record);
    283291        }
    284         while(1);
     292
     293        /* Make sure the called doesn't mix trunacted tar files with the official
     294         * end indicated by rtTarCalcChkSum. */
     295        if (rc == VERR_EOF)
     296            rc == VERR_FILE_IO_ERROR;
    285297    }
    286298    RTFileClose(hOldFile);
     
    292304{
    293305    int rc = VINF_SUCCESS;
    294     uint64_t offAct;
    295306    /* Seek over the data parts (512 bytes aligned) */
    296307    int64_t offSeek = RT_ALIGN(RTStrToInt64(pRecord->h.size), sizeof(RTTARRECORD));
    297308    if (offSeek > 0)
    298         rc = RTFileSeek(hFile, offSeek, RTFILE_SEEK_CURRENT, &offAct);
    299     return rc;
    300 }
    301 
    302 /*******************************************************************************
    303 *   Public RTTar interface                                                     *
    304 *******************************************************************************/
     309        rc = RTFileSeek(hFile, offSeek, RTFILE_SEEK_CURRENT, NULL);
     310    return rc;
     311}
     312
    305313
    306314RTR3DECL(int) RTTarExists(const char *pszTarFile, const char *pszFile)
    307315{
    308316    /* Validate input */
    309     if (RT_UNLIKELY(!pszTarFile || !pszFile))
    310     {
    311         AssertMsgFailed(("Must supply pszTarFile, pszFile\n"));
    312         return VERR_INVALID_PARAMETER;
    313     }
     317    AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);
     318    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    314319
    315320    /* Open the tar file */
     
    321326    bool fFound = false;
    322327    RTTARRECORD record;
    323     size_t cbRead;
    324     do
    325     {
    326         rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);
     328    for (;;)
     329    {
     330/** @todo r=bird: the reading, validation and EOF check done here should be
     331 *        moved to a separate helper function. That would make it easiser to
     332 *        distinguish genuine-end-of-tar-file and VERR_EOF caused by a
     333 *        trunacted file. That said, rtTarSkipData won't return VERR_EOF, at
     334 *        least not on unix, since it's not a sin to seek beyond the end of a
     335 *        file. */
     336        rc = RTFileRead(hFile, &record, sizeof(record), NULL);
    327337        /* Check for error or EOF. */
    328338        if (RT_FAILURE(rc))
     
    333343            break;
    334344        /* We support normal files only */
    335         if (record.h.linkflag == LF_OLDNORMAL ||
    336             record.h.linkflag == LF_NORMAL)
     345        if (   record.h.linkflag == LF_OLDNORMAL
     346            || record.h.linkflag == LF_NORMAL)
    337347        {
    338348            if (!RTStrCmp(record.h.name, pszFile))
     
    346356            break;
    347357    }
    348     while(1);
    349358
    350359    RTFileClose(hFile);
     
    354363
    355364    /* Something found? */
    356     if (RT_SUCCESS(rc) &&
    357         fFound == false)
     365    if (    RT_SUCCESS(rc)
     366        &&  !fFound)
    358367        rc = VERR_FILE_NOT_FOUND;
    359368
     
    364373{
    365374    /* Validate input */
    366     if (RT_UNLIKELY(!pszTarFile || !ppapszFiles || !pcFiles))
    367     {
    368         AssertMsgFailed(("Must supply pszTarFile, ppapszFiles, pcFiles!\n"));
    369         return VERR_INVALID_PARAMETER;
    370     }
     375    AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);
     376    AssertPtrReturn(ppapszFiles, VERR_INVALID_POINTER);
     377    AssertPtrReturn(pcFiles, VERR_INVALID_POINTER);
    371378
    372379    /* Open the tar file */
     
    379386     * didn't need them. */
    380387    RTTARRECORD record;
    381     size_t cbRead;
    382     PRTTARFILELIST pCurr = NULL;
    383     PRTTARFILELIST pFirst = NULL;
    384     size_t cCount = 0;
    385     do
    386     {
    387         rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);
     388    char **papszFiles = NULL;
     389    size_t cFilesAlloc = 0;
     390    size_t cFiles = 0;
     391    for (;;)
     392    {
     393        rc = RTFileRead(hFile, &record, sizeof(record), NULL);
    388394        /* Check for error or EOF. */
    389395        if (RT_FAILURE(rc))
     
    394400            break;
    395401        /* We support normal files only */
    396         if (record.h.linkflag == LF_OLDNORMAL ||
    397             record.h.linkflag == LF_NORMAL)
     402        if (   record.h.linkflag == LF_OLDNORMAL
     403            || record.h.linkflag == LF_NORMAL)
    398404        {
    399             PRTTARFILELIST pNew = (PRTTARFILELIST)RTMemAllocZ(sizeof(RTTARFILELIST));
    400             ++cCount;
    401             /* Fill our linked list */
    402             if (pCurr)
    403                 pCurr->pNext = pNew;
    404             else
    405                 pFirst = pNew;
    406             pCurr = pNew;
    407             pCurr->pszFilename = RTStrDup(record.h.name);
     405            if (cFiles >= cFilesAlloc)
     406            {
     407                /* Double the array size, make sure the size doesn't wrap. */
     408                void  *pvNew = NULL;
     409                size_t cbNew = cFilesAlloc * sizeof(char *) * 2;
     410                if (cbNew / sizeof(char *) / 2 == cFilesAlloc)
     411                    pvNew = RTMemRealloc(papszFiles, cbNew);
     412                if (!pvNew)
     413                {
     414                    rc = VERR_NO_MEMORY;
     415                    break;
     416                }
     417                papszFiles = (char **)pvNew;
     418                cFilesAlloc *= 2;
     419            }
     420
     421            /* Duplicate the name */
     422            papszFiles[cFiles] = RTStrDup(record.h.name);
     423            if (!papszFiles[cFiles])
     424            {
     425                rc = VERR_NO_MEMORY;
     426                break;
     427            }
     428            cFiles++;
    408429        }
    409430        rc = rtTarSkipData(hFile, &record);
     
    411432            break;
    412433    }
    413     while(1);
    414434
    415435    RTFileClose(hFile);
     
    418438        rc = VINF_SUCCESS;
    419439
    420     /* On success copy the filenames over to the user provided array pointer */
    421     if (RT_SUCCESS(rc) &&
    422         cCount > 0)
    423     {
    424         *ppapszFiles = (char**)RTMemAlloc(sizeof(char*)*cCount);
    425         pCurr = pFirst;
    426         size_t i = 0;
    427         while (pCurr)
    428         {
    429             (*ppapszFiles)[i++] = pCurr->pszFilename;
    430             PRTTARFILELIST pTmp = pCurr->pNext;
    431             /* Free the linked list node */
    432             RTMemFree(pCurr);
    433             pCurr = pTmp;
    434         }
    435         *pcFiles = cCount;
    436     }
    437 
     440    /* Return the file array on success, dispose of it on failure. */
     441    if (RT_SUCCESS(rc))
     442    {
     443        *pcFiles = cFiles;
     444        *ppapszFiles = papszFiles;
     445    }
     446    else
     447    {
     448        while (cFiles-- > 0)
     449            RTStrFree(papszFiles[cFiles]);
     450        RTMemFree(papszFiles);
     451    }
    438452    return rc;
    439453}
     
    442456{
    443457    /* Validate input */
    444     if (RT_UNLIKELY(!pszTarFile || !pszOutputDir || !papszFiles))
    445     {
    446         AssertMsgFailed(("Must supply pszTarFile, pszOutputDir, papszFiles!\n"));
    447         return VERR_INVALID_PARAMETER;
    448     }
     458    AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);
     459    AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER);
     460    AssertPtrReturn(papszFiles, VERR_INVALID_POINTER);
    449461
    450462    /* Open the tar file */
     
    456468    /* Iterate through the tar file record by record. */
    457469    RTTARRECORD record;
    458     PRTTARFILELIST pCurr = NULL;
    459     PRTTARFILELIST pFirst = NULL;
    460     size_t cbRead = 0;
    461     size_t cCount = 0;
    462     do
    463     {
    464         rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);
    465         /* Check for error or EOF. */
    466         if (RT_FAILURE(rc))
    467             break;
    468         /* Check for EOF & data integrity */
    469         rc = rtTarCheckHeader(&record);
    470         if (RT_FAILURE(rc))
    471             break;
    472         /* We support normal files only */
    473         if (record.h.linkflag == LF_OLDNORMAL ||
    474             record.h.linkflag == LF_NORMAL)
     470    char **paExtracted = (char **)RTMemTmpAllocZ(sizeof(char *) * cFiles);
     471    if (paExtracted)
     472    {
     473        size_t cExtracted = 0;
     474        for (;;)
    475475        {
    476             bool fFound = false;
    477             for (size_t i=0; i < cFiles; ++i)
     476            rc = RTFileRead(hFile, &record, sizeof(record), NULL);
     477            /* Check for error or EOF. */
     478            if (RT_FAILURE(rc))
     479                break;
     480            /* Check for EOF & data integrity */
     481            rc = rtTarCheckHeader(&record);
     482            if (RT_FAILURE(rc))
     483                break;
     484            /* We support normal files only */
     485            if (   record.h.linkflag == LF_OLDNORMAL
     486                || record.h.linkflag == LF_NORMAL)
    478487            {
    479                 if (!RTStrCmp(record.h.name, papszFiles[i]))
     488                bool fFound = false;
     489                for (size_t i = 0; i < cFiles; ++i)
    480490                {
    481                     ++cCount; fFound = true;
    482                     char *pszTargetName;
    483                     RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, papszFiles[i]);
    484                     rc = rtTarCopyFileFrom(hFile, pszTargetName, &record);
     491                    if (!RTStrCmp(record.h.name, papszFiles[i]))
     492                    {
     493                        fFound = true;
     494                        if (cExtracted < cFiles)
     495                        {
     496                            char *pszTargetFile;
     497                            rc = RTStrAPrintf(&pszTargetFile, "%s/%s", pszOutputDir, papszFiles[i]);
     498                            if (rc > 0)
     499                            {
     500                                rc = rtTarCopyFileFrom(hFile, paExtracted[cExtracted], &record);
     501                                if (RT_SUCCESS(rc))
     502                                    paExtracted[cExtracted++] = pszTargetFile;
     503                                else
     504                                    RTStrFree(pszTargetFile);
     505                            }
     506                            else
     507                                rc = VERR_NO_MEMORY;
     508                        }
     509                        else
     510                            rc = VERR_ALREADY_EXISTS;
     511                        break;
     512                    }
     513                }
     514                if (RT_FAILURE(rc))
     515                    break;
     516                /* If the current record isn't a file in the file list we have to
     517                 * skip the data */
     518                if (!fFound)
     519                {
     520                    rc = rtTarSkipData(hFile, &record);
    485521                    if (RT_FAILURE(rc))
    486522                        break;
    487                     PRTTARFILELIST pNew = (PRTTARFILELIST)RTMemAllocZ(sizeof(RTTARFILELIST));
    488                     /* Fill our linked list */
    489                     if (pCurr)
    490                         pCurr->pNext = pNew;
    491                     else
    492                         pFirst = pNew;
    493                     pCurr = pNew;
    494                     pCurr->pszFilename = pszTargetName;
    495                     break;
    496523                }
    497524            }
     525        }
     526
     527        if (rc == VERR_EOF)
     528            rc = VINF_SUCCESS;
     529
     530        /* If we didn't found all files, indicate an error */
     531        if (cExtracted != cFiles && RT_SUCCESS(rc))
     532            rc = VERR_FILE_NOT_FOUND;
     533
     534        /* Cleanup the names of the extracted files, deleting them on failure. */
     535        while (cExtracted-- > 0)
     536        {
    498537            if (RT_FAILURE(rc))
    499                 break;
    500             /* If the current record isn't a file in the file list we have to
    501              * skip the data */
    502             if (!fFound)
    503             {
    504                 rc = rtTarSkipData(hFile, &record);
    505                 if (RT_FAILURE(rc))
    506                     break;
    507             }
     538                RTFileDelete(paExtracted[cExtracted]);
     539            RTStrFree(paExtracted[cExtracted]);
    508540        }
    509     }
    510     while(1);
     541        RTMemTmpFree(paExtracted);
     542    }
     543    else
     544        rc = VERR_NO_TMP_MEMORY;
    511545
    512546    RTFileClose(hFile);
    513 
    514     if (rc == VERR_EOF)
    515         rc = VINF_SUCCESS;
    516 
    517     /* If we didn't found all files, indicate an error */
    518     if (cCount != cFiles)
    519         rc = VERR_FILE_NOT_FOUND;
    520 
    521     pCurr = pFirst;
    522     while (pCurr)
    523     {
    524         /* If there was a failure during extraction, delete all files which
    525          * were extracted already */
    526         if (RT_FAILURE(rc))
    527             RTFileDelete(pCurr->pszFilename);
    528         /* Delete the filename string and the list node */
    529         RTStrFree(pCurr->pszFilename);
    530         PRTTARFILELIST pTmp = pCurr->pNext;
    531         RTMemFree(pCurr);
    532         pCurr = pTmp;
    533     }
    534 
    535     return rc;
    536 }
    537 
    538 RTR3DECL(int) RTTarExtractIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char** ppszFileName)
     547    return rc;
     548}
     549
     550RTR3DECL(int) RTTarExtractIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName)
    539551{
    540552    /* Validate input */
    541     if (RT_UNLIKELY(!pszTarFile || !pszOutputDir))
    542     {
    543         AssertMsgFailed(("Must supply pszTarFile, pszOutputDir!\n"));
    544         return VERR_INVALID_PARAMETER;
    545     }
     553    AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);
     554    AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER);
    546555
    547556    /* Open the tar file */
     
    553562    /* Iterate through the tar file record by record. */
    554563    RTTARRECORD record;
    555     size_t cbRead = 0;
    556     size_t cCount = 0;
     564    size_t iFile = 0;
    557565    bool fFound = false;
    558     do
    559     {
    560         rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);
     566    for (;;)
     567    {
     568        rc = RTFileRead(hFile, &record, sizeof(record), NULL);
    561569        /* Check for error or EOF. */
    562570        if (RT_FAILURE(rc))
     
    567575            break;
    568576        /* We support normal files only */
    569         if (record.h.linkflag == LF_OLDNORMAL ||
    570             record.h.linkflag == LF_NORMAL)
     577        if (   record.h.linkflag == LF_OLDNORMAL
     578            || record.h.linkflag == LF_NORMAL)
    571579        {
    572             if (iIndex == cCount)
     580            if (iIndex == iFile)
    573581            {
    574582                fFound = true;
    575583                char *pszTargetName;
    576                 RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, record.h.name);
    577                 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record);
    578                 /* On success copy the filename */
    579                 if (RT_SUCCESS(rc) &&
    580                     ppszFileName)
    581                     *ppszFileName = RTStrDup(record.h.name);
     584                rc = RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, record.h.name);
     585                if (rc > 0)
     586                {
     587                    rc = rtTarCopyFileFrom(hFile, pszTargetName, &record);
     588                    /* On success pass on the filename if requested. */
     589                    if (    RT_SUCCESS(rc)
     590                        &&  ppszFileName)
     591                        *ppszFileName = pszTargetName;
     592                    else
     593                        RTStrFree(pszTargetName);
     594                }
     595                else
     596                    rc = VERR_NO_MEMORY;
    582597                break;
    583598            }
    584             ++cCount;
     599            ++iFile;
    585600        }
    586601        rc = rtTarSkipData(hFile, &record);
     
    588603            break;
    589604    }
    590     while(1);
    591605
    592606    RTFileClose(hFile);
     
    596610
    597611    /* If we didn't found the index, indicate an error */
    598     if (!fFound)
     612    if (!fFound && RT_SUCCESS(rc))
    599613        rc = VERR_FILE_NOT_FOUND;
    600614
     
    605619{
    606620    /* Validate input */
    607     if (RT_UNLIKELY(!pszTarFile || !papszFiles))
    608     {
    609         AssertMsgFailed(("Must supply pszTarFile, papszFiles!\n"));
    610         return VERR_INVALID_PARAMETER;
    611     }
     621    AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);
     622    AssertPtrReturn(papszFiles, VERR_INVALID_POINTER);
    612623
    613624    /* Open the tar file */
    614625    RTFILE hFile;
    615     int rc = RTFileOpen(&hFile, pszTarFile, RTFILE_O_CREATE | RTFILE_O_WRITE);
    616     if (RT_FAILURE(rc))
    617         return rc;
    618 
    619     for (size_t i=0; i < cFiles; ++i)
     626    int rc = RTFileOpen(&hFile, pszTarFile, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
     627    if (RT_FAILURE(rc))
     628        return rc;
     629
     630    for (size_t i = 0; i < cFiles; ++i)
    620631    {
    621632        rc = rtTarCopyFileTo(hFile, papszFiles[i]);
     
    626637    /* gtar gives a warning, but the documentation says EOF is indicated by a
    627638     * zero block. Disabled for now. */
    628 //    if (RT_SUCCESS(rc))
    629 //    {
    630 //        /* Append the EOF record which is filled all by zeros */
    631 //        RTTARRECORD record;
    632 //        ASMMemFill32(&record, sizeof(record), 0);
    633 //        rc = RTFileWrite(hFile, &record, sizeof(record), NULL);
    634 //    }
     639#if 0
     640    if (RT_SUCCESS(rc))
     641    {
     642        /* Append the EOF record which is filled all by zeros */
     643        RTTARRECORD record;
     644        ASMMemFill32(&record, sizeof(record), 0);
     645        rc = RTFileWrite(hFile, &record, sizeof(record), NULL);
     646    }
     647#endif
    635648
    636649    /* Time to close the new tar archive */
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