43af8389304c77c3d4db525de8907cb74207c380vboxsync/* $Id$ */
43af8389304c77c3d4db525de8907cb74207c380vboxsync/** @file
43af8389304c77c3d4db525de8907cb74207c380vboxsync * IPRT - TAR Virtual Filesystem.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2010-2011 Oracle Corporation
43af8389304c77c3d4db525de8907cb74207c380vboxsync *
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 *
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 *
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
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/******************************************************************************
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Header Files *
43af8389304c77c3d4db525de8907cb74207c380vboxsync ******************************************************************************/
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include "internal/iprt.h"
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/zip.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync#include <iprt/asm.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/assert.h>
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync#include <iprt/ctype.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/err.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/poll.h>
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync#include <iprt/file.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/string.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/vfs.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include <iprt/vfslowlevel.h>
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync#include "tar.h"
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/*******************************************************************************
43af8389304c77c3d4db525de8907cb74207c380vboxsync* Structures and Typedefs *
43af8389304c77c3d4db525de8907cb74207c380vboxsync*******************************************************************************/
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * TAR reader state machine states.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsynctypedef enum RTZIPTARREADERSTATE
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Invalid state. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_INVALID = 0,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting the next file/dir/whatever entry. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_FIRST,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting more zero headers or the end of the stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_ZERO,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a GNU long name. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_GNU_LONGNAME,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a GNU long link. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_GNU_LONGLINK,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Expecting a normal header or another GNU specific one. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_GNU_NEXT,
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** End of valid states (not included). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE_END
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync} RTZIPTARREADERSTATE;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Tar reader instance data.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsynctypedef struct RTZIPTARREADER
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Zero header counter. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync uint32_t cZeroHdrs;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The state machine state. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADERSTATE enmState;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The type of the previous TAR header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARTYPE enmPrevType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The type of the current TAR header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARTYPE enmType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARHDR Hdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The expected long name/link length (GNU). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync uint32_t cbGnuLongExpect;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current long name/link length (GNU). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync uint32_t offGnuLongCur;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The name of the current object.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * This is for handling GNU and PAX long names. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync char szName[RTPATH_MAX];
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The current link target if symlink or hardlink. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync char szTarget[RTPATH_MAX];
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync} RTZIPTARREADER;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to the TAR reader instance data. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsynctypedef RTZIPTARREADER *PRTZIPTARREADER;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar directory, character device, block device, fifo socket or symbolic link.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef struct RTZIPTARBASEOBJ
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The stream offset of the (first) header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF offHdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** Pointer to the reader instance data (resides in the filesystem
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * stream).
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @todo Fix this so it won't go stale... Back ref from this obj to fss? */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync PRTZIPTARREADER pTarReader;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The object info with unix attributes. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFSOBJINFO ObjInfo;
43af8389304c77c3d4db525de8907cb74207c380vboxsync} RTZIPTARBASEOBJ;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a TAR filesystem stream base object. */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef RTZIPTARBASEOBJ *PRTZIPTARBASEOBJ;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar file represented as a VFS I/O stream.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef struct RTZIPTARIOSTREAM
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The basic TAR object data. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARBASEOBJ BaseObj;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The number of bytes in the file. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF cbFile;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The current file position. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF offFile;
3904c2d16fea12be79d817b255d59d480658b799vboxsync /** The start position in the hVfsIos (for seekable hVfsIos). */
3904c2d16fea12be79d817b255d59d480658b799vboxsync RTFOFF offStart;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The number of padding bytes following the file. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync uint32_t cbPadding;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've reached the end of the file. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync bool fEndOfStream;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The input I/O stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTVFSIOSTREAM hVfsIos;
43af8389304c77c3d4db525de8907cb74207c380vboxsync} RTZIPTARIOSTREAM;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a the private data of a TAR file I/O stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef RTZIPTARIOSTREAM *PRTZIPTARIOSTREAM;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar filesystem stream private data.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef struct RTZIPTARFSSTREAM
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The input I/O stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTVFSIOSTREAM hVfsIos;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The current object (referenced). */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTVFSOBJ hVfsCurObj;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Pointer to the private data if hVfsCurObj is representing a file. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync PRTZIPTARIOSTREAM pCurIosData;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The start offset. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF offStart;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** The offset of the next header. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF offNextHdr;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've reached the end of the stream. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync bool fEndOfStream;
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** Set if we've encountered a fatal error. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rcFatal;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** The TAR reader instance data. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARREADER TarReader;
43af8389304c77c3d4db525de8907cb74207c380vboxsync} RTZIPTARFSSTREAM;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** Pointer to a the private data of a TAR filesystem stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsynctypedef RTZIPTARFSSTREAM *PRTZIPTARFSSTREAM;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync/**
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * Converts a numeric header field to the C native type.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync *
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync * @returns IPRT status code.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync *
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.
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync */
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsyncstatic int rtZipTarHdrFieldToNum(const char *pszField, size_t cchField, bool fOctalOnly, int64_t *pi64)
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync{
6efcec753717bae68ada4b060466934b111739fdvboxsync unsigned char const *puchField = (unsigned char const *)pszField;
6efcec753717bae68ada4b060466934b111739fdvboxsync size_t const cchFieldOrg = cchField;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if ( fOctalOnly
6efcec753717bae68ada4b060466934b111739fdvboxsync || !(*puchField & 0x80))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Skip leading spaces. Include zeros to save a few slower loops below.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
6efcec753717bae68ada4b060466934b111739fdvboxsync unsigned char ch;
6efcec753717bae68ada4b060466934b111739fdvboxsync while (cchField > 0 && ((ch = *puchField) == ' '|| ch == '0'))
6efcec753717bae68ada4b060466934b111739fdvboxsync cchField--, puchField++;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Convert octal digits.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int64_t i64 = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync while (cchField > 0)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
6efcec753717bae68ada4b060466934b111739fdvboxsync unsigned char uDigit = *puchField - '0';
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (uDigit >= 8)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i64 <<= 3;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i64 |= uDigit;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
6efcec753717bae68ada4b060466934b111739fdvboxsync puchField++;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync cchField--;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *pi64 = i64;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Was it terminated correctly?
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync while (cchField > 0)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
6efcec753717bae68ada4b060466934b111739fdvboxsync ch = *puchField++;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (ch != 0 && ch != ' ')
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return cchField < cchFieldOrg
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync ? VERR_TAR_BAD_NUM_FIELD_TERM
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync : VERR_TAR_BAD_NUM_FIELD;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync cchField--;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync else
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
6efcec753717bae68ada4b060466934b111739fdvboxsync /*
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 */
6efcec753717bae68ada4b060466934b111739fdvboxsync int64_t i64 = !(0x40 & *puchField) ? 0 : -1;
6efcec753717bae68ada4b060466934b111739fdvboxsync i64 = (i64 << 6) | (*puchField & 0x3f);
6efcec753717bae68ada4b060466934b111739fdvboxsync cchField--;
6efcec753717bae68ada4b060466934b111739fdvboxsync puchField++;
6efcec753717bae68ada4b060466934b111739fdvboxsync
6efcec753717bae68ada4b060466934b111739fdvboxsync /*
6efcec753717bae68ada4b060466934b111739fdvboxsync * The remaining bytes are used in full.
6efcec753717bae68ada4b060466934b111739fdvboxsync */
6efcec753717bae68ada4b060466934b111739fdvboxsync while (cchField-- > 0)
6efcec753717bae68ada4b060466934b111739fdvboxsync {
6efcec753717bae68ada4b060466934b111739fdvboxsync if (RT_UNLIKELY(i64 > INT64_MAX / 256))
6efcec753717bae68ada4b060466934b111739fdvboxsync return VERR_TAR_NUM_VALUE_TOO_LARGE;
6efcec753717bae68ada4b060466934b111739fdvboxsync if (RT_UNLIKELY(i64 < INT64_MIN / 256))
6efcec753717bae68ada4b060466934b111739fdvboxsync return VERR_TAR_NUM_VALUE_TOO_LARGE;
6efcec753717bae68ada4b060466934b111739fdvboxsync i64 = (i64 << 8) | *puchField++;
6efcec753717bae68ada4b060466934b111739fdvboxsync }
6efcec753717bae68ada4b060466934b111739fdvboxsync *pi64 = i64;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VINF_SUCCESS;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync}
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Calculates the TAR header checksums and detects if it's all zeros.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *
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 *
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.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsyncstatic bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync{
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int32_t i32Unsigned = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int32_t i32Signed = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Sum up the entire header.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync const char *pch = (const char *)pHdr;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync const char *pchEnd = pch + sizeof(*pHdr);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync do
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i32Unsigned += *(unsigned char *)pch;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i32Signed += *(signed char *)pch;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync } while (++pch != pchEnd);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Check if it's all zeros and replace the chksum field with spaces.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync bool const fZeroHdr = i32Unsigned == 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pch = pHdr->Common.chksum;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pchEnd = pch + sizeof(pHdr->Common.chksum);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync do
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i32Unsigned -= *(unsigned char *)pch;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync i32Signed -= *(signed char *)pch;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync } while (++pch != pchEnd);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync i32Signed += (signed char)' ' * sizeof(pHdr->Common.chksum);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *pi32Unsigned = i32Unsigned;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (pi32Signed)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *pi32Signed = i32Signed;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return fZeroHdr;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync}
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync/**
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Validates the TAR header.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *
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.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsyncstatic int rtZipTarHdrValidate(PCRTZIPTARHDR pTar, PRTZIPTARTYPE penmType)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync{
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Calc the checksum first since this enables us to detect zero headers.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int32_t i32ChkSum;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int32_t i32ChkSumSignedAlt;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (rtZipTarCalcChkSum(pTar, &i32ChkSum, &i32ChkSumSignedAlt))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_ZERO_HEADER;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Read the checksum field and match the checksums.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int64_t i64HdrChkSum;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (RT_FAILURE(rc))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_BAD_CHKSUM_FIELD;
cf9045d402be1e8b7344a439eaefe2ca4c2b53d3vboxsync if ( i32ChkSum != i64HdrChkSum
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync && i32ChkSumSignedAlt != i64HdrChkSum) /** @todo test this */
cf9045d402be1e8b7344a439eaefe2ca4c2b53d3vboxsync return VERR_TAR_CHKSUM_MISMATCH;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Detect the TAR type.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync RTZIPTARTYPE enmType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pTar->Common.magic[0] == 'u'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.magic[1] == 's'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.magic[2] == 't'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.magic[3] == 'a'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.magic[4] == 'r')
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/** @todo detect star headers */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pTar->Common.magic[5] == '\0'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.version[0] == '0'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pTar->Common.version[1] == '0')
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync enmType = RTZIPTARTYPE_POSIX;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync else if ( pTar->Common.magic[5] == ' '
e4bb2f8312bbd05cdb3c4c01406274f946e7b76cvboxsync && pTar->Common.version[0] == ' '
e4bb2f8312bbd05cdb3c4c01406274f946e7b76cvboxsync && pTar->Common.version[1] == '\0')
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync enmType = RTZIPTARTYPE_GNU;
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync else if ( pTar->Common.magic[5] == '\0' /* VMWare ambiguity - they probably mean posix but */
e4bb2f8312bbd05cdb3c4c01406274f946e7b76cvboxsync && pTar->Common.version[0] == ' ' /* got the version wrong. */
e4bb2f8312bbd05cdb3c4c01406274f946e7b76cvboxsync && pTar->Common.version[1] == '\0')
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync enmType = RTZIPTARTYPE_POSIX;
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync else
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync return VERR_TAR_NOT_USTAR_V00;
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync }
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync else
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync enmType = RTZIPTARTYPE_ANCIENT;
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync *penmType = enmType;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync /*
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync * Perform some basic checks.
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (enmType)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARTYPE_POSIX:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( !RT_C_IS_ALNUM(pTar->Common.typeflag)
0b4e62c819b44a33a2ff548c18f11ed9709e1c48vboxsync && pTar->Common.typeflag != '\0')
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARTYPE_GNU:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pTar->Common.typeflag)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_OLDNORMAL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_NORMAL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_CONTIG:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_DIR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_CHR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_BLK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_LINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_SYMLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_FIFO:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_LONGLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_LONGNAME:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_DUMPDIR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_MULTIVOL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_SPARSE:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_VOLDHR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo Implement full GNU TAR support. .*/
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARTYPE_ANCIENT:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pTar->Common.typeflag)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_OLDNORMAL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_NORMAL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_CONTIG:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_DIR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_LINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_SYMLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_FIFO:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default: /* shut up gcc */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertFailedReturn(VERR_INTERNAL_ERROR_3);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VINF_SUCCESS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parses and validates the first TAR header of a archive/file/dir/whatever.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
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
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * clear.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderParseNextHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr, bool fFirst)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Basic header validation and detection first.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARTYPE enmType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = rtZipTarHdrValidate(pHdr, &enmType);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (RT_FAILURE_NP(rc))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (rc == VERR_TAR_ZERO_HEADER)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->cZeroHdrs = 1;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmState = RTZIPTARREADERSTATE_ZERO;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VINF_SUCCESS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rc;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (fFirst)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmType = enmType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Handle the header by type.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pHdr->Common.typeflag)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_OLDNORMAL:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_NORMAL:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_CONTIG:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_LINK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_SYMLINK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_CHR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_BLK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_FIFO:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_DIR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Extract the name first.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (!pHdr->Common.name[0])
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_EMPTY_NAME;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pThis->enmType == RTZIPTARTYPE_POSIX)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0');
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->szName[0] = '\0';
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pHdr->Posix.prefix[0])
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertRC(rc); /* shall not fail */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCat(pThis->szName, sizeof(pThis->szName), "/");
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertRC(rc); /* ditto */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertRCReturn(rc, rc);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync else if (pThis->enmType == RTZIPTARTYPE_GNU)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (!pThis->szName[0])
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertRCReturn(rc, rc);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync else
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
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 AssertRCReturn(rc, rc);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Extract the link target.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pHdr->Common.typeflag == RTZIPTAR_TF_LINK
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pHdr->Common.typeflag == RTZIPTAR_TF_SYMLINK)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pThis->enmType == RTZIPTARTYPE_POSIX
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pThis->enmType == RTZIPTARTYPE_ANCIENT
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || (pThis->enmType == RTZIPTARTYPE_GNU && pThis->szTarget[0] == '\0')
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync )
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync Assert(pThis->szTarget[0] == '\0');
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrCopyEx(pThis->szTarget, sizeof(pThis->szTarget),
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pHdr->Common.linkname, sizeof(pHdr->Common.linkname));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync AssertRCReturn(rc, rc);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync else
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->szTarget[0] = '\0';
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->Hdr = *pHdr;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_X_HDR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_X_GLOBAL:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo implement PAX */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_UNSUPPORTED_PAX_TYPE;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_SOLARIS_XHDR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo implement solaris / pax attribute lists. */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
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.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_GNU_LONGNAME:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_LONGLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (strcmp(pHdr->Gnu.name, "././@LongLink"))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_MALFORMED_GNU_LONGXXXX;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync int64_t cb64;
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync rc = rtZipTarHdrFieldToNum(pHdr->Gnu.size, sizeof(pHdr->Gnu.size), false /*fOctalOnly*/, &cb64);
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync if (RT_FAILURE(rc) || cb64 < 0 || cb64 > _1M)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_MALFORMED_GNU_LONGXXXX;
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync uint32_t cb = (uint32_t)cb64;
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync if (cb >= sizeof(pThis->szName))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_NAME_TOO_LONG;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync pThis->cbGnuLongExpect = cb;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->offGnuLongCur = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmState = pHdr->Common.typeflag == RTZIPTAR_TF_GNU_LONGNAME
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync ? RTZIPTARREADERSTATE_GNU_LONGNAME
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync : RTZIPTARREADERSTATE_GNU_LONGLINK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_DUMPDIR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_GNU_MULTIVOL:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_GNU_SPARSE:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_GNU_VOLDHR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /** @todo Implement or skip GNU headers */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
0bb0c0c0e3f9e5fdb3e745715dde1af951c04998vboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VINF_SUCCESS;
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync}
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
d001743f2d86c2cf54f3afdcc697d1b305dd9d72vboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parses and validates a TAR header.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns IPRT status code.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader stat.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pTar The TAR header that has been read.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderParseHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pThis->enmState)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * The first record for a file/directory/whatever.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARREADERSTATE_FIRST:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->Hdr.Common.typeflag = 0x7f;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmPrevType = pThis->enmType;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmType = RTZIPTARTYPE_INVALID;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->offGnuLongCur = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->cbGnuLongExpect = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->szName[0] = '\0';
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->szTarget[0] = '\0';
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderParseNextHeader(pThis, pHdr, true /*fFirst*/);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
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 */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARREADERSTATE_ZERO:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (ASMMemIsAllU32(pHdr, sizeof(*pHdr), 0) != NULL)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_ZERO_HEADER;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->cZeroHdrs++;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pThis->cZeroHdrs <= _64K / 512 + 2)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VINF_SUCCESS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_ZERO_HEADER;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARREADERSTATE_GNU_LONGNAME:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARREADERSTATE_GNU_LONGLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync size_t cbIncoming = RTStrNLen((const char *)pHdr->ab, sizeof(*pHdr));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (cbIncoming < sizeof(*pHdr))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync cbIncoming += 1;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (cbIncoming + pThis->offGnuLongCur > pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_MALFORMED_GNU_LONGXXXX;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( cbIncoming < sizeof(*pHdr)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && cbIncoming + pThis->offGnuLongCur != pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_MALFORMED_GNU_LONGXXXX;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pszDst += pThis->offGnuLongCur;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync memcpy(pszDst, pHdr->ab, cbIncoming);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
b385d10d09ba23d12c2baa62bb82381641e5a792vboxsync pThis->offGnuLongCur += (uint32_t)cbIncoming;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pThis->offGnuLongCur == pThis->cbGnuLongExpect)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmState = RTZIPTARREADERSTATE_GNU_NEXT;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VINF_SUCCESS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARREADERSTATE_GNU_NEXT:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->enmState = RTZIPTARREADERSTATE_FIRST;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderParseNextHeader(pThis, pHdr, false /*fFirst*/);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_INTERNAL_ERROR_5;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
d001743f2d86c2cf54f3afdcc697d1b305dd9d72vboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Translate a TAR header to an IPRT object info structure with additional UNIX
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * attributes.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync *
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * This completes the validation done by rtZipTarHdrValidate.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync *
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).
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic int rtZipTarReaderGetFsObjInfo(PRTZIPTARREADER pThis, PRTFSOBJINFO pObjInfo)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Zap the whole structure, this takes care of unused space in the union.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RT_ZERO(*pObjInfo);
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Convert the TAR field in RTFSOBJINFO order.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int rc;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int64_t i64Tmp;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync#define GET_TAR_NUMERIC_FIELD_RET(a_Var, a_Field) \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync do { \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync rc = rtZipTarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (RT_FAILURE(rc)) \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return rc; \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync (a_Var) = i64Tmp; \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if ((a_Var) != i64Tmp) \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_NUM_VALUE_TOO_LARGE; \
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync } while (0)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync GET_TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync int64_t c64SecModTime;
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))
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_NUM_VALUE_TOO_LARGE;
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);
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.cHardlinks = 1;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.INodeIdDevice = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.INodeId = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.fFlags = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.GenerationId = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.u.Unix.Device = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pThis->enmType)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARTYPE_POSIX:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTARTYPE_GNU:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync uint32_t uMajor, uMinor;
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))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_DEV_VALUE_TOO_LARGE;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync#undef GET_TAR_NUMERIC_FIELD_RET
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync /*
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Massage the result a little bit.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync * Also validate some more now that we've got the numbers to work with.
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if ( (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && pThis->enmType == RTZIPTARTYPE_POSIX)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_BAD_MODE_FIELD;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pObjInfo->Attr.fMode &= RTFS_UNIX_MASK;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
f7fcf2d6b3d1d0439517cd61ed95a68adb8b33e9vboxsync RTFMODE fModeType = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pThis->Hdr.Common.typeflag)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_OLDNORMAL:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_NORMAL:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_CONTIG:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync const char *pszEnd = strchr(pThis->szName, '\0');
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (pszEnd == &pThis->szName[0] || pszEnd[-1] != '/')
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync fModeType |= RTFS_TYPE_FILE;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync else
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync fModeType |= RTFS_TYPE_DIRECTORY;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_LINK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if (pObjInfo->cbObject != 0)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync#if 0 /* too strict */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_SIZE_NOT_ZERO;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync#else
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pObjInfo->cbObject = pObjInfo->cbAllocated = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync#endif
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_FILE; /* no better idea for now */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_SYMLINK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_SYMLINK;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_CHR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_DEV_CHAR;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_BLK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_DEV_BLOCK;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_DIR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_DIRECTORY;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_FIFO:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync fModeType |= RTFS_TYPE_FIFO;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_LONGLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTZIPTAR_TF_GNU_LONGNAME:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync fModeType = pObjInfo->Attr.fMode & RTFS_TYPE_MASK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (fModeType)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_FILE:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DIRECTORY:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_SYMLINK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DEV_BLOCK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DEV_CHAR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_FIFO:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync break;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync default:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case 0:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync default:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync if ( (pObjInfo->Attr.fMode & RTFS_TYPE_MASK)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync return VERR_TAR_MODE_WITH_TYPE;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pObjInfo->Attr.fMode &= ~RTFS_TYPE_MASK;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->Attr.fMode |= fModeType;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (pThis->Hdr.Common.typeflag)
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync {
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_CHR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_BLK:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_DIR:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync case RTZIPTAR_TF_FIFO:
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->cbObject = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync pObjInfo->cbAllocated = 0;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync break;
3a1d76f6489a485dfa7e3784c1fa76b4a53c28afvboxsync }
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return VINF_SUCCESS;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the reader is expecting more headers.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderExpectingMoreHeaders(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->enmState != RTZIPTARREADERSTATE_FIRST;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if we're at the end of the TAR file.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderIsAtEnd(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
ad5bb444f7c905a96159de8608c81bd4b4bce9c6vboxsync /* Turns out our own tar writer code doesn't get this crap right.
ad5bb444f7c905a96159de8608c81bd4b4bce9c6vboxsync Kludge our way around it. */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (!pThis->cZeroHdrs)
ad5bb444f7c905a96159de8608c81bd4b4bce9c6vboxsync return pThis->enmPrevType == RTZIPTARTYPE_GNU ? true /* IPRT tar.cpp */ : false;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
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}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the current TAR object is a hard link or not.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true if it is, false if not.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncstatic bool rtZipTarReaderIsHardlink(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->Hdr.Common.typeflag == RTZIPTAR_TF_LINK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the TAR header includes a POSIX or GNU user name field.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncDECLINLINE(bool) rtZipTarReaderHasUserName(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->Hdr.Common.uname[0] != '\0'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && ( pThis->enmType == RTZIPTARTYPE_POSIX
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pThis->enmType == RTZIPTARTYPE_GNU);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync/**
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Checks if the TAR header includes a POSIX or GNU group name field.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync *
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @returns true / false.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * @param pThis The TAR reader instance.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsyncDECLINLINE(bool) rtZipTarReaderHasGroupName(PRTZIPTARREADER pThis)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync{
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->Hdr.Common.gname[0] != '\0'
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && ( pThis->enmType == RTZIPTARTYPE_POSIX
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync || pThis->enmType == RTZIPTARTYPE_GNU);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync}
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/*
43af8389304c77c3d4db525de8907cb74207c380vboxsync *
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 *
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssBaseObj_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Currently there is nothing we really have to do here. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->offHdr = -1;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssBaseObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Copy the desired data.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync switch (enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync case RTFSOBJATTRADD_NOTHING:
43af8389304c77c3d4db525de8907cb74207c380vboxsync case RTFSOBJATTRADD_UNIX:
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pObjInfo = pThis->ObjInfo;
43af8389304c77c3d4db525de8907cb74207c380vboxsync break;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync case RTFSOBJATTRADD_UNIX_OWNER:
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pObjInfo = pThis->ObjInfo;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixOwner.uid = pThis->ObjInfo.Attr.u.Unix.uid;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (rtZipTarReaderHasUserName(pThis->pTarReader))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName),
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->pTarReader->Hdr.Common.uname);
43af8389304c77c3d4db525de8907cb74207c380vboxsync break;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync case RTFSOBJATTRADD_UNIX_GROUP:
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pObjInfo = pThis->ObjInfo;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixGroup.gid = pThis->ObjInfo.Attr.u.Unix.gid;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (rtZipTarReaderHasGroupName(pThis->pTarReader))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName),
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->pTarReader->Hdr.Common.gname);
43af8389304c77c3d4db525de8907cb74207c380vboxsync break;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync case RTFSOBJATTRADD_EASIZE:
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pObjInfo = pThis->ObjInfo;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
43af8389304c77c3d4db525de8907cb74207c380vboxsync RT_ZERO(pObjInfo->Attr.u);
43af8389304c77c3d4db525de8907cb74207c380vboxsync break;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync default:
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VERR_NOT_SUPPORTED;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar filesystem base object operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic const RTVFSOBJOPS g_rtZipTarFssBaseObjOps =
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJTYPE_BASE,
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream::Obj",
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssBaseObj_Close,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssBaseObj_QueryInfo,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION
43af8389304c77c3d4db525de8907cb74207c380vboxsync};
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync RTVfsIoStrmRelease(pThis->hVfsIos);
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync pThis->hVfsIos = NIL_RTVFSIOSTREAM;
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return rtZipTarFssBaseObj_Close(&pThis->BaseObj);
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync return rtZipTarFssBaseObj_QueryInfo(&pThis->BaseObj, pObjInfo, enmAddAttr);
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
3904c2d16fea12be79d817b255d59d480658b799vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
3904c2d16fea12be79d817b255d59d480658b799vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
3904c2d16fea12be79d817b255d59d480658b799vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
3904c2d16fea12be79d817b255d59d480658b799vboxsync Assert(pSgBuf->cSegs == 1);
3904c2d16fea12be79d817b255d59d480658b799vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
3904c2d16fea12be79d817b255d59d480658b799vboxsync * Make offset into a real offset so it's possible to do random access
3904c2d16fea12be79d817b255d59d480658b799vboxsync * on TAR files that are seekable. Fend of reads beyond the end of the
3904c2d16fea12be79d817b255d59d480658b799vboxsync * stream.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
3904c2d16fea12be79d817b255d59d480658b799vboxsync if (off < 0)
3904c2d16fea12be79d817b255d59d480658b799vboxsync off = pThis->offFile;
3904c2d16fea12be79d817b255d59d480658b799vboxsync if (off >= pThis->cbFile)
43af8389304c77c3d4db525de8907cb74207c380vboxsync return pcbRead ? VINF_EOF : VERR_EOF;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
3904c2d16fea12be79d817b255d59d480658b799vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync Assert(pThis->cbFile >= pThis->offFile);
3904c2d16fea12be79d817b255d59d480658b799vboxsync uint64_t cbLeft = (uint64_t)(pThis->cbFile - pThis->offFile);
3904c2d16fea12be79d817b255d59d480658b799vboxsync size_t cbToRead = pSgBuf->paSegs[0].cbSeg;
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (cbToRead > cbLeft)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (!pcbRead)
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VERR_EOF;
43af8389304c77c3d4db525de8907cb74207c380vboxsync cbToRead = (size_t)cbLeft;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Do the reading.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync size_t cbReadStack = 0;
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (!pcbRead)
43af8389304c77c3d4db525de8907cb74207c380vboxsync pcbRead = &cbReadStack;
3904c2d16fea12be79d817b255d59d480658b799vboxsync int rc = RTVfsIoStrmReadAt(pThis->hVfsIos, pThis->offStart + off, pSgBuf->paSegs[0].pvSeg, cbToRead, fBlocking, pcbRead);
3904c2d16fea12be79d817b255d59d480658b799vboxsync pThis->offFile = off + *pcbRead;
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (pThis->offFile >= pThis->cbFile)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync Assert(pThis->offFile == pThis->cbFile);
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->fEndOfStream = true;
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVfsIoStrmSkip(pThis->hVfsIos, pThis->cbPadding);
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return rc;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Cannot write to a read-only I/O stream. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync NOREF(pvThis); NOREF(off); NOREF(pSgBuf); NOREF(fBlocking); NOREF(pcbWritten);
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VERR_ACCESS_DENIED;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Flush(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* It's a read only stream, nothing dirty to flush. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync NOREF(pvThis);
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
43af8389304c77c3d4db525de8907cb74207c380vboxsync uint32_t *pfRetEvents)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* When we've reached the end, read will be set to indicate it. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync if ( (fEvents & RTPOLL_EVT_READ)
43af8389304c77c3d4db525de8907cb74207c380vboxsync && pThis->fEndOfStream)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync int rc = RTVfsIoStrmPoll(pThis->hVfsIos, fEvents, 0, fIntr, pfRetEvents);
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (RT_SUCCESS(rc))
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pfRetEvents |= RTPOLL_EVT_READ;
43af8389304c77c3d4db525de8907cb74207c380vboxsync else
43af8389304c77c3d4db525de8907cb74207c380vboxsync *pfRetEvents = RTPOLL_EVT_READ;
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return RTVfsIoStrmPoll(pThis->hVfsIos, fEvents, cMillies, fIntr, pfRetEvents);
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFssIos_Tell(void *pvThis, PRTFOFF poffActual)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;
1f963f01f4f9a3848e72d4748c4f36feb715dba3vboxsync *poffActual = pThis->offFile;
1f963f01f4f9a3848e72d4748c4f36feb715dba3vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar I/O stream operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic const RTVFSIOSTREAMOPS g_rtZipTarFssIosOps =
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync { /* Obj */
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJTYPE_IO_STREAM,
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream::IoStream",
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_Close,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_QueryInfo,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION
43af8389304c77c3d4db525de8907cb74207c380vboxsync },
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSIOSTREAMOPS_VERSION,
3904c2d16fea12be79d817b255d59d480658b799vboxsync RTVFSIOSTREAMOPS_FEAT_NO_SG,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_Read,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_Write,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_Flush,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_PollOne,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFssIos_Tell,
43af8389304c77c3d4db525de8907cb74207c380vboxsync NULL /*Skip*/,
43af8389304c77c3d4db525de8907cb74207c380vboxsync NULL /*ZeroFill*/,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSIOSTREAMOPS_VERSION
43af8389304c77c3d4db525de8907cb74207c380vboxsync};
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_Close(void *pvThis)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return rtZipTarFssBaseObj_Close(pThis);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return rtZipTarFssBaseObj_QueryInfo(pThis, pObjInfo, enmAddAttr);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NOREF(pvThis); NOREF(fMode); NOREF(fMask);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return VERR_ACCESS_DENIED;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NOREF(pvThis); NOREF(pAccessTime); NOREF(pModificationTime); NOREF(pChangeTime); NOREF(pBirthTime);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return VERR_ACCESS_DENIED;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_SetOwner(void *pvThis, RTUID uid, RTGID gid)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NOREF(pvThis); NOREF(uid); NOREF(gid);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return VERR_ACCESS_DENIED;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * @interface_method_impl{RTVFSSYMLINKOPS,pfnRead}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic DECLCALLBACK(int) rtZipTarFssSym_Read(void *pvThis, char *pszTarget, size_t cbTarget)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return RTStrCopy(pszTarget, cbTarget, pThis->pTarReader->szTarget);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync}
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync/**
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Tar symbolic (and hardlink) operations.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsyncstatic const RTVFSSYMLINKOPS g_rtZipTarFssSymOps =
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync{
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync { /* Obj */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJOPS_VERSION,
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync RTVFSOBJTYPE_SYMLINK,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync "TarFsStream::Symlink",
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync rtZipTarFssSym_Close,
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync rtZipTarFssSym_QueryInfo,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJOPS_VERSION
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync },
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSSYMLINKOPS_VERSION,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync 0,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync { /* ObjSet */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJSETOPS_VERSION,
1c434bf12564eb5a885b3f7e230b7638955004cevboxsync RT_OFFSETOF(RTVFSSYMLINKOPS, Obj) - RT_OFFSETOF(RTVFSSYMLINKOPS, ObjSet),
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rtZipTarFssSym_SetMode,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rtZipTarFssSym_SetTimes,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rtZipTarFssSym_SetOwner,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJSETOPS_VERSION
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync },
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rtZipTarFssSym_Read,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSSYMLINKOPS_VERSION
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync};
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_Close(void *pvThis)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVfsObjRelease(pThis->hVfsCurObj);
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->hVfsCurObj = NIL_RTVFSOBJ;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->pCurIosData = NULL;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVfsIoStrmRelease(pThis->hVfsIos);
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->hVfsIos = NIL_RTVFSIOSTREAM;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
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}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * @interface_method_impl{RTVFSFSSTREAMOPS,pfnNext}
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic DECLCALLBACK(int) rtZipTarFss_Next(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Dispense with the current object.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (pThis->hVfsCurObj != NIL_RTVFSOBJ)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (pThis->pCurIosData)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->pCurIosData->fEndOfStream = true;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->pCurIosData->offFile = pThis->pCurIosData->cbFile;
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->pCurIosData = NULL;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVfsObjRelease(pThis->hVfsCurObj);
43af8389304c77c3d4db525de8907cb74207c380vboxsync pThis->hVfsCurObj = NIL_RTVFSOBJ;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Check if we've already reached the end in some way.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (pThis->fEndOfStream)
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VERR_EOF;
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (pThis->rcFatal != VINF_SUCCESS)
43af8389304c77c3d4db525de8907cb74207c380vboxsync return pThis->rcFatal;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Make sure the input stream is in the right place.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFOFF offHdr = RTVfsIoStrmTell(pThis->hVfsIos);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync while ( offHdr >= 0
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync && offHdr < pThis->offNextHdr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc = RTVfsIoStrmSkip(pThis->hVfsIos, pThis->offNextHdr - offHdr);
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (RT_FAILURE(rc))
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
43af8389304c77c3d4db525de8907cb74207c380vboxsync /** @todo Ignore if we're at the end of the stream? */
43af8389304c77c3d4db525de8907cb74207c380vboxsync return pThis->rcFatal = rc;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync offHdr = RTVfsIoStrmTell(pThis->hVfsIos);
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (offHdr < 0)
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->rcFatal = (int)offHdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (offHdr > pThis->offNextHdr)
43af8389304c77c3d4db525de8907cb74207c380vboxsync return pThis->rcFatal = VERR_INTERNAL_ERROR_3;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Consume TAR headers.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync size_t cbHdrs = 0;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync int rc;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync do
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Read the next header.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTZIPTARHDR Hdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync size_t cbRead;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (RT_FAILURE(rc))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->rcFatal = rc;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (rc == VINF_EOF && cbRead == 0)
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->fEndOfStream = true;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return rtZipTarReaderIsAtEnd(&pThis->TarReader) ? VERR_EOF : VERR_TAR_UNEXPECTED_EOS;
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync }
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (cbRead != sizeof(Hdr))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->rcFatal = VERR_TAR_UNEXPECTED_EOS;
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync cbHdrs += sizeof(Hdr);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Parse the it.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = rtZipTarReaderParseHeader(&pThis->TarReader, &Hdr);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (RT_FAILURE(rc))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync return pThis->rcFatal = rc;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync } while (rtZipTarReaderExpectingMoreHeaders(&pThis->TarReader));
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->offNextHdr = offHdr + cbHdrs;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync /*
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync * Fill an object info structure from the current TAR state.
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTFSOBJINFO Info;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = rtZipTarReaderGetFsObjInfo(&pThis->TarReader, &Info);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (RT_FAILURE(rc))
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return pThis->rcFatal = rc;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Create an object of the appropriate type.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJTYPE enmType;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSOBJ hVfsObj;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync RTFMODE fType = Info.Attr.fMode & RTFS_TYPE_MASK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync if (rtZipTarReaderIsHardlink(&pThis->TarReader))
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync fType = RTFS_TYPE_SYMLINK;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync switch (fType)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync /*
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Files are represented by a VFS I/O stream.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_FILE:
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSIOSTREAM hVfsIos;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARIOSTREAM pIosData;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rc = RTVfsNewIoStream(&g_rtZipTarFssIosOps,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync sizeof(*pIosData),
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFS,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFSLOCK,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync &hVfsIos,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync (void **)&pIosData);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (RT_FAILURE(rc))
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return pThis->rcFatal = rc;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->BaseObj.offHdr = offHdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->BaseObj.pTarReader= &pThis->TarReader;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->BaseObj.ObjInfo = Info;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->cbFile = Info.cbObject;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->offFile = 0;
3904c2d16fea12be79d817b255d59d480658b799vboxsync pIosData->offStart = RTVfsIoStrmTell(pThis->hVfsIos);
1f963f01f4f9a3848e72d4748c4f36feb715dba3vboxsync pIosData->cbPadding = (uint32_t)(Info.cbAllocated - Info.cbObject);
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->fEndOfStream = false;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pIosData->hVfsIos = pThis->hVfsIos;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVfsIoStrmRetain(pThis->hVfsIos);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync pThis->pCurIosData = pIosData;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync pThis->offNextHdr += pIosData->cbFile + pIosData->cbPadding;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync enmType = RTVFSOBJTYPE_IO_STREAM;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync hVfsObj = RTVfsObjFromIoStream(hVfsIos);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVfsIoStrmRelease(hVfsIos);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync break;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync /*
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 */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_SYMLINK:
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVFSSYMLINK hVfsSym;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARBASEOBJ pBaseObjData;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rc = RTVfsNewSymlink(&g_rtZipTarFssSymOps,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync sizeof(*pBaseObjData),
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFS,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFSLOCK,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync &hVfsSym,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync (void **)&pBaseObjData);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (RT_FAILURE(rc))
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return pThis->rcFatal = rc;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->offHdr = offHdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->pTarReader= &pThis->TarReader;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->ObjInfo = Info;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync enmType = RTVFSOBJTYPE_SYMLINK;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync hVfsObj = RTVfsObjFromSymlink(hVfsSym);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVfsSymlinkRelease(hVfsSym);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync break;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync /*
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 */
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DEV_BLOCK:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DEV_CHAR:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_DIRECTORY:
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync case RTFS_TYPE_FIFO:
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync PRTZIPTARBASEOBJ pBaseObjData;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync rc = RTVfsNewBaseObj(&g_rtZipTarFssBaseObjOps,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync sizeof(*pBaseObjData),
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFS,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync NIL_RTVFSLOCK,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync &hVfsObj,
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync (void **)&pBaseObjData);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (RT_FAILURE(rc))
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return pThis->rcFatal = rc;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->offHdr = offHdr;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->pTarReader= &pThis->TarReader;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pBaseObjData->ObjInfo = Info;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync enmType = RTVFSOBJTYPE_BASE;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync break;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync default:
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync AssertFailed();
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return pThis->rcFatal = VERR_INTERNAL_ERROR_5;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync pThis->hVfsCurObj = hVfsObj;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync /*
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync * Set the return data and we're done.
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync */
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (ppszName)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync rc = RTStrDupEx(ppszName, pThis->TarReader.szName);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (RT_FAILURE(rc))
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return rc;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (phVfsObj)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync {
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync RTVfsObjRetain(hVfsObj);
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync *phVfsObj = hVfsObj;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync if (penmType)
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync *penmType = enmType;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync/**
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Tar filesystem stream operations.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsyncstatic const RTVFSFSSTREAMOPS rtZipTarFssOps =
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync { /* Obj */
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJTYPE_FS_STREAM,
43af8389304c77c3d4db525de8907cb74207c380vboxsync "TarFsStream",
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFss_Close,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFss_QueryInfo,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSOBJOPS_VERSION
43af8389304c77c3d4db525de8907cb74207c380vboxsync },
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSFSSTREAMOPS_VERSION,
43af8389304c77c3d4db525de8907cb74207c380vboxsync 0,
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFss_Next,
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSFSSTREAMOPS_VERSION
43af8389304c77c3d4db525de8907cb74207c380vboxsync};
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsyncRTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss)
43af8389304c77c3d4db525de8907cb74207c380vboxsync{
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Input validation.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync AssertPtrReturn(phVfsFss, VERR_INVALID_HANDLE);
43af8389304c77c3d4db525de8907cb74207c380vboxsync *phVfsFss = NIL_RTVFSFSSTREAM;
43af8389304c77c3d4db525de8907cb74207c380vboxsync AssertPtrReturn(hVfsIosIn, VERR_INVALID_HANDLE);
1e7030f54deae0a8aa27817ab26c5d6d6c246541vboxsync AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTFOFF const offStart = RTVfsIoStrmTell(hVfsIosIn);
43af8389304c77c3d4db525de8907cb74207c380vboxsync AssertReturn(offStart >= 0, (int)offStart);
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosIn);
43af8389304c77c3d4db525de8907cb74207c380vboxsync AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /*
43af8389304c77c3d4db525de8907cb74207c380vboxsync * Retain the input stream and create a new filesystem stream handle.
43af8389304c77c3d4db525de8907cb74207c380vboxsync */
43af8389304c77c3d4db525de8907cb74207c380vboxsync PRTZIPTARFSSTREAM pThis;
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVFSFSSTREAM hVfsFss;
4152e1d3f89dc5e2319a53c242e8e7cfcdf3726evboxsync int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis);
43af8389304c77c3d4db525de8907cb74207c380vboxsync if (RT_SUCCESS(rc))
43af8389304c77c3d4db525de8907cb74207c380vboxsync {
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->hVfsIos = hVfsIosIn;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->hVfsCurObj = NIL_RTVFSOBJ;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->pCurIosData = NULL;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->offStart = offStart;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->offNextHdr = offStart;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->fEndOfStream = false;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->rcFatal = VINF_SUCCESS;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->TarReader.enmPrevType= RTZIPTARTYPE_INVALID;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->TarReader.enmType = RTZIPTARTYPE_INVALID;
1a62088b18e24a01c1dc85e13d60468e78bd649dvboxsync pThis->TarReader.enmState = RTZIPTARREADERSTATE_FIRST;
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync /* Don't check if it's a TAR stream here, do that in the
43af8389304c77c3d4db525de8907cb74207c380vboxsync rtZipTarFss_Next. */
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync *phVfsFss = hVfsFss;
43af8389304c77c3d4db525de8907cb74207c380vboxsync return VINF_SUCCESS;
43af8389304c77c3d4db525de8907cb74207c380vboxsync }
43af8389304c77c3d4db525de8907cb74207c380vboxsync
43af8389304c77c3d4db525de8907cb74207c380vboxsync RTVfsIoStrmRelease(hVfsIosIn);
43af8389304c77c3d4db525de8907cb74207c380vboxsync return rc;
43af8389304c77c3d4db525de8907cb74207c380vboxsync}
43af8389304c77c3d4db525de8907cb74207c380vboxsync