tarvfs.cpp revision 4e47bb772df0d04d1ded3e06354de547d52e2d06
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * IPRT - TAR Virtual Filesystem.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2010 Oracle Corporation
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * General Public License (GPL) as published by the Free Software
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * The contents of this file may alternatively be used under the terms
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * of the Common Development and Distribution License Version 1.0
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution, in which case the provisions of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * CDDL are applicable instead of those of the GPL.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * You may elect to license modified versions of this file under the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * terms and conditions of either the GPL or the CDDL or both.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Header Files *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync ******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Structures and Typedefs *
typedef enum RTZIPTARREADERSTATE
typedef struct RTZIPTARREADER
typedef struct RTZIPTARBASEOBJ
typedef struct RTZIPTARIOSTREAM
bool fEndOfStream;
typedef struct RTZIPTARFSSTREAM
bool fEndOfStream;
int rcFatal;
static int rtZipTarHdrFieldToNum(const char *pszField, size_t cchField, bool fOctalOnly, int64_t *pi64)
if ( fOctalOnly
unsigned char ch;
while (cchField > 0)
puchField++;
cchField--;
while (cchField > 0)
cchField--;
cchField--;
puchField++;
while (cchField-- > 0)
return VERR_TAR_NUM_VALUE_TOO_LARGE;
return VERR_TAR_NUM_VALUE_TOO_LARGE;
return VINF_SUCCESS;
if (pi32Signed)
return fZeroHdr;
return VERR_TAR_ZERO_HEADER;
int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum);
return VERR_TAR_BAD_CHKSUM_FIELD;
return VERR_TAR_CHKSUM_MISMATCH;
return VERR_TAR_NOT_USTAR_V00;
switch (enmType)
case RTZIPTARTYPE_POSIX:
return VERR_TAR_UNKNOWN_TYPE_FLAG;
case RTZIPTARTYPE_GNU:
case RTZIPTAR_TF_OLDNORMAL:
case RTZIPTAR_TF_NORMAL:
case RTZIPTAR_TF_CONTIG:
case RTZIPTAR_TF_DIR:
case RTZIPTAR_TF_CHR:
case RTZIPTAR_TF_BLK:
case RTZIPTAR_TF_LINK:
case RTZIPTAR_TF_SYMLINK:
case RTZIPTAR_TF_FIFO:
case RTZIPTAR_TF_GNU_LONGLINK:
case RTZIPTAR_TF_GNU_LONGNAME:
case RTZIPTAR_TF_GNU_DUMPDIR:
case RTZIPTAR_TF_GNU_MULTIVOL:
case RTZIPTAR_TF_GNU_SPARSE:
case RTZIPTAR_TF_GNU_VOLDHR:
return VERR_TAR_UNKNOWN_TYPE_FLAG;
case RTZIPTARTYPE_ANCIENT:
case RTZIPTAR_TF_OLDNORMAL:
case RTZIPTAR_TF_NORMAL:
case RTZIPTAR_TF_CONTIG:
case RTZIPTAR_TF_DIR:
case RTZIPTAR_TF_LINK:
case RTZIPTAR_TF_SYMLINK:
case RTZIPTAR_TF_FIFO:
return VERR_TAR_UNKNOWN_TYPE_FLAG;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
return rc;
if (fFirst)
case RTZIPTAR_TF_OLDNORMAL:
case RTZIPTAR_TF_NORMAL:
case RTZIPTAR_TF_CONTIG:
case RTZIPTAR_TF_LINK:
case RTZIPTAR_TF_SYMLINK:
case RTZIPTAR_TF_CHR:
case RTZIPTAR_TF_BLK:
case RTZIPTAR_TF_FIFO:
case RTZIPTAR_TF_DIR:
return VERR_TAR_EMPTY_NAME;
rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix));
rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name));
case RTZIPTAR_TF_X_HDR:
case RTZIPTAR_TF_X_GLOBAL:
return VERR_TAR_UNSUPPORTED_PAX_TYPE;
case RTZIPTAR_TF_SOLARIS_XHDR:
case RTZIPTAR_TF_GNU_LONGNAME:
case RTZIPTAR_TF_GNU_LONGLINK:
return VERR_TAR_MALFORMED_GNU_LONGXXXX;
return VERR_TAR_MALFORMED_GNU_LONGXXXX;
return VERR_TAR_NAME_TOO_LONG;
case RTZIPTAR_TF_GNU_DUMPDIR:
case RTZIPTAR_TF_GNU_MULTIVOL:
case RTZIPTAR_TF_GNU_SPARSE:
case RTZIPTAR_TF_GNU_VOLDHR:
return VERR_TAR_UNKNOWN_TYPE_FLAG;
return VINF_SUCCESS;
case RTZIPTARREADERSTATE_ZERO:
return VERR_TAR_ZERO_HEADER;
return VINF_SUCCESS;
return VERR_TAR_ZERO_HEADER;
return VERR_TAR_MALFORMED_GNU_LONGXXXX;
return VERR_TAR_MALFORMED_GNU_LONGXXXX;
char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget;
return VINF_SUCCESS;
return VERR_INTERNAL_ERROR_5;
int rc;
return rc; \
return VERR_TAR_NUM_VALUE_TOO_LARGE; \
return VERR_TAR_NUM_VALUE_TOO_LARGE;
case RTZIPTARTYPE_POSIX:
case RTZIPTARTYPE_GNU:
return VERR_TAR_DEV_VALUE_TOO_LARGE;
return VERR_TAR_UNKNOWN_TYPE_FLAG;
return VERR_TAR_BAD_MODE_FIELD;
case RTZIPTAR_TF_OLDNORMAL:
case RTZIPTAR_TF_NORMAL:
case RTZIPTAR_TF_CONTIG:
case RTZIPTAR_TF_LINK:
return VERR_TAR_SIZE_NOT_ZERO;
case RTZIPTAR_TF_SYMLINK:
case RTZIPTAR_TF_CHR:
case RTZIPTAR_TF_BLK:
case RTZIPTAR_TF_DIR:
case RTZIPTAR_TF_FIFO:
case RTZIPTAR_TF_GNU_LONGLINK:
case RTZIPTAR_TF_GNU_LONGNAME:
switch (fModeType)
case RTFS_TYPE_FILE:
case RTFS_TYPE_DIRECTORY:
case RTFS_TYPE_SYMLINK:
case RTFS_TYPE_DEV_BLOCK:
case RTFS_TYPE_DEV_CHAR:
case RTFS_TYPE_FIFO:
return VERR_TAR_MODE_WITH_TYPE;
case RTZIPTAR_TF_CHR:
case RTZIPTAR_TF_BLK:
case RTZIPTAR_TF_DIR:
case RTZIPTAR_TF_FIFO:
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(int) rtZipTarFssBaseObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
switch (enmAddAttr)
case RTFSOBJATTRADD_NOTHING:
case RTFSOBJATTRADD_UNIX:
case RTFSOBJATTRADD_EASIZE:
return VERR_NOT_SUPPORTED;
return VINF_SUCCESS;
static DECLCALLBACK(int) rtZipTarFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
static int rtZipTarFssIos_ReadOneSeg(PRTZIPTARIOSTREAM pThis, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead)
if (!pcbRead)
return VERR_EOF;
if (!pcbRead)
return rc;
static DECLCALLBACK(int) rtZipTarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
int rc;
rc = rtZipTarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead);
cbReadSeg = 0;
rc = rtZipTarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg);
if (pcbRead)
if (pcbRead)
return rc;
static DECLCALLBACK(int) rtZipTarFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
static DECLCALLBACK(int) rtZipTarFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(int) rtZipTarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
return VERR_ACCESS_DENIED;
static DECLCALLBACK(int) rtZipTarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
return VERR_ACCESS_DENIED;
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
static DECLCALLBACK(int) rtZipTarFss_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
static DECLCALLBACK(int) rtZipTarFss_Next(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj)
return VERR_EOF;
while ( offHdr >= 0
if (offHdr < 0)
int rc;
switch (fType)
case RTFS_TYPE_FILE:
sizeof(*pIosData),
&hVfsIos,
(void **)&pIosData);
case RTFS_TYPE_SYMLINK:
sizeof(*pBaseObjData),
&hVfsSym,
(void **)&pBaseObjData);
case RTFS_TYPE_DEV_BLOCK:
case RTFS_TYPE_DEV_CHAR:
case RTFS_TYPE_DIRECTORY:
case RTFS_TYPE_FIFO:
sizeof(*pBaseObjData),
&hVfsObj,
(void **)&pBaseObjData);
AssertFailed();
if (ppszName)
return rc;
if (phVfsObj)
if (penmType)
return VINF_SUCCESS;
RTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss)
int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis);
return VINF_SUCCESS;
return rc;