tar.cpp revision 8328361b272002e2384c8264b0f64c69ee84a6c0
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * IPRT - Tar archive I/O.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2009-2010 Oracle Corporation
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The contents of this file may alternatively be used under the terms
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * of the Common Development and Distribution License Version 1.0
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * CDDL are applicable instead of those of the GPL.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * You may elect to license modified versions of this file under the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * terms and conditions of either the GPL or the CDDL or both.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Header Files *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Structures and Typedefs *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @name RTTARRECORD::h::linkflag
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define LF_OLDNORMAL '\0' /**< Normal disk file, Unix compatible */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define LF_LINK '1' /**< Link to previously dumped file */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * A tar file header.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char d[512];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncAssertCompileMemberOffset(RTTARRECORD, h.size, 100+8*3);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a tar file header. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if 0 /* not currently used */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a tar file handle. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct RTTARFILEINTERNAL *PRTTARFILEINTERNAL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The internal data of a tar handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The magic (RTTAR_MAGIC). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The handle to the tar file. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The open mode for hTarFile. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Whether a file within the archive is currently open for writing.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Only one can be open. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Whether operating in stream mode. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The file cache of one file. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a the internal data of a tar handle. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The internal data of a file within a tar file.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The magic (RTTARFILE_MAGIC). */
char *pszFilename;
if (!zero)
return VERR_TAR_END_OF_FILE;
return VINF_SUCCESS;
return VERR_TAR_END_OF_FILE;
return rc;
return rc;
return rc;
DECLINLINE(int) rtTarCreateHeaderRecord(PRTTARRECORD pRecord, const char *pszSrcName, uint64_t cbSize,
return rc;
return VINF_SUCCESS;
*pcbSize = 0;
if (!pvTmp)
return pvTmp;
if (!pvTmp)
return VERR_NO_MEMORY;
return rc;
DECLINLINE(PRTTARFILEINTERNAL) rtCreateTarFileInternal(PRTTARINTERNAL pInt, const char *pszFilename, uint32_t fOpen)
if (!pFileInt)
return NULL;
return NULL;
return pFileInt;
if (!pNewInt)
return NULL;
return NULL;
return pNewInt;
if (pInt)
static int rtTarExtractFileToFile(RTTARFILE hFile, const char *pszTargetName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
return rc;
if (!pvTmp)
if (pfnProgressCallback)
if (pvTmp)
return rc;
static int rtTarAppendFileFromFile(RTTAR hTar, const char *pszSrcName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
return rc;
if (!pvTmp)
if (pfnProgressCallback)
if (pvTmp)
if (hFile)
return rc;
if (offSeek > 0)
return rc;
bool fFound = false;
fFound = true;
&& !fFound)
return rc;
static int rtTarGetFilesOverallSize(RTFILE hFile, const char * const *papszFiles, size_t cFiles, uint64_t *pcbOverallSize)
++cFound;
return rc;
if (!pThis)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return rc;
return VERR_INVALID_HANDLE;
return VERR_INVALID_STATE;
return VERR_WRITE_PROTECT;
return VERR_TOO_MANY_OPEN_FILES;
if (!pFileInt)
return VERR_NO_MEMORY;
return rc;
return VINF_SUCCESS;
&& offCur < RT_ALIGN(pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD)))
uint64_t offNext = RT_ALIGN(pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD));
&record,
NULL);
rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart, &record, sizeof(RTTARRECORD), NULL);
return rc;
RTR3DECL(int) RTTarFileSeek(RTTARFILE hFile, uint64_t offSeek, unsigned uMethod, uint64_t *poffActual)
return VERR_INVALID_STATE;
switch (uMethod)
case RTFILE_SEEK_BEGIN:
return VERR_SEEK_ON_DEVICE;
case RTFILE_SEEK_CURRENT:
return VERR_SEEK_ON_DEVICE;
case RTFILE_SEEK_END:
return VERR_NEGATIVE_SEEK;
return VINF_SUCCESS;
RTR3DECL(int) RTTarFileReadAt(RTTARFILE hFile, uint64_t off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
if (pcbRead)
*pcbRead = 0;
int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->offStart + 512 + off, pvBuf, cbToCopy, &cbTmpRead);
if (pcbRead)
return rc;
RTR3DECL(int) RTTarFileWrite(RTTARFILE hFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
return VERR_WRITE_ERROR;
int rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart + 512 + off, pvBuf, cbToWrite, &cbTmpWritten);
if (pcbWritten)
return rc;
return VINF_SUCCESS;
return VERR_WRITE_ERROR;
return VINF_SUCCESS;
NULL);
return rc;
return VERR_WRITE_ERROR;
NULL);
NULL);
return rc;
return rc;
return VERR_WRITE_ERROR;
NULL);
NULL);
return rc;
return rc;
return VERR_WRITE_ERROR;
NULL);
return rc;
NULL);
return rc;
return rc;
int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);
return rc;
return rc;
int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);
return rc;
if (!papszFiles)
if (!pvNew)
cFiles++;
while (cFiles-- > 0)
return rc;
RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, size_t *pcbSize, const char *pszFile,
rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);
if (!pvTmp)
if (pfnProgressCallback)
&& pvTmp)
if (hFile)
if (hTar)
return rc;
RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles,
int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);
return rc;
if (pfnProgressCallback)
rc = RTTarFileOpen(hTar, &hFile, papszFiles[i], RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
if (pszTargetFile)
rc = rtTarExtractFileToFile(hFile, pszTargetFile, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser);
return rc;
RTR3DECL(int) RTTarExtractAll(const char *pszTarFile, const char *pszOutputDir, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
char **papszFiles;
return rc;
return RTTarExtractFiles(pszTarFile, pszOutputDir, papszFiles, cFiles, pfnProgressCallback, pvUser);
RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser)
int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_NONE, false /*fStream*/);
return rc;
if (pfnProgressCallback)
rc = rtTarAppendFileFromFile(hTar, papszFiles[i], cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser);
return rc;
int rc = RTTarFileOpenCurrentFile(hTar, &hFile, ppszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
return rc;
return VERR_INVALID_STATE;
return rc;
return VERR_INVALID_STATE;
uint64_t offNext = RT_ALIGN(pInt->pFileCache->offStart + sizeof(RTTARRECORD) + pInt->pFileCache->cbSize, sizeof(RTTARRECORD));
return rc;
RTR3DECL(int) RTTarFileOpenCurrentFile(RTTAR hTar, PRTTARFILE phFile, char **ppszFilename, uint32_t fOpen)
return VERR_INVALID_STATE;
if (ppszFilename)
return VINF_SUCCESS;
if (!pFileInt)
if (ppszFilename)
if (pFileInt)
return rc;