VirtualBox

Ignore:
Timestamp:
May 28, 2017 12:19:53 PM (8 years ago)
Author:
vboxsync
Message:

IPRT: Some more tar vfs writer bits.

Location:
trunk/src/VBox/Runtime/common/zip
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/zip/pkzipvfs.cpp

    r67116 r67123  
    12401240    rtZipPkzipFss_Next,
    12411241    NULL,
     1242    NULL,
    12421243    RTVFSFSSTREAMOPS_VERSION
    12431244};
  • trunk/src/VBox/Runtime/common/zip/tar.h

    r67116 r67123  
    9393 * @remarks The terminator character is not part of the field.  */
    9494#define RTZIPTAR_USTAR_VERSION  "00"
     95
     96/** The GNU magic + version value. */
     97#define RTZIPTAR_USTAR_GNU_MAGIC    "ustar  "
    9598
    9699
     
    136139AssertCompileMemberOffset(RTZIPTARHDRPOSIX, prefix,    345);
    137140
     141/**
     142 * GNU sparse data segment descriptor entry.
     143 */
     144typedef struct RTZIPTARGNUSPARSE
     145{
     146    char    offset[12];     /**< Absolute offset relative to the start of the file. */
     147    char    numbytes[12];
     148} RTZIPTARGNUSPARSE;
     149AssertCompileSize(RTZIPTARGNUSPARSE, 24);
     150AssertCompileMemberOffset(RTZIPTARGNUSPARSE, offset,    0);
     151AssertCompileMemberOffset(RTZIPTARGNUSPARSE, numbytes,  12);
    138152
    139153/**
     
    161175    char    longnames[4];
    162176    char    unused[1];
    163     struct
    164     {
    165         char offset[12];
    166         char numbytes[12];
    167     }       sparse[4];
    168     char    isextended;
     177    RTZIPTARGNUSPARSE sparse[4];
     178    char    isextended; /**< More headers about sparse stuff if binary value 1. */
    169179    char    realsize[12];
    170180    char    unused2[17];
     
    197207
    198208/**
     209 * GNU sparse header.
     210 */
     211typedef struct RTZIPTARHDRGNUSPARSE
     212{
     213    RTZIPTARGNUSPARSE sp[21];
     214    char    isextended;
     215    char    unused[7];
     216} RTZIPTARHDRGNUSPARSE;
     217AssertCompileSize(RTZIPTARHDRGNUSPARSE, 512);
     218AssertCompileMemberOffset(RTZIPTARHDRGNUSPARSE, sp,         0);
     219AssertCompileMemberOffset(RTZIPTARHDRGNUSPARSE, isextended, 504);
     220AssertCompileMemberOffset(RTZIPTARHDRGNUSPARSE, unused,     505);
     221
     222
     223/**
    199224 * The bits common to posix and GNU.
    200225 */
     
    218243    char    not_common[155+12];
    219244} RTZIPTARHDRCOMMON;
     245AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, name,      RTZIPTARHDRPOSIX, name);
     246AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, mode,      RTZIPTARHDRPOSIX, mode);
     247AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, uid,       RTZIPTARHDRPOSIX, uid);
     248AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, gid,       RTZIPTARHDRPOSIX, gid);
     249AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, size,      RTZIPTARHDRPOSIX, size);
     250AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, mtime,     RTZIPTARHDRPOSIX, mtime);
     251AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, chksum,    RTZIPTARHDRPOSIX, chksum);
     252AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, typeflag,  RTZIPTARHDRPOSIX, typeflag);
     253AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, linkname,  RTZIPTARHDRPOSIX, linkname);
     254AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, magic,     RTZIPTARHDRPOSIX, magic);
     255AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, version,   RTZIPTARHDRPOSIX, version);
     256AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, uname,     RTZIPTARHDRPOSIX, uname);
     257AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, gname,     RTZIPTARHDRPOSIX, gname);
     258AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, devmajor,  RTZIPTARHDRPOSIX, devmajor);
     259AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, devminor,  RTZIPTARHDRPOSIX, devminor);
     260
     261AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, name,      RTZIPTARHDRGNU, name);
     262AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, mode,      RTZIPTARHDRGNU, mode);
     263AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, uid,       RTZIPTARHDRGNU, uid);
     264AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, gid,       RTZIPTARHDRGNU, gid);
     265AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, size,      RTZIPTARHDRGNU, size);
     266AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, mtime,     RTZIPTARHDRGNU, mtime);
     267AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, chksum,    RTZIPTARHDRGNU, chksum);
     268AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, typeflag,  RTZIPTARHDRGNU, typeflag);
     269AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, linkname,  RTZIPTARHDRGNU, linkname);
     270AssertCompileMembersAtSameOffset(     RTZIPTARHDRCOMMON, magic,     RTZIPTARHDRGNU, magic);
     271AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, uname,     RTZIPTARHDRGNU, uname);
     272AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, gname,     RTZIPTARHDRGNU, gname);
     273AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, devmajor,  RTZIPTARHDRGNU, devmajor);
     274AssertCompileMembersSameSizeAndOffset(RTZIPTARHDRCOMMON, devminor,  RTZIPTARHDRGNU, devminor);
     275
    220276
    221277
  • trunk/src/VBox/Runtime/common/zip/tarvfs.cpp

    r67116 r67123  
    14751475    rtZipTarFss_Next,
    14761476    NULL,
     1477    NULL,
    14771478    RTVFSFSSTREAMOPS_VERSION
    14781479};
  • trunk/src/VBox/Runtime/common/zip/tarvfswriter.cpp

    r67116 r67123  
    3434#include <iprt/assert.h>
    3535#include <iprt/err.h>
     36#include <iprt/file.h>
    3637#include <iprt/mem.h>
    3738#include <iprt/path.h>
     
    3940#include <iprt/vfs.h>
    4041#include <iprt/vfslowlevel.h>
     42#include <iprt/zero.h>
    4143
    4244#include "tar.h"
     
    5456    RTVFSIOSTREAM           hVfsIos;
    5557
     58    /** The TAR format. */
     59    RTZIPTARFORMAT          enmFormat;
    5660    /** Set if we've encountered a fatal error. */
    5761    int                     rcFatal;
     
    8589                            8 /*uBase*/, -1 /*cchWidth*/, sizeof(pHdr->Common.chksum) - 1, RTSTR_F_ZEROPAD);
    8690    AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
     91    return VINF_SUCCESS;
     92}
     93
     94
     95
     96/**
     97 * Formats a 12 character wide file offset or size field.
     98 *
     99 * This is mainly used for RTZIPTARHDR::Common.size, but also for formatting the
     100 * sparse map.
     101 *
     102 * @returns IPRT status code.
     103 * @param   pach12Field     The 12 character wide destination field.
     104 * @param   off             The offset to set.
     105 */
     106static int rtZipTarFssWriter_FormatOffset(char pach12Field[12], uint64_t off)
     107{
     108    /*
     109     * Is the size small enough for the standard octal string encoding?
     110     *
     111     * Note! We could actually use the terminator character as well if we liked,
     112     *       but let not do that as it's easier to test this way.
     113     */
     114    if (off < _4G * 2U)
     115    {
     116        int rc = RTStrFormatU64(pach12Field, 12, off, 8 /*uBase*/, -1 /*cchWidth*/, 12 - 1, RTSTR_F_ZEROPAD);
     117        AssertRCReturn(rc, rc);
     118    }
     119    /*
     120     * No, use the base 256 extension. Set the highest bit of the left most
     121     * character.  We don't deal with negatives here, cause the size have to
     122     * be greater than zero.
     123     *
     124     * Note! The base-256 extension are never used by gtar or libarchive
     125     *       with the "ustar  \0" format version, only the later
     126     *       "ustar\000" version.  However, this shouldn't cause much
     127     *       trouble as they are not picky about what they read.
     128     */
     129    else
     130    {
     131        size_t         cchField  = 12 - 1;
     132        unsigned char *puchField = (unsigned char *)pach12Field;
     133        puchField[0] = 0x80;
     134        do
     135        {
     136            puchField[cchField--] = off & 0xff;
     137            off >>= 8;
     138        } while (cchField);
     139    }
     140
    87141    return VINF_SUCCESS;
    88142}
     
    156210
    157211    /*
    158      * Is the size small enough for the standard octal string encoding?
    159      *
    160      * Note! We could actually use the terminator character as well if we liked,
    161      *       but let not do that as it's easier to test this way.
    162      */
    163     uint64_t cbObject = pObjInfo->cbObject;
    164     if (cbObject < _4G * 2U)
    165     {
    166         rc = RTStrFormatU64(pThis->aHdrs[0].Common.size, sizeof(pThis->aHdrs[0].Common.size), cbObject,
    167                             8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.size) - 1, RTSTR_F_ZEROPAD);
    168         AssertRCReturn(rc, rc);
    169     }
    170     /*
    171      * No, use the base 256 extension. Set the highest bit of the left most
    172      * character.  We don't deal with negatives here, cause the size have to
    173      * be greater than zero.
    174      *
    175      * Note! The base-256 extension are never used by gtar or libarchive
    176      *       with the "ustar  \0" format version, only the later
    177      *       "ustar\000" version.  However, this shouldn't cause much
    178      *       trouble as they are not picky about what they read.
    179      */
    180     else
    181     {
    182         size_t         cchField  = sizeof(pThis->aHdrs[0].Common.size) - 1;
    183         unsigned char *puchField = (unsigned char*)pThis->aHdrs[0].Common.size;
    184         puchField[0] = 0x80;
    185         do
    186         {
    187             puchField[cchField--] = cbObject & 0xff;
    188             cbObject >>= 8;
    189         } while (cchField);
    190     }
     212     * The file size.
     213     */
     214    rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pObjInfo->cbObject);
     215    AssertRCReturn(rc, rc);
    191216
    192217    /*
     
    271296                                     PCRTFSOBJINFO pObjInfo, const char *pszOwnerNm, const char *pszGroupNm)
    272297{
    273     RT_NOREF(fFlags);
    274 
    275298    /*
    276299     * Append the header.
     
    279302    if (RT_SUCCESS(rc))
    280303    {
     304        RTFOFF const offHdr = fFlags & RTVFSFSSTRM_ADD_F_STREAM ? RTVfsIoStrmTell(pThis->hVfsIos) : RTFOFF_MAX;
    281305        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
    282306        if (RT_SUCCESS(rc))
     
    296320                if (!pbBuf)
    297321                {
    298                     cbBuf = sizeof(pThis->aHdrs);
    299                     pbBuf = (uint8_t *)&pThis->aHdrs[0];
     322                    cbBuf = sizeof(pThis->aHdrs) - sizeof(pThis->aHdrs[0]);
     323                    pbBuf = (uint8_t *)&pThis->aHdrs[1];
    300324                }
    301325            }
     
    304328             * Copy the bytes.  Padding the last buffer to a multiple of 512.
    305329             */
    306             uint64_t cbLeft = pObjInfo->cbObject;
    307             while (cbLeft > 0 && RT_SUCCESS(rc))
     330            if (!(fFlags & RTVFSFSSTRM_ADD_F_STREAM))
    308331            {
    309                 size_t cbRead = cbLeft > cbBuf ? cbBuf : (size_t)cbBuf;
    310                 rc = RTVfsIoStrmRead(hVfsIos, pbBuf, cbRead, true /*fBlocking*/, NULL);
    311                 if (RT_FAILURE(rc))
     332                uint64_t cbLeft = pObjInfo->cbObject;
     333                while (cbLeft > 0)
     334                {
     335                    size_t cbRead = cbLeft > cbBuf ? cbBuf : (size_t)cbBuf;
     336                    rc = RTVfsIoStrmRead(hVfsIos, pbBuf, cbRead, true /*fBlocking*/, NULL);
     337                    if (RT_FAILURE(rc))
     338                        break;
     339
     340                    size_t cbToWrite = cbRead;
     341                    if (cbRead & (sizeof(RTZIPTARHDR) - 1))
     342                    {
     343                        size_t cbToZero = sizeof(RTZIPTARHDR) - (cbRead & (sizeof(RTZIPTARHDR) - 1));
     344                        memset(&pbBuf[cbRead], 0, cbToZero);
     345                        cbToWrite += cbToZero;
     346                    }
     347
     348                    rc = RTVfsIoStrmWrite(pThis->hVfsIos, pbBuf, cbToWrite, true /*fBlocking*/, NULL);
     349                    if (RT_FAILURE(rc))
     350                        break;
     351                    pThis->cbWritten += cbToWrite;
     352                    cbLeft -= cbRead;
     353                }
     354            }
     355            /*
     356             * Same as above, only here we don't know the exact input length.
     357             */
     358            else
     359            {
     360                uint64_t cbReadTotal = 0;
     361                for (;;)
     362                {
     363                    size_t cbRead = 0;
     364                    int rc2 = rc = RTVfsIoStrmRead(hVfsIos, pbBuf, cbBuf, true /*fBlocking*/, &cbRead);
     365                    if (RT_SUCCESS(rc))
     366                    {
     367                        cbReadTotal += cbRead;
     368                        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pbBuf, cbRead, true /*fBlocking*/, NULL);
     369                        if (RT_SUCCESS(rc))
     370                        {
     371                            pThis->cbWritten += cbRead;
     372                            if (rc2 != VINF_EOF)
     373                                continue;
     374                        }
     375                    }
     376                    Assert(rc != VERR_EOF /* expecting VINF_EOF! */);
    312377                    break;
    313 
    314                 size_t cbToWrite = cbRead;
    315                 if (cbRead & (sizeof(RTZIPTARHDR) - 1))
     378                }
     379
     380                /* Do the zero padding. */
     381                if ((cbReadTotal & (sizeof(RTZIPTARHDR) - 1)) && RT_SUCCESS(rc))
    316382                {
    317                     size_t cbToZero = sizeof(RTZIPTARHDR) - (cbRead & (sizeof(RTZIPTARHDR) - 1));
    318                     memset(&pbBuf[cbRead], 0, cbToZero);
    319                     cbToWrite += cbToZero;
     383                    size_t cbToZero = sizeof(RTZIPTARHDR) - (cbReadTotal & (sizeof(RTZIPTARHDR) - 1));
     384                    rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, cbToZero, true /*fBlocking*/, NULL);
     385                    if (RT_SUCCESS(rc))
     386                        pThis->cbWritten += cbToZero;
    320387                }
    321388
    322                 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pbBuf, cbToWrite, true /*fBlocking*/, NULL);
    323                 if (RT_FAILURE(rc))
    324                     break;
    325                 pThis->cbWritten += cbToWrite;
    326                 cbLeft -= cbRead;
     389                /*
     390                 * Update the header.  We ASSUME that aHdr[0] is unmodified
     391                 * from before the data pumping above and just update the size.
     392                 */
     393                if (RT_SUCCESS(rc) && (RTFOFF)cbReadTotal != pObjInfo->cbObject)
     394                {
     395                    RTVFSFILE hVfsFile = RTVfsIoStrmToFile(pThis->hVfsIos);
     396                    if (hVfsFile != NIL_RTVFSFILE)
     397                    {
     398                        RTFOFF offRestore = RTVfsFileTell(hVfsFile);
     399                        if (offRestore >= 0)
     400                        {
     401                            rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, cbReadTotal);
     402                            if (RT_SUCCESS(rc))
     403                                rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     404                            if (RT_SUCCESS(rc))
     405                            {
     406                                rc = RTVfsFileWriteAt(hVfsFile, offHdr, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), NULL);
     407                                if (RT_SUCCESS(rc))
     408                                    rc = RTVfsFileSeek(hVfsFile, offRestore, RTFILE_SEEK_BEGIN, NULL);
     409                            }
     410                        }
     411                        else
     412                            rc = (int)offRestore;
     413                        RTVfsFileRelease(hVfsFile);
     414                    }
     415                    else
     416                        AssertFailedStmt(rc = VERR_NOT_A_FILE);
     417                }
    327418            }
    328419
     
    442533    pThis->hVfsIos = NIL_RTVFSIOSTREAM;
    443534
    444     /** @todo investigate zero end records.  */
    445 
    446535    return VINF_SUCCESS;
    447536}
     
    466555{
    467556    PRTZIPTARFSSTREAMWRITER pThis = (PRTZIPTARFSSTREAMWRITER)pvThis;
    468     RT_NOREF(pThis, pszPath, hVfsObj, fFlags);
    469557
    470558    /*
     
    517605}
    518606
     607
     608/**
     609 * @interface_method_impl{RTVFSFSSTREAMOPS,pfnEnd}
     610 */
     611static DECLCALLBACK(int) rtZipTarFssWriter_End(void *pvThis)
     612{
     613    PRTZIPTARFSSTREAMWRITER pThis = (PRTZIPTARFSSTREAMWRITER)pvThis;
     614    if (RT_SUCCESS(pThis->rcFatal))
     615    {
     616        /** @todo investigate zero end records. */
     617        return VINF_SUCCESS;
     618    }
     619    return pThis->rcFatal;
     620}
    519621
    520622
     
    536638    NULL,
    537639    rtZipTarFssWriter_Add,
     640    rtZipTarFssWriter_End,
    538641    RTVFSFSSTREAMOPS_VERSION
    539642};
    540643
    541644
    542 RTDECL(int) RTZipTarFsStreamToIoStream(RTVFSIOSTREAM hVfsIosOut, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss)
     645RTDECL(int) RTZipTarFsStreamToIoStream(RTVFSIOSTREAM hVfsIosOut, RTZIPTARFORMAT enmFormat,
     646                                       uint32_t fFlags, PRTVFSFSSTREAM phVfsFss)
    543647{
    544648    /*
     
    548652    *phVfsFss = NIL_RTVFSFSSTREAM;
    549653    AssertPtrReturn(hVfsIosOut, VERR_INVALID_HANDLE);
    550     AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
     654    AssertReturn(enmFormat > RTZIPTARFORMAT_INVALID && enmFormat < RTZIPTARFORMAT_END, VERR_INVALID_PARAMETER);
     655    AssertReturn(!(fFlags & ~RTZIPTAR_C_VALID_MASK), VERR_INVALID_FLAGS);
     656
     657    if (enmFormat == RTZIPTARFORMAT_DEFAULT)
     658        enmFormat = RTZIPTARFORMAT_GNU;
     659    AssertReturn(enmFormat == RTZIPTARFORMAT_GNU, VERR_NOT_IMPLEMENTED); /* Only implementing GNU output at the moment. */
    551660
    552661    uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosOut);
     
    562671    if (RT_SUCCESS(rc))
    563672    {
    564         pThis->hVfsIos = hVfsIosOut;
    565         pThis->rcFatal = VINF_SUCCESS;
     673        pThis->hVfsIos   = hVfsIosOut;
     674        pThis->enmFormat = enmFormat;
     675        pThis->rcFatal   = VINF_SUCCESS;
    566676
    567677        *phVfsFss = hVfsFss;
  • trunk/src/VBox/Runtime/common/zip/xarvfs.cpp

    r67116 r67123  
    18021802    0,
    18031803    rtZipXarFss_Next,
     1804    NULL,
    18041805    NULL,
    18051806    RTVFSFSSTREAMOPS_VERSION
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