tarvfs.cpp revision 4e47bb772df0d04d1ded3e06354de547d52e2d06
43af8389304c77c3d4db525de8907cb74207c380vboxsync * IPRT - TAR Virtual Filesystem.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Copyright (C) 2010 Oracle Corporation
43af8389304c77c3d4db525de8907cb74207c380vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
43af8389304c77c3d4db525de8907cb74207c380vboxsync * available from http://www.virtualbox.org. This file is free software;
43af8389304c77c3d4db525de8907cb74207c380vboxsync * you can redistribute it and/or modify it under the terms of the GNU
43af8389304c77c3d4db525de8907cb74207c380vboxsync * General Public License (GPL) as published by the Free Software
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
43af8389304c77c3d4db525de8907cb74207c380vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
43af8389304c77c3d4db525de8907cb74207c380vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * The contents of this file may alternatively be used under the terms
43af8389304c77c3d4db525de8907cb74207c380vboxsync * of the Common Development and Distribution License Version 1.0
43af8389304c77c3d4db525de8907cb74207c380vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
43af8389304c77c3d4db525de8907cb74207c380vboxsync * VirtualBox OSE distribution, in which case the provisions of the
43af8389304c77c3d4db525de8907cb74207c380vboxsync * CDDL are applicable instead of those of the GPL.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * You may elect to license modified versions of this file under the
43af8389304c77c3d4db525de8907cb74207c380vboxsync * terms and conditions of either the GPL or the CDDL or both.
43af8389304c77c3d4db525de8907cb74207c380vboxsync/******************************************************************************
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Header Files *
43af8389304c77c3d4db525de8907cb74207c380vboxsync ******************************************************************************/
43af8389304c77c3d4db525de8907cb74207c380vboxsync/*******************************************************************************
43af8389304c77c3d4db525de8907cb74207c380vboxsync* Structures and Typedefs *
43af8389304c77c3d4db525de8907cb74207c380vboxsync*******************************************************************************/
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * TAR reader state machine states.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Invalid state. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting the next file/dir/whatever entry. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting more zero headers or the end of the stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a GNU long name. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a GNU long link. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a normal header or another GNU specific one. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** End of valid states (not included). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Tar reader instance data.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Zero header counter. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The state machine state. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The type of the previous TAR header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The type of the current TAR header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The expected long name/link length (GNU). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current long name/link length (GNU). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The name of the current object.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * This is for handling GNU and PAX long names. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current link target if symlink or hardlink. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to the TAR reader instance data. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar directory, character device, block device, fifo socket or symbolic link.
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The stream offset of the (first) header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Pointer to the reader instance data (resides in the filesystem
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @todo Fix this so it won't go stale... Back ref from this obj to fss? */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The object info with unix attributes. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a TAR filesystem stream base object. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar file represented as a VFS I/O stream.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The basic TAR object data. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The number of bytes in the file. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The current file position. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The number of padding bytes following the file. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've reached the end of the file. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The input I/O stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a the private data of a TAR file I/O stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar filesystem stream private data.
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The input I/O stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The current object (referenced). */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Pointer to the private data if hVfsCurObj is representing a file. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The start offset. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The offset of the next header. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've reached the end of the stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've encountered a fatal error. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The TAR reader instance data. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a the private data of a TAR filesystem stream. */
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * Converts a numeric header field to the C native type.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @returns IPRT status code.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @param pszField The TAR header field.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @param cchField The length of the field.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @param fOctalOnly Must be octal.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @param pi64 Where to store the value.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsyncstatic int rtZipTarHdrFieldToNum(const char *pszField, size_t cchField, bool fOctalOnly, int64_t *pi64)
6efcec753717bae68ada4b060466934b111739fdvboxsync unsigned char const *puchField = (unsigned char const *)pszField;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Skip leading spaces. Include zeros to save a few slower loops below.
6efcec753717bae68ada4b060466934b111739fdvboxsync unsigned char ch;
6efcec753717bae68ada4b060466934b111739fdvboxsync while (cchField > 0 && ((ch = *puchField) == ' '|| ch == '0'))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Convert octal digits.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Was it terminated correctly?
6efcec753717bae68ada4b060466934b111739fdvboxsync * The first byte has the bit 7 set to indicate base-256, while bit 6
6efcec753717bae68ada4b060466934b111739fdvboxsync * is the signed bit. Bits 5:0 are the most significant value bits.
6efcec753717bae68ada4b060466934b111739fdvboxsync * The remaining bytes are used in full.
6efcec753717bae68ada4b060466934b111739fdvboxsync while (cchField-- > 0)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Calculates the TAR header checksums and detects if it's all zeros.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @returns true if all zeros, false if not.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @param pHdr The header to checksum.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @param pi32Unsigned Where to store the checksum calculated using
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * unsigned chars. This is the one POSIX
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * specifies.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @param pi32Signed Where to store the checksum calculated using
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * signed chars.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @remarks The reason why we calculate the checksum as both signed and unsigned
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * has to do with various the char C type being signed on some hosts
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * and unsigned on others.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsyncstatic bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Sum up the entire header.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Check if it's all zeros and replace the chksum field with spaces.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync i32Signed += (signed char)' ' * sizeof(pHdr->Common.chksum);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Validates the TAR header.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns VINF_SUCCESS if valid, VERR_TAR_ZERO_HEADER if all zeros, and
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * the appropriate VERR_TAR_XXX otherwise.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * @param pTar The TAR header.
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync * @param penmType Where to return the type of header on success.
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsyncstatic int rtZipTarHdrValidate(PCRTZIPTARHDR pTar, PRTZIPTARTYPE penmType)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Calc the checksum first since this enables us to detect zero headers.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (rtZipTarCalcChkSum(pTar, &i32ChkSum, &i32ChkSumSignedAlt))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Read the checksum field and match the checksums.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum);
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync && i32ChkSumSignedAlt != i64HdrChkSum) /** @todo test this */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Detect the TAR type.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** @todo detect star headers */
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync * Perform some basic checks.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo Implement full GNU TAR support. .*/
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default: /* shut up gcc */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parses and validates the first TAR header of a archive/file/dir/whatever.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns IPRT status code.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader stat.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pTar The TAR header that has been read.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param fFirst Set if this is the first header, otherwise
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderParseNextHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr, bool fFirst)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Basic header validation and detection first.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Handle the header by type.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Extract the name first.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0');
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCat(pThis->szName, sizeof(pThis->szName), "/");
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /* Old TAR */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0');
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Extract the link target.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || (pThis->enmType == RTZIPTARTYPE_GNU && pThis->szTarget[0] == '\0')
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szTarget, sizeof(pThis->szTarget),
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pHdr->Common.linkname, sizeof(pHdr->Common.linkname));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo implement PAX */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo implement solaris / pax attribute lists. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * A GNU long name or long link is a dummy record followed by one or
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * more 512 byte string blocks holding the long name/link. The name
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * lenght is encoded in the size field, null terminator included. If
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * it is a symlink or hard link the long name may be followed by a
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * long link sequence.
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync rc = rtZipTarHdrFieldToNum(pHdr->Gnu.size, sizeof(pHdr->Gnu.size), false /*fOctalOnly*/, &cb64);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmState = pHdr->Common.typeflag == RTZIPTAR_TF_GNU_LONGNAME
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo Implement or skip GNU headers */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parses and validates a TAR header.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns IPRT status code.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader stat.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pTar The TAR header that has been read.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderParseHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * The first record for a file/directory/whatever.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderParseNextHeader(pThis, pHdr, true /*fFirst*/);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * There should only be so many zero headers at the end of the file as
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * it is a function of the block size used when writing. Don't go on
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * reading them forever in case someone points us to /dev/zero.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (ASMMemIsAllU32(pHdr, sizeof(*pHdr), 0) != NULL)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync size_t cbIncoming = RTStrNLen((const char *)pHdr->ab, sizeof(*pHdr));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (cbIncoming + pThis->offGnuLongCur > pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && cbIncoming + pThis->offGnuLongCur != pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pThis->offGnuLongCur == pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderParseNextHeader(pThis, pHdr, false /*fFirst*/);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Translate a TAR header to an IPRT object info structure with additional UNIX
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * attributes.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * This completes the validation done by rtZipTarHdrValidate.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @param pObjInfo The object info structure (output).
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderGetFsObjInfo(PRTZIPTARREADER pThis, PRTFSOBJINFO pObjInfo)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Zap the whole structure, this takes care of unused space in the union.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Convert the TAR field in RTFSOBJINFO order.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync rc = rtZipTarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync } while (0)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, c64SecModTime);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, c64SecModTime);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTTimeSpecSetSeconds(&pObjInfo->AccessTime, c64SecModTime);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTTimeSpecSetSeconds(&pObjInfo->BirthTime, c64SecModTime);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (c64SecModTime != RTTimeSpecGetSeconds(&pObjInfo->ModificationTime))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode);
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Massage the result a little bit.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Also validate some more now that we've got the numbers to work with.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pszEnd == &pThis->szName[0] || pszEnd[-1] != '/')
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync#if 0 /* too strict */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_FILE; /* no better idea for now */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the reader is expecting more headers.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderExpectingMoreHeaders(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->enmState != RTZIPTARREADERSTATE_FIRST;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if we're at the end of the TAR file.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderIsAtEnd(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return false;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /* Here is a kludge to try deal with archivers not putting at least two
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync zero headers at the end. Afraid it may require further relaxing
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync later on, but let's try be strict about things for now. */
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync return pThis->cZeroHdrs >= (pThis->enmPrevType == RTZIPTARTYPE_POSIX ? 2U : 1U);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the current TAR object is a hard link or not.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true if it is, false if not.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderIsHardlink(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->Hdr.Common.typeflag == RTZIPTAR_TF_LINK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the TAR header includes a POSIX or GNU user name field.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncDECLINLINE(bool) rtZipTarReaderHasUserName(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the TAR header includes a POSIX or GNU group name field.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncDECLINLINE(bool) rtZipTarReaderHasGroupName(PRTZIPTARREADER pThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync * T h e V F S F i l e s y s t e m S t r e a m B i t s.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * T h e V F S F i l e s y s t e m S t r e a m B i t s.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * T h e V F S F i l e s y s t e m S t r e a m B i t s.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssBaseObj_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Currently there is nothing we really have to do here. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssBaseObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Copy the desired data.
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixOwner.uid = pThis->ObjInfo.Attr.u.Unix.uid;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName),
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixGroup.gid = pThis->ObjInfo.Attr.u.Unix.gid;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName),
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar filesystem base object operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream::Obj",
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync return rtZipTarFssBaseObj_QueryInfo(&pThis->BaseObj, pObjInfo, enmAddAttr);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Reads one segment.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @returns IPRT status code.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @param pThis The instance data.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @param pvBuf Where to put the read bytes.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @param cbToRead The number of bytes to read.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @param fBlocking Whether to block or not.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @param pcbRead Where to store the number of bytes actually read.
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic int rtZipTarFssIos_ReadOneSeg(PRTZIPTARIOSTREAM pThis, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead)
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Fend of reads beyond the end of the stream here.
43af8389304c77c3d4db525de8907cb74207c380vboxsync uint64_t cbLeft = (uint64_t)(pThis->cbFile - pThis->offFile);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Do the reading.
43af8389304c77c3d4db525de8907cb74207c380vboxsync int rc = RTVfsIoStrmRead(pThis->hVfsIos, pvBuf, cbToRead, fBlocking, pcbRead);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync rc = rtZipTarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead);
43af8389304c77c3d4db525de8907cb74207c380vboxsync for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
43af8389304c77c3d4db525de8907cb74207c380vboxsync rc = rtZipTarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Cannot write to a read-only I/O stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync NOREF(pvThis); NOREF(off); NOREF(pSgBuf); NOREF(fBlocking); NOREF(pcbWritten);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Flush(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* It's a read only stream, nothing dirty to flush. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* When we've reached the end, read will be set to indicate it. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync int rc = RTVfsIoStrmPoll(pThis->hVfsIos, fEvents, 0, fIntr, pfRetEvents);
43af8389304c77c3d4db525de8907cb74207c380vboxsync return RTVfsIoStrmPoll(pThis->hVfsIos, fEvents, cMillies, fIntr, pfRetEvents);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Tell(void *pvThis, PRTFOFF poffActual)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar I/O stream operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync { /* Obj */
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream::IoStream",
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_Close(void *pvThis)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return rtZipTarFssBaseObj_QueryInfo(pThis, pObjInfo, enmAddAttr);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NOREF(pvThis); NOREF(pAccessTime); NOREF(pModificationTime); NOREF(pChangeTime); NOREF(pBirthTime);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetOwner(void *pvThis, RTUID uid, RTGID gid)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSSYMLINKOPS,pfnRead}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_Read(void *pvThis, char *pszTarget, size_t cbTarget)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return RTStrCopy(pszTarget, cbTarget, pThis->pTarReader->szTarget);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar symbolic (and hardlink) operations.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync { /* Obj */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync "TarFsStream::Symlink",
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync { /* ObjSet */
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync RT_OFFSETOF(RTVFSSYMLINKOPS, Obj) - RT_OFFSETOF(RTVFSSYMLINKOPS, ObjSet),
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Take the lazy approach here, with the sideffect of providing some info
43af8389304c77c3d4db525de8907cb74207c380vboxsync that is actually kind of useful. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync return RTVfsIoStrmQueryInfo(pThis->hVfsIos, pObjInfo, enmAddAttr);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSFSSTREAMOPS,pfnNext}
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_Next(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj)
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Dispense with the current object.
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->pCurIosData->offFile = pThis->pCurIosData->cbFile;
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Check if we've already reached the end in some way.
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Make sure the input stream is in the right place.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync while ( offHdr >= 0
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc = RTVfsIoStrmSkip(pThis->hVfsIos, pThis->offNextHdr - offHdr);
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** @todo Ignore if we're at the end of the stream? */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Consume TAR headers.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Read the next header.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderIsAtEnd(&pThis->TarReader) ? VERR_EOF : VERR_TAR_UNEXPECTED_EOS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parse the it.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = rtZipTarReaderParseHeader(&pThis->TarReader, &Hdr);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync } while (rtZipTarReaderExpectingMoreHeaders(&pThis->TarReader));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Fill an object info structure from the current TAR state.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = rtZipTarReaderGetFsObjInfo(&pThis->TarReader, &Info);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Create an object of the appropriate type.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Files are represented by a VFS I/O stream.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
1f963f01f4f9a3848e72d4748c4f36feb715dba3vboxsync pIosData->cbPadding = (uint32_t)(Info.cbAllocated - Info.cbObject);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync pThis->offNextHdr += pIosData->cbFile + pIosData->cbPadding;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * We represent hard links using a symbolic link object. This fits
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * best with the way TAR stores it and there is currently no better
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * fitting VFS type alternative.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * All other objects are repesented using a VFS base object since they
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * carry no data streams (unless some TAR extension implements extended
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * attributes / alternative streams).
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Set the return data and we're done.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrDupEx(ppszName, pThis->TarReader.szName);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar filesystem stream operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync { /* Obj */
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream",
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsyncRTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss)
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Input validation.
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTFOFF const offStart = RTVfsIoStrmTell(hVfsIosIn);
43af8389304c77c3d4db525de8907cb74207c380vboxsync AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Retain the input stream and create a new filesystem stream handle.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->TarReader.enmPrevType= RTZIPTARTYPE_INVALID;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->TarReader.enmState = RTZIPTARREADERSTATE_FIRST;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Don't check if it's a TAR stream here, do that in the
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFss_Next. */