VirtualBox

Ignore:
Timestamp:
Feb 3, 2023 10:54:21 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155711
Message:

Runtime/commone/zip/tarvfswriter.cpp: Add support to write CPIO archives (only the ascii style without checksum is supported right now), shares a lot with the tar code so it didn't made sense to put it into a new vfs module

File:
1 edited

Legend:

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

    r98325 r98457  
    5454
    5555#include "tarvfsreader.h"
     56#include "cpiovfsreader.h"
    5657
    5758
     
    196197    /** When in update mode (RTZIPTAR_C_UPDATE) we have an reader FSS instance,
    197198     * though w/o the RTVFSFSSTREAM bits. (Allocated after this structure.) */
    198     PRTZIPTARFSSTREAM       pRead;
     199    PRTZIPTARFSSTREAM       pReadTar;
     200    /** Same when a CPIO archive is used. */
     201    /** @todo Possible to merge it with the tar reader maybe? */
     202    PRTZIPCPIOFSSTREAM      pReadCpio;
    199203    /** Set if we're in writing mode and pfnNext shall fail. */
    200204    bool                    fWriting;
     
    203207    /** Number of headers returned by rtZipTarFssWriter_ObjInfoToHdr. */
    204208    uint32_t                cHdrs;
    205     /** Header buffers returned by rtZipTarFssWriter_ObjInfoToHdr. */
    206     RTZIPTARHDR             aHdrs[3];
     209    /** Size of a single header returned by rtZipTarFssWriter_ObjInfoToHdr. */
     210    uint32_t                cbHdr;
     211    /** Format dependent header data. */
     212    union
     213    {
     214        /** Byte view of the different headers. */
     215        uint8_t             abHdrs[512];
     216        /** Header buffers returned by rtZipTarFssWriter_ObjInfoToHdrTar. */
     217        RTZIPTARHDR         aHdrsTar[3];
     218        /** CPIO stuff. */
     219        struct
     220        {
     221            /** CPIO header. */
     222            CPIOHDR         Hdr;
     223            /** The filepath which comes directly after the header - embedded here
     224             * to make the code more uniform with the tar code later on. */
     225            char            achFilePath[_1K];
     226            /** Maximum padding if the file path is completely used. */
     227            char            abPad[3];
     228        } Cpio;
     229    };
     230    /** The fallback I/O buffer if memory allocation fails. */
     231    uint8_t                 abIoBuf[512];
    207232} RTZIPTARFSSTREAMWRITER;
    208233
     
    288313
    289314/**
     315 * Returns a flag whether the writer is writing a tar archive, false if CPIO.
     316 *
     317 * @returns Flag whether the writer is in tar mode, true for tar and false for CPIO.
     318 * @param   pThis           The TAR writer instance.
     319 */
     320DECLINLINE(bool) rtZipTarFssWrite_IsTar(PRTZIPTARFSSTREAMWRITER pThis)
     321{
     322    return pThis->enmFormat != RTZIPTARFORMAT_CPIO_ASCII_NEW;
     323}
     324
     325
     326/**
     327 * Returns the block size of the given archive format.
     328 *
     329 * @returns Block size in bytes.
     330 * @param   pThis           The TAR writer instance.
     331 */
     332DECLINLINE(size_t) rtZipTarFssWrite_GetBlockSize(PRTZIPTARFSSTREAMWRITER pThis)
     333{
     334    if (!rtZipTarFssWrite_IsTar(pThis))
     335        return sizeof(uint32_t);
     336
     337    return RTZIPTAR_BLOCKSIZE;
     338}
     339
     340
     341/**
    290342 * Creates one or more tar headers for the object.
    291343 *
    292  * Returns RTZIPTARFSSTREAMWRITER::aHdrs and RTZIPTARFSSTREAMWRITER::cHdrs.
     344 * Returns RTZIPTARFSSTREAMWRITER::aHdrsTar and RTZIPTARFSSTREAMWRITER::cHdrs.
    293345 *
    294346 * @returns IPRT status code.
     
    302354 * @param   chType          The tar record type, UINT8_MAX for default.
    303355 */
    304 static int rtZipTarFssWriter_ObjInfoToHdr(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo,
    305                                           const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType)
     356static int rtZipTarFssWriter_ObjInfoToHdrTar(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo,
     357                                             const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType)
    306358{
    307359    pThis->cHdrs = 0;
    308     RT_ZERO(pThis->aHdrs[0]);
     360    RT_ZERO(pThis->aHdrsTar[0]);
    309361
    310362    /*
     
    312364     */
    313365    size_t cchPath = strlen(pszPath);
    314     if (cchPath < sizeof(pThis->aHdrs[0].Common.name))
    315     {
    316         memcpy(pThis->aHdrs[0].Common.name, pszPath, cchPath + 1);
     366    if (cchPath < sizeof(pThis->aHdrsTar[0].Common.name))
     367    {
     368        memcpy(pThis->aHdrsTar[0].Common.name, pszPath, cchPath + 1);
    317369#if RTPATH_STYLE != RTPATH_STR_F_STYLE_UNIX
    318         char *pszDosSlash = strchr(pThis->aHdrs[0].Common.name, '\\');
     370        char *pszDosSlash = strchr(pThis->aHdrsTar[0].Common.name, '\\');
    319371        while (pszDosSlash)
    320372        {
     
    339391    else
    340392        uValue = (uValue & pThis->fFileModeAndMask) | pThis->fFileModeOrMask;
    341     int rc = RTStrFormatU32(pThis->aHdrs[0].Common.mode, sizeof(pThis->aHdrs[0].Common.mode), uValue, 8 /*uBase*/,
    342                             -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.mode) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     393    int rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.mode, sizeof(pThis->aHdrsTar[0].Common.mode), uValue, 8 /*uBase*/,
     394                            -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.mode) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    343395    AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
    344396
     
    348400    uValue = pThis->uidOwner != NIL_RTUID ? pThis->uidOwner
    349401           : pObjInfo->Attr.u.Unix.uid != NIL_RTUID ? pObjInfo->Attr.u.Unix.uid : 0;
    350     rc = RTStrFormatU32(pThis->aHdrs[0].Common.uid, sizeof(pThis->aHdrs[0].Common.uid), uValue,
    351                         8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.uid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     402    rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.uid, sizeof(pThis->aHdrsTar[0].Common.uid), uValue,
     403                        8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.uid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    352404    AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
    353405
    354406    uValue = pThis->gidGroup != NIL_RTGID ? pThis->gidGroup
    355407           : pObjInfo->Attr.u.Unix.gid != NIL_RTGID ? pObjInfo->Attr.u.Unix.gid : 0;
    356     rc = RTStrFormatU32(pThis->aHdrs[0].Common.gid, sizeof(pThis->aHdrs[0].Common.gid), uValue,
    357                         8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.gid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     408    rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.gid, sizeof(pThis->aHdrsTar[0].Common.gid), uValue,
     409                        8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.gid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    358410    AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
    359411
     
    361413     * The file size.
    362414     */
    363     rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pObjInfo->cbObject);
     415    rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pObjInfo->cbObject);
    364416    AssertRCReturn(rc, rc);
    365417
     
    367419     * Modification time relative to unix epoc.
    368420     */
    369     rc = RTStrFormatU64(pThis->aHdrs[0].Common.mtime, sizeof(pThis->aHdrs[0].Common.mtime),
     421    rc = RTStrFormatU64(pThis->aHdrsTar[0].Common.mtime, sizeof(pThis->aHdrsTar[0].Common.mtime),
    370422                        RTTimeSpecGetSeconds(pThis->pModTime ? pThis->pModTime : &pObjInfo->ModificationTime),
    371                         8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.mtime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     423                        8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.mtime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    372424    AssertRCReturn(rc, rc);
    373425
     
    389441            case RTFS_TYPE_WHITEOUT:    AssertFailedReturn(VERR_WRONG_TYPE);
    390442        }
    391     pThis->aHdrs[0].Common.typeflag = chType;
     443    pThis->aHdrsTar[0].Common.typeflag = chType;
    392444
    393445    /* No link name, at least not for now.  Caller might set it. */
     
    397449     */
    398450    if (pThis->enmFormat == RTZIPTARFORMAT_GNU)
    399         memcpy(pThis->aHdrs[0].Gnu.magic, RTZIPTAR_GNU_MAGIC, sizeof(pThis->aHdrs[0].Gnu.magic));
     451        memcpy(pThis->aHdrsTar[0].Gnu.magic, RTZIPTAR_GNU_MAGIC, sizeof(pThis->aHdrsTar[0].Gnu.magic));
    400452    else if (   pThis->enmFormat == RTZIPTARFORMAT_USTAR
    401453             || pThis->enmFormat == RTZIPTARFORMAT_PAX)
    402454    {
    403         memcpy(pThis->aHdrs[0].Common.magic, RTZIPTAR_USTAR_MAGIC, sizeof(pThis->aHdrs[0].Common.magic));
    404         memcpy(pThis->aHdrs[0].Common.version, RTZIPTAR_USTAR_VERSION, sizeof(pThis->aHdrs[0].Common.version));
     455        memcpy(pThis->aHdrsTar[0].Common.magic, RTZIPTAR_USTAR_MAGIC, sizeof(pThis->aHdrsTar[0].Common.magic));
     456        memcpy(pThis->aHdrsTar[0].Common.version, RTZIPTAR_USTAR_VERSION, sizeof(pThis->aHdrsTar[0].Common.version));
    405457    }
    406458    else
     
    410462     * Owner and group names.  Silently truncate them for now.
    411463     */
    412     RTStrCopy(pThis->aHdrs[0].Common.uname, sizeof(pThis->aHdrs[0].Common.uname), pThis->pszOwner ? pThis->pszOwner : pszOwnerNm);
    413     RTStrCopy(pThis->aHdrs[0].Common.gname, sizeof(pThis->aHdrs[0].Common.uname), pThis->pszGroup ? pThis->pszGroup : pszGroupNm);
     464    RTStrCopy(pThis->aHdrsTar[0].Common.uname, sizeof(pThis->aHdrsTar[0].Common.uname), pThis->pszOwner ? pThis->pszOwner : pszOwnerNm);
     465    RTStrCopy(pThis->aHdrsTar[0].Common.gname, sizeof(pThis->aHdrsTar[0].Common.uname), pThis->pszGroup ? pThis->pszGroup : pszGroupNm);
    414466
    415467    /*
     
    419471        || RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode) )
    420472    {
    421         rc = RTStrFormatU32(pThis->aHdrs[0].Common.devmajor, sizeof(pThis->aHdrs[0].Common.devmajor),
     473        rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.devmajor, sizeof(pThis->aHdrsTar[0].Common.devmajor),
    422474                            RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device),
    423                             8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     475                            8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    424476        AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
    425477
    426         rc = RTStrFormatU32(pThis->aHdrs[0].Common.devminor, sizeof(pThis->aHdrs[0].Common.devmajor),
     478        rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.devminor, sizeof(pThis->aHdrsTar[0].Common.devmajor),
    427479                            RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device),
    428                             8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     480                            8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    429481        AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE);
    430482    }
     
    436488    if (pThis->enmFormat == RTZIPTARFORMAT_GNU)
    437489    {
    438         rc = RTStrFormatU64(pThis->aHdrs[0].Gnu.ctime, sizeof(pThis->aHdrs[0].Gnu.ctime),
     490        rc = RTStrFormatU64(pThis->aHdrsTar[0].Gnu.ctime, sizeof(pThis->aHdrsTar[0].Gnu.ctime),
    439491                            RTTimeSpecGetSeconds(&pObjInfo->ChangeTime),
    440                             8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Gnu.ctime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     492                            8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Gnu.ctime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    441493        AssertRCReturn(rc, rc);
    442494
    443         rc = RTStrFormatU64(pThis->aHdrs[0].Gnu.atime, sizeof(pThis->aHdrs[0].Gnu.atime),
     495        rc = RTStrFormatU64(pThis->aHdrsTar[0].Gnu.atime, sizeof(pThis->aHdrsTar[0].Gnu.atime),
    444496                            RTTimeSpecGetSeconds(&pObjInfo->ChangeTime),
    445                             8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs[0].Gnu.atime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
     497                            8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Gnu.atime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);
    446498        AssertRCReturn(rc, rc);
    447499    }
     
    452504     */
    453505    pThis->cHdrs = 1;
    454     return rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     506    pThis->cbHdr = sizeof(pThis->aHdrsTar[0]);
     507    return rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
     508}
     509
     510
     511/**
     512 * Formats a given 32-bit value into a CPIO header field.
     513 *
     514 * @returns nothing.
     515 * @param   pach8Field      The field to format the value into.
     516 * @param   u32             The value to format.
     517 */
     518static void rtZipTarFssWriter_CpioFmtU32(char pach8Field[8], uint32_t u32)
     519{
     520    static const char s_achHex[] = "0123456789abcdef";
     521    size_t         cchField  = 7;
     522    unsigned char *puchField = (unsigned char *)pach8Field;
     523    do
     524    {
     525        puchField[cchField--] = s_achHex[u32 & 0xf];
     526        u32 >>= 4;
     527    } while (cchField);
     528
     529    /* Last one. */
     530    puchField[0] = s_achHex[u32 & 0xf];
     531}
     532
     533
     534/**
     535 * Creates one or more CPIO headers for the object.
     536 *
     537 * Returns RTZIPTARFSSTREAMWRITER::Cpio::Hdr and RTZIPTARFSSTREAMWRITER::cHdrs.
     538 *
     539 * @returns IPRT status code.
     540 * @param   pThis           The TAR writer instance.
     541 * @param   pszPath         The path to the file.
     542 * @param   hVfsIos         The I/O stream of the file.
     543 * @param   fFlags          The RTVFSFSSTREAMOPS::pfnAdd flags.
     544 * @param   pObjInfo        The object information.
     545 * @param   pszOwnerNm      The owner name.
     546 * @param   pszGroupNm      The group name.
     547 */
     548static int rtZipTarFssWriter_ObjInfoToHdrCpio(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo,
     549                                              const char *pszOwnerNm, const char *pszGroupNm)
     550{
     551    RT_NOREF(pszOwnerNm, pszGroupNm);
     552    AssertReturn(!rtZipTarFssWrite_IsTar(pThis), VERR_INTERNAL_ERROR_3);
     553
     554    pThis->cHdrs = 0;
     555    RT_ZERO(pThis->Cpio.Hdr);
     556    RT_ZERO(pThis->Cpio.achFilePath);
     557
     558    /*
     559     * The path name first.  Make sure to flip DOS slashes.
     560     */
     561    size_t cchPath = strlen(pszPath) + 1;
     562    if (cchPath < sizeof(pThis->Cpio.achFilePath))
     563    {
     564        memcpy(&pThis->Cpio.achFilePath[0], pszPath, cchPath);
     565#if RTPATH_STYLE != RTPATH_STR_F_STYLE_UNIX
     566        char *pszDosSlash = strchr(&pThis->Cpio.achFilePath[0], '\\');
     567        while (pszDosSlash)
     568        {
     569            *pszDosSlash = '/';
     570            pszDosSlash = strchr(pszDosSlash + 1, '\\');
     571        }
     572#endif
     573    }
     574    else
     575        return VERR_TAR_NAME_TOO_LONG;
     576
     577    if (pObjInfo->cbObject != (uint32_t)pObjInfo->cbObject)
     578        return VERR_FILE_TOO_BIG;
     579
     580    /*
     581     * Set CPIO record magic and version.
     582     */
     583    if (pThis->enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW)
     584        memcpy(pThis->Cpio.Hdr.AsciiNew.achMagic, CPIO_HDR_NEW_MAGIC, sizeof(pThis->Cpio.Hdr.AsciiNew.achMagic));
     585    else
     586        AssertFailedReturn(VERR_INTERNAL_ERROR_4);
     587
     588    /*
     589     * File mode.  ASSUME that the unix part of the IPRT mode mask is
     590     * compatible with the TAR/Unix world.
     591     */
     592    uint32_t uValue = pObjInfo->Attr.fMode & RTFS_UNIX_MASK;
     593    if (pObjInfo->Attr.fMode) /* Don't want to modify the EOS record here. */
     594    {
     595        if (RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode))
     596            uValue = (uValue & pThis->fDirModeAndMask) | pThis->fDirModeOrMask;
     597        else
     598            uValue = (uValue & pThis->fFileModeAndMask) | pThis->fFileModeOrMask;
     599    }
     600    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achMode, uValue);
     601
     602    /*
     603     * Inode id.
     604     */
     605    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achInode, pObjInfo->Attr.u.Unix.INodeId);
     606
     607    /*
     608     * Number of hardlinks.
     609     */
     610    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achNLinks, pObjInfo->Attr.u.Unix.cHardlinks ? pObjInfo->Attr.u.Unix.cHardlinks : 1);
     611
     612    /*
     613     * uid & gid.  Just guard against NIL values as they won't fit.
     614     */
     615    uValue = pThis->uidOwner != NIL_RTUID ? pThis->uidOwner
     616           : pObjInfo->Attr.u.Unix.uid != NIL_RTUID ? pObjInfo->Attr.u.Unix.uid : 0;
     617    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achUid, uValue);
     618
     619    uValue = pThis->gidGroup != NIL_RTGID ? pThis->gidGroup
     620           : pObjInfo->Attr.u.Unix.gid != NIL_RTGID ? pObjInfo->Attr.u.Unix.gid : 0;
     621    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achGid, uValue);
     622
     623    /*
     624     * The file size.
     625     */
     626    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pObjInfo->cbObject);
     627
     628    /*
     629     * Modification time relative to unix epoc.
     630     */
     631    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achMTime,
     632                      RTTimeSpecGetSeconds(pThis->pModTime ? pThis->pModTime : &pObjInfo->ModificationTime));
     633
     634    /*
     635     * Char/block device numbers.
     636     */
     637    if (   RTFS_IS_DEV_BLOCK(pObjInfo->Attr.fMode)
     638        || RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode) )
     639    {
     640        rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achDevMajor, RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device));
     641        rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achDevMajor, RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device));
     642    }
     643
     644    /*
     645     * File path size including the terminator.
     646     */
     647    rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achNameSize, cchPath);
     648
     649    pThis->cHdrs = 1;
     650    pThis->cbHdr = RT_ALIGN_32(sizeof(pThis->Cpio.Hdr) + cchPath, 4);
     651    return VINF_SUCCESS;
     652}
     653
     654
     655/**
     656 * Creates one or more headers for the object.
     657 *
     658 * Returns RTZIPTARFSSTREAMWRITER::cbHdrs and RTZIPTARFSSTREAMWRITER::cHdrs.
     659 *
     660 * @returns IPRT status code.
     661 * @param   pThis           The TAR writer instance.
     662 * @param   pszPath         The path to the file.
     663 * @param   hVfsIos         The I/O stream of the file.
     664 * @param   fFlags          The RTVFSFSSTREAMOPS::pfnAdd flags.
     665 * @param   pObjInfo        The object information.
     666 * @param   pszOwnerNm      The owner name.
     667 * @param   pszGroupNm      The group name.
     668 * @param   chType          The tar record type, UINT8_MAX for default.
     669 */
     670static int rtZipTarFssWriter_ObjInfoToHdr(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo,
     671                                          const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType)
     672{
     673    if (!rtZipTarFssWrite_IsTar(pThis))
     674        return rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm);
     675
     676    return rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, chType);
    455677}
    456678
     
    486708    *pObjInfo = pPush->ObjInfo;
    487709    pObjInfo->cbObject = pPush->cbCurrent;
    488     pObjInfo->cbAllocated = RT_ALIGN_64(pPush->cbCurrent, RTZIPTAR_BLOCKSIZE);
     710    pObjInfo->cbAllocated = RT_ALIGN_64(pPush->cbCurrent, rtZipTarFssWrite_GetBlockSize(pPush->pParent));
    489711
    490712    /* Additional info. */
     
    498720        case RTFSOBJATTRADD_UNIX_OWNER:
    499721            pObjInfo->Attr.u.UnixOwner.uid = pPush->ObjInfo.Attr.u.Unix.uid;
    500             if (pPush->pParent)
    501                 strcpy(pObjInfo->Attr.u.UnixOwner.szName, pPush->pParent->aHdrs[0].Common.uname);
     722            if (   pPush->pParent
     723                && rtZipTarFssWrite_IsTar(pPush->pParent))
     724                strcpy(pObjInfo->Attr.u.UnixOwner.szName, pPush->pParent->aHdrsTar[0].Common.uname);
    502725            else
    503726                pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
     
    507730        case RTFSOBJATTRADD_UNIX_GROUP:
    508731            pObjInfo->Attr.u.UnixGroup.gid = pPush->ObjInfo.Attr.u.Unix.gid;
    509             if (pPush->pParent)
    510                 strcpy(pObjInfo->Attr.u.UnixGroup.szName, pPush->pParent->aHdrs[0].Common.uname);
     732            if (   pPush->pParent
     733                && rtZipTarFssWrite_IsTar(pPush->pParent))
     734                strcpy(pObjInfo->Attr.u.UnixGroup.szName, pPush->pParent->aHdrsTar[0].Common.uname);
    511735            else
    512736                pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
     
    8821106
    8831107    /*
    884      * Do we need to update the header.  pThis->aHdrs[0] will retain the current
     1108     * Do we need to update the header.  pThis->aHdrsTar[0] will retain the current
    8851109     * content at pPush->offHdr and we only need to update the size.
    8861110     */
    8871111    if (pPush->fOpenEnded)
    8881112    {
    889         rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pPush->cbCurrent);
     1113        if (rtZipTarFssWrite_IsTar(pThis))
     1114        {
     1115            rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pPush->cbCurrent);
     1116            if (RT_SUCCESS(rc))
     1117                rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
     1118        }
     1119        else
     1120        {
     1121            if (pPush->cbCurrent == (uint32_t)pPush->cbCurrent)
     1122                rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pPush->cbCurrent);
     1123            else
     1124                rc = VERR_FILE_TOO_BIG;
     1125        }
     1126
    8901127        if (RT_SUCCESS(rc))
    891             rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
    892         if (RT_SUCCESS(rc))
    893         {
    894             rc = RTVfsFileWriteAt(pThis->hVfsFile, pPush->offHdr, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), NULL);
     1128        {
     1129            rc = RTVfsFileWriteAt(pThis->hVfsFile, pPush->offHdr, &pThis->abHdrs[0], pThis->cbHdr, NULL);
    8951130            if (RT_SUCCESS(rc))
    8961131                rc = RTVfsFileSeek(pThis->hVfsFile, pPush->offData + pPush->cbCurrent, RTFILE_SEEK_BEGIN, NULL);
     
    9101145         * Do zero padding if necessary.
    9111146         */
    912         if (pPush->cbCurrent & (RTZIPTAR_BLOCKSIZE - 1))
    913         {
    914             size_t cbToZero = RTZIPTAR_BLOCKSIZE - (pPush->cbCurrent & (RTZIPTAR_BLOCKSIZE - 1));
     1147        size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis);
     1148        if (pPush->cbCurrent & (cbBlock - 1))
     1149        {
     1150            size_t cbToZero = cbBlock - (pPush->cbCurrent & (cbBlock - 1));
    9151151            rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, cbToZero, true /*fBlocking*/, NULL);
    9161152            if (RT_SUCCESS(rc))
     
    9451181     */
    9461182    /** @todo Optimize skipping to end of tar file in update mode. */
    947     while (!pThis->pRead->fEndOfStream)
    948     {
    949         int rc = rtZipTarFss_Next(pThis->pRead, NULL, NULL, NULL);
     1183    while (!pThis->pReadTar->fEndOfStream)
     1184    {
     1185        int rc = rtZipTarFss_Next(pThis->pReadTar, NULL, NULL, NULL);
    9501186        if (rc == VERR_EOF)
    9511187            break;
     
    9561192     * Seek to the desired cut-off point and indicate that we've switched to writing.
    9571193     */
    958     Assert(pThis->pRead->offNextHdr == pThis->pRead->offCurHdr);
    959     int rc = RTVfsFileSeek(pThis->hVfsFile, pThis->pRead->offNextHdr, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
     1194    Assert(pThis->pReadTar->offNextHdr == pThis->pReadTar->offCurHdr);
     1195    int rc = RTVfsFileSeek(pThis->hVfsFile, pThis->pReadTar->offNextHdr, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
    9601196    if (RT_SUCCESS(rc))
    9611197        pThis->fWriting = true;
     
    10521288
    10531289    /*
    1054      * Final fallback, 512KB buffer using the 3rd header.
    1055      */
    1056     AssertCompile(RT_ELEMENTS(pThis->aHdrs) >= 3);
    1057     *pcbBuf  = sizeof(pThis->aHdrs[2]);
     1290     * Final fallback, 512B buffer using the fallback buffer.
     1291     */
     1292    *pcbBuf  = sizeof(pThis->abIoBuf);
    10581293    *ppvFree = NULL;
    1059     return (uint8_t *)&pThis->aHdrs[2];
     1294    return &pThis->abIoBuf[0];
    10601295}
    10611296
     
    12491484     * Format the first header.
    12501485     */
    1251     int rc = rtZipTarFssWriter_ObjInfoToHdr(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, RTZIPTAR_TF_GNU_SPARSE);
     1486    int rc = rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, RTZIPTAR_TF_GNU_SPARSE);
    12521487    AssertRCReturn(rc, rc);
    12531488    AssertReturn(pThis->cHdrs == 1, VERR_INTERNAL_ERROR_2);
    12541489
    12551490    /* data size. */
    1256     rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pSparse->cbDataSpans);
     1491    rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pSparse->cbDataSpans);
    12571492    AssertRCReturn(rc, rc);
    12581493
    12591494    /* realsize. */
    1260     rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Gnu.realsize, pObjInfo->cbObject);
     1495    rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Gnu.realsize, pObjInfo->cbObject);
    12611496    AssertRCReturn(rc, rc);
    12621497
    1263     Assert(pThis->aHdrs[0].Gnu.isextended == 0);
     1498    Assert(pThis->aHdrsTar[0].Gnu.isextended == 0);
    12641499
    12651500    /*
    12661501     * Walk the sparse spans, fill and write headers one by one.
    12671502     */
    1268     PRTZIPTARGNUSPARSE  paSparse    = &pThis->aHdrs[0].Gnu.sparse[0];
    1269     uint32_t            cSparse     = RT_ELEMENTS(pThis->aHdrs[0].Gnu.sparse);
     1503    PRTZIPTARGNUSPARSE  paSparse    = &pThis->aHdrsTar[0].Gnu.sparse[0];
     1504    uint32_t            cSparse     = RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse);
    12701505    uint32_t            iSparse     = 0;
    12711506
     
    12811516            if (iSparse >= cSparse)
    12821517            {
    1283                 if (cSparse != RT_ELEMENTS(pThis->aHdrs[0].Gnu.sparse))
    1284                     pThis->aHdrs[0].GnuSparse.isextended = 1; /* more headers to come */
     1518                if (cSparse != RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse))
     1519                    pThis->aHdrsTar[0].GnuSparse.isextended = 1; /* more headers to come */
    12851520                else
    12861521                {
    1287                     pThis->aHdrs[0].Gnu.isextended = 1; /* more headers to come */
    1288                     rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     1522                    pThis->aHdrsTar[0].Gnu.isextended = 1; /* more headers to come */
     1523                    rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
    12891524                }
    12901525                if (RT_SUCCESS(rc))
    1291                     rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1526                    rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrsTar[0], sizeof(pThis->aHdrsTar[0]), true /*fBlocking*/, NULL);
    12921527                if (RT_FAILURE(rc))
    12931528                    return rc;
    1294                 RT_ZERO(pThis->aHdrs[0]);
    1295                 cSparse  = RT_ELEMENTS(pThis->aHdrs[0].GnuSparse.sp);
     1529                RT_ZERO(pThis->aHdrsTar[0]);
     1530                cSparse  = RT_ELEMENTS(pThis->aHdrsTar[0].GnuSparse.sp);
    12961531                iSparse  = 0;
    1297                 paSparse = &pThis->aHdrs[0].GnuSparse.sp[0];
     1532                paSparse = &pThis->aHdrsTar[0].GnuSparse.sp[0];
    12981533            }
    12991534
     
    13121547    if (iSparse != 0)
    13131548    {
    1314         if (cSparse != RT_ELEMENTS(pThis->aHdrs[0].Gnu.sparse))
    1315             Assert(pThis->aHdrs[0].GnuSparse.isextended == 0);
     1549        if (cSparse != RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse))
     1550            Assert(pThis->aHdrsTar[0].GnuSparse.isextended == 0);
    13161551        else
    13171552        {
    1318             Assert(pThis->aHdrs[0].Gnu.isextended == 0);
    1319             rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     1553            Assert(pThis->aHdrsTar[0].Gnu.isextended == 0);
     1554            rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
    13201555        }
    13211556        if (RT_SUCCESS(rc))
    1322             rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1557            rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrsTar[0], sizeof(pThis->aHdrsTar[0]), true /*fBlocking*/, NULL);
    13231558    }
    13241559    pThis->cHdrs = 0;
     
    13431578                                           const char *pszOwnerNm, const char *pszGroupNm)
    13441579{
     1580    AssertReturn(rtZipTarFssWrite_IsTar(pThis), VERR_INTERNAL_ERROR_2);
     1581
    13451582    /*
    13461583     * Scan the input file to locate all zero blocks.
     
    14631700        if (offHdr >= 0)
    14641701        {
    1465             rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1702            rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL);
    14661703            if (RT_SUCCESS(rc))
    14671704            {
    1468                 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);
     1705                pThis->cbWritten += pThis->cHdrs * pThis->cbHdr;
    14691706
    14701707                /*
     
    15021739                 * Do the zero padding.
    15031740                 */
    1504                 if ((cbReadTotal & (RTZIPTAR_BLOCKSIZE - 1)) && RT_SUCCESS(rc))
     1741                size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis);
     1742                if ((cbReadTotal & (cbBlock - 1)) && RT_SUCCESS(rc))
    15051743                {
    1506                     size_t cbToZero = RTZIPTAR_BLOCKSIZE - (cbReadTotal & (RTZIPTAR_BLOCKSIZE - 1));
     1744                    size_t cbToZero = cbBlock - (cbReadTotal & (cbBlock - 1));
    15071745                    rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, cbToZero, true /*fBlocking*/, NULL);
    15081746                    if (RT_SUCCESS(rc))
     
    15191757                    if (offRestore >= 0)
    15201758                    {
    1521                         rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, cbReadTotal);
    1522                         if (RT_SUCCESS(rc))
    1523                             rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     1759                        if (rtZipTarFssWrite_IsTar(pThis))
     1760                        {
     1761                            rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, cbReadTotal);
     1762                            if (RT_SUCCESS(rc))
     1763                                rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
     1764                        }
     1765                        else
     1766                        {
     1767                            if (pObjInfo->cbObject == (uint32_t)pObjInfo->cbObject)
     1768                                rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pObjInfo->cbObject);
     1769                            else
     1770                                rc = VERR_FILE_TOO_BIG;
     1771                        }
     1772
    15241773                        if (RT_SUCCESS(rc))
    15251774                        {
    1526                             rc = RTVfsFileWriteAt(pThis->hVfsFile, offHdr, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), NULL);
     1775                            rc = RTVfsFileWriteAt(pThis->hVfsFile, offHdr, &pThis->abHdrs[0], pThis->cbHdr, NULL);
    15271776                            if (RT_SUCCESS(rc))
    15281777                                rc = RTVfsFileSeek(pThis->hVfsFile, offRestore, RTFILE_SEEK_BEGIN, NULL);
     
    15661815    if (RT_SUCCESS(rc))
    15671816    {
    1568         rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1817        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL);
    15691818        if (RT_SUCCESS(rc))
    15701819        {
    1571             pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);
     1820            pThis->cbWritten += pThis->cHdrs * pThis->cbHdr;
    15721821
    15731822            /*
    1574              * Copy the bytes.  Padding the last buffer to a multiple of 512.
     1823             * Copy the bytes.  Padding the last buffer to a multiple of the block size.
    15751824             */
    15761825            void    *pvBufFree;
     
    15791828
    15801829            uint64_t cbLeft = pObjInfo->cbObject;
     1830            size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis);
    15811831            while (cbLeft > 0)
    15821832            {
     
    15871837
    15881838                size_t cbToWrite = cbRead;
    1589                 if (cbRead & (RTZIPTAR_BLOCKSIZE - 1))
     1839                if (cbRead & (cbBlock - 1))
    15901840                {
    1591                     size_t cbToZero = RTZIPTAR_BLOCKSIZE - (cbRead & (RTZIPTAR_BLOCKSIZE - 1));
     1841                    size_t cbToZero = cbBlock - (cbRead & (cbBlock - 1));
    15921842                    memset(&pbBuf[cbRead], 0, cbToZero);
    15931843                    cbToWrite += cbToZero;
     
    16431893#endif
    16441894        size_t cchTarget = strlen(szTarget);
    1645         if (cchTarget < sizeof(pThis->aHdrs[0].Common.linkname))
    1646         {
    1647             /*
    1648              * Create a header, add the link target and push it out.
    1649              */
    1650             rc = rtZipTarFssWriter_ObjInfoToHdr(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, UINT8_MAX);
     1895        if (rtZipTarFssWrite_IsTar(pThis))
     1896        {
     1897            if (cchTarget < sizeof(pThis->aHdrsTar[0].Common.linkname))
     1898            {
     1899                /*
     1900                 * Create a header, add the link target and push it out.
     1901                 */
     1902                rc = rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, UINT8_MAX);
     1903                if (RT_SUCCESS(rc))
     1904                {
     1905                    memcpy(pThis->aHdrsTar[0].Common.linkname, szTarget, cchTarget + 1);
     1906                    rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]);
     1907                    if (RT_SUCCESS(rc))
     1908                    {
     1909                        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr,
     1910                                              true /*fBlocking*/, NULL);
     1911                        if (RT_SUCCESS(rc))
     1912                        {
     1913                            pThis->cbWritten += pThis->cHdrs * pThis->cbHdr;
     1914                            return VINF_SUCCESS;
     1915                        }
     1916                        pThis->rcFatal = rc;
     1917                    }
     1918                }
     1919            }
     1920            else
     1921            {
     1922                /** @todo implement gnu and pax long name extensions. */
     1923                rc = VERR_TAR_NAME_TOO_LONG;
     1924            }
     1925        }
     1926        else
     1927        {
     1928            /* CPIO stores the target path as file data after the header, without any zero terminator. */
     1929            rc = rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm);
    16511930            if (RT_SUCCESS(rc))
    16521931            {
    1653                 memcpy(pThis->aHdrs[0].Common.linkname, szTarget, cchTarget + 1);
    1654                 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);
     1932                rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr,
     1933                                      true /*fBlocking*/, NULL);
    16551934                if (RT_SUCCESS(rc))
    16561935                {
    1657                     rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]),
    1658                                           true /*fBlocking*/, NULL);
     1936                    rc = RTVfsIoStrmWrite(pThis->hVfsIos, szTarget, cchTarget, true /*fBlocking*/, NULL);
    16591937                    if (RT_SUCCESS(rc))
    16601938                    {
    1661                         pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);
    1662                         return VINF_SUCCESS;
     1939                        /* Need to pad the entry to a 4 byte aligned boundary. */
     1940                        size_t cbPad = RT_ALIGN_32(cchTarget, 4) - cchTarget;
     1941                        if (cbPad)
     1942                            rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->Cpio.abPad[0], cbPad, true /*fBlocking*/, NULL);
     1943                        if (RT_SUCCESS(rc))
     1944                        {
     1945                            pThis->cbWritten += pThis->cHdrs * pThis->cbHdr + cbPad;
     1946                            return VINF_SUCCESS;
     1947                        }
    16631948                    }
    1664                     pThis->rcFatal = rc;
    16651949                }
     1950                pThis->rcFatal = rc;
    16661951            }
    1667         }
    1668         else
    1669         {
    1670             /** @todo implement gnu and pax long name extensions. */
    1671             rc = VERR_TAR_NAME_TOO_LONG;
    16721952        }
    16731953    }
     
    16951975    if (RT_SUCCESS(rc))
    16961976    {
    1697         rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1977        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL);
    16981978        if (RT_SUCCESS(rc))
    16991979        {
    1700             pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);
     1980            pThis->cbWritten += pThis->cHdrs * pThis->cbHdr;
    17011981            return VINF_SUCCESS;
    17021982        }
     
    17682048     * modifications takes place (truncating the archive or appending files).
    17692049     */
    1770     AssertReturn(pThis->pRead, VERR_ACCESS_DENIED);
     2050    AssertReturn(pThis->pReadTar || pThis->pReadCpio, VERR_ACCESS_DENIED);
    17712051    AssertReturn(pThis->fFlags & RTZIPTAR_C_UPDATE, VERR_ACCESS_DENIED);
    17722052
    17732053    AssertReturn(!pThis->fWriting, VERR_WRONG_ORDER);
    17742054
    1775     return rtZipTarFss_Next(pThis->pRead, ppszName, penmType, phVfsObj);
     2055    if (rtZipTarFssWrite_IsTar(pThis))
     2056        return rtZipTarFss_Next(pThis->pReadTar, ppszName, penmType, phVfsObj);
     2057    else
     2058        return rtZipCpioFss_Next(pThis->pReadCpio, ppszName, penmType, phVfsObj);
    17762059}
    17772060
     
    18262109                                                 ObjOwnerName.Attr.u.UnixOwner.szName, ObjGrpName.Attr.u.UnixOwner.szName);
    18272110        else if (   !(pThis->fFlags & RTZIPTAR_C_SPARSE)
    1828                  || ObjInfo.cbObject < RTZIPTAR_MIN_SPARSE)
     2111                 || ObjInfo.cbObject < RTZIPTAR_MIN_SPARSE
     2112                 || !rtZipTarFssWrite_IsTar(pThis))
    18292113            rc = rtZipTarFssWriter_AddFile(pThis, pszPath, hVfsIos, &ObjInfo,
    18302114                                           ObjOwnerName.Attr.u.UnixOwner.szName, ObjGrpName.Attr.u.UnixOwner.szName);
     
    18862170    const char *pszOwnerNm = "someone";
    18872171    const char *pszGroupNm = "somegroup";
     2172    const size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis);
    18882173    RTFSOBJINFO ObjInfo;
    18892174    if (cObjInfo == 0)
     
    18922177        RT_ZERO(ObjInfo);
    18932178        ObjInfo.cbObject                    = cbFile != UINT64_MAX ? cbFile : 0;
    1894         ObjInfo.cbAllocated                 = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, RTZIPTAR_BLOCKSIZE) : UINT64_MAX;
     2179        ObjInfo.cbAllocated                 = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, cbBlock) : UINT64_MAX;
    18952180        RTTimeNow(&ObjInfo.ModificationTime);
    18962181        ObjInfo.BirthTime                   = ObjInfo.ModificationTime;
     
    19172202        {
    19182203            ObjInfo.cbObject    = cbFile != UINT64_MAX ? cbFile : 0;
    1919             ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, RTZIPTAR_BLOCKSIZE) : UINT64_MAX;
     2204            ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, cbBlock) : UINT64_MAX;
    19202205        }
    19212206
     
    19762261    if (RT_SUCCESS(rc))
    19772262    {
    1978         size_t cbHdrs = pThis->cHdrs * sizeof(pThis->aHdrs[0]);
    1979         rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, cbHdrs, true /*fBlocking*/, NULL);
     2263        size_t cbHdrs = pThis->cHdrs * pThis->cbHdr;
     2264        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, cbHdrs, true /*fBlocking*/, NULL);
    19802265        if (RT_SUCCESS(rc))
    19812266        {
     
    20152300    if (RT_SUCCESS(rc))
    20162301    {
    2017         /*
    2018          * There are supposed to be two zero headers at the end of the archive.
    2019          * GNU tar may write more because of the way it does buffering,
    2020          * libarchive OTOH writes exactly two.
    2021          */
    2022         rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, RTZIPTAR_BLOCKSIZE * 2, true /*fBlocking*/, NULL);
     2302        if (rtZipTarFssWrite_IsTar(pThis))
     2303        {
     2304            /*
     2305             * There are supposed to be two zero headers at the end of the archive.
     2306             * GNU tar may write more because of the way it does buffering,
     2307             * libarchive OTOH writes exactly two.
     2308             */
     2309            rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, RTZIPTAR_BLOCKSIZE * 2, true /*fBlocking*/, NULL);
     2310            if (RT_SUCCESS(rc))
     2311                pThis->cbWritten += RTZIPTAR_BLOCKSIZE * 2;
     2312        }
     2313        else
     2314        {
     2315            /* CPIO has a special trailer marker. */
     2316            RTFSOBJINFO ObjInfoEos; RT_ZERO(ObjInfoEos);
     2317            rc = rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, CPIO_EOS_FILE_NAME, &ObjInfoEos, NULL, NULL);
     2318            if (RT_SUCCESS(rc))
     2319                rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cbHdr, true /*fBlocking*/, NULL);
     2320            if (RT_SUCCESS(rc))
     2321                pThis->cbWritten += pThis->cbHdr;
     2322        }
    20232323        if (RT_SUCCESS(rc))
    20242324        {
    2025             pThis->cbWritten += RTZIPTAR_BLOCKSIZE * 2;
    2026 
    20272325            /*
    20282326             * Flush the output.
     
    20962394    AssertReturn(   enmFormat == RTZIPTARFORMAT_GNU
    20972395                 || enmFormat == RTZIPTARFORMAT_USTAR
     2396                 || enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW
    20982397                 , VERR_NOT_IMPLEMENTED); /* Only implementing GNU and USTAR output at the moment. */
    20992398
     
    21532452    AssertReturn(   enmFormat == RTZIPTARFORMAT_GNU
    21542453                 || enmFormat == RTZIPTARFORMAT_USTAR
    2155                  , VERR_NOT_IMPLEMENTED); /* Only implementing GNU and USTAR output at the moment. */
     2454                 || enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW
     2455                 , VERR_NOT_IMPLEMENTED); /* Only implementing GNU, USTAR and CPIO output at the moment. */
    21562456
    21572457    RTFOFF const offStart = RTVfsFileTell(hVfsFile);
     
    21682468     */
    21692469    PRTZIPTARFSSTREAMWRITER pThis;
    2170     size_t const            cbThis = sizeof(*pThis) + (fFlags & RTZIPTAR_C_UPDATE ? sizeof(*pThis->pRead) : 0);
     2470    size_t const            cbThis = sizeof(*pThis) + (  fFlags & RTZIPTAR_C_UPDATE
     2471                                                       ?   enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW
     2472                                                         ? sizeof(*pThis->pReadTar)
     2473                                                         : sizeof(*pThis->pReadCpio)
     2474                                                       : 0);
    21712475    RTVFSFSSTREAM           hVfsFss;
    21722476    int rc = RTVfsNewFsStream(&g_rtZipTarFssOps, cbThis, NIL_RTVFS, NIL_RTVFSLOCK,
     
    21972501        {
    21982502            pThis->fWriting     = false;
    2199             pThis->pRead        = (PRTZIPTARFSSTREAM)(pThis + 1);
    2200             rtZipTarReaderInit(pThis->pRead, hVfsIos, (uint64_t)offStart);
     2503            if (rtZipTarFssWrite_IsTar(pThis))
     2504            {
     2505                pThis->pReadTar     = (PRTZIPTARFSSTREAM)(pThis + 1);
     2506                rtZipTarReaderInit(pThis->pReadTar, hVfsIos, (uint64_t)offStart);
     2507            }
     2508            else
     2509            {
     2510                pThis->pReadCpio    = (PRTZIPCPIOFSSTREAM)(pThis + 1);
     2511                rtZipCpioReaderInit(pThis->pReadCpio, hVfsIos, (uint64_t)offStart);
     2512            }
    22012513        }
    22022514
     
    23432655
    23442656    AssertReturn(hVfsObj != NIL_RTVFSOBJ, VERR_INVALID_HANDLE);
    2345     PRTZIPTARBASEOBJ pThisObj = rtZipTarFsStreamBaseObjToPrivate(pThis->pRead, hVfsObj);
    2346     AssertReturn(pThis, VERR_NOT_OWNER);
    2347 
    2348     AssertReturn(pThis->pRead, VERR_ACCESS_DENIED);
     2657    AssertReturn(pThis->pReadTar || pThis->pReadCpio, VERR_ACCESS_DENIED);
    23492658    AssertReturn(pThis->fFlags & RTZIPTAR_C_UPDATE, VERR_ACCESS_DENIED);
    23502659    AssertReturn(!pThis->fWriting, VERR_WRONG_ORDER);
    23512660
    2352     /*
    2353      * Seek to the desired cut-off point and indicate that we've switched to writing.
    2354      */
    2355     int rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr,
     2661    int rc;
     2662    if (rtZipTarFssWrite_IsTar(pThis))
     2663    {
     2664        PRTZIPTARBASEOBJ pThisObj = rtZipTarFsStreamBaseObjToPrivate(pThis->pReadTar, hVfsObj);
     2665        AssertReturn(pThisObj, VERR_NOT_OWNER);
     2666
     2667        /*
     2668         * Seek to the desired cut-off point and indicate that we've switched to writing.
     2669         */
     2670        rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr,
    23562671                           RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
     2672    }
     2673    else
     2674    {
     2675        PRTZIPCPIOBASEOBJ pThisObj = rtZipCpioFsStreamBaseObjToPrivate(pThis->pReadCpio, hVfsObj);
     2676        AssertReturn(pThisObj, VERR_NOT_OWNER);
     2677
     2678        /*
     2679         * Seek to the desired cut-off point and indicate that we've switched to writing.
     2680         */
     2681        rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr,
     2682                           RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
     2683    }
    23572684    if (RT_SUCCESS(rc))
    23582685        pThis->fWriting = true;
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