unzipcmd.cpp revision df9eb29d4fc657eb85ce9b3762d564738e952412
/* $Id$ */
/** @file
* IPRT - A mini UNZIP Command.
*/
/*
* Copyright (C) 2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* IPRT UNZIP option structure.
*/
typedef struct RTZIPUNZIPCMDOPS
{
/** The operation. */
int iOperation;
/** The long operation option name. */
const char *pszOperation;
/** The directory to change into when upacking. */
const char *pszDirectory;
/** The unzip file name. */
const char *pszFile;
/** The number of files/directories to be extracted from archive specified. */
/** Wether we're verbose or quiet. */
bool fVerbose;
/** Skip the restauration of the modification time for directories. */
bool fNoModTimeDirectories;
/** Skip the restauration of the modification time for files. */
bool fNoModTimeFiles;
/** Array of files/directories, terminated by a NULL entry. */
const char * const *papszFiles;
/** Pointer to the IPRT tar options. */
typedef RTZIPUNZIPCMDOPS *PRTZIPUNZIPCMDOPS;
/**
* Callback used by rtZipTarDoWithMembers
*
* @returns rcExit or RTEXITCODE_FAILURE.
* @param pOpts The tar options.
* @param hVfsObj The tar object to display
* @param pszName The name.
* @param rcExit The current exit code.
*/
typedef RTEXITCODE (*PFNDOWITHMEMBER)(PRTZIPUNZIPCMDOPS pOpts, RTVFSOBJ hVfsObj, const char *pszName, RTEXITCODE rcExit, PRTFOFF pcBytes);
/**
*
*/
{
/*
* Query all the information.
*/
if (RT_FAILURE(rc))
RTPrintf("%9RU64 %04d-%02d-%02d %02d:%02d %s\n",
pszName);
return rcExit;
}
/**
* Extracts a file.
*/
static RTEXITCODE rtZipUnzipCmdExtractFile(PRTZIPUNZIPCMDOPS pOpts, RTVFSOBJ hVfsObj, RTEXITCODE rcExit,
{
/*
* Open the destination file and create a stream object for it.
*/
uint32_t fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_ACCESS_ATTR_DEFAULT
if (RT_FAILURE(rc))
if (RT_SUCCESS(rc))
{
/*
* Pump the data thru.
*/
if (RT_SUCCESS(rc))
{
/*
* Correct the file mode and other attributes.
*/
if (!pOpts->fNoModTimeFiles)
{
if (RT_FAILURE(rc))
}
}
else
}
else
rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error creating I/O stream for file: %Rrc", pszDst, rc);
return rcExit;
}
/**
*
*/
{
/*
* Query all the information.
*/
if (RT_FAILURE(rc))
char szDst[RTPATH_MAX];
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to construct destination path for: %Rrc", pszName, rc);
/*
* Extract according to the type.
*/
{
case RTFS_TYPE_FILE:
case RTFS_TYPE_DIRECTORY:
if (RT_FAILURE(rc))
break;
default:
}
if (!pOpts->fNoModTimeDirectories)
{
rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error changing modification time: %Rrc.", pszName, rc);
}
return rcExit;
}
/**
* Checks if @a pszName is a member of @a papszNames, optionally returning the
* index.
*
* @returns true if the name is in the list, otherwise false.
* @param pszName The name to find.
* @param papszNames The array of names.
* @param piName Where to optionally return the array index.
*/
static bool rtZipUnzipCmdIsNameInArray(const char *pszName, const char * const *papszNames, uint32_t *piName)
{
{
if (piName)
return true;
}
return false;
}
/**
* Opens the input archive specified by the options.
*
* @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + printed message.
* @param pOpts The options.
* @param phVfsFss Where to return the UNZIP filesystem stream handle.
*/
{
/*
* Open the input file.
*/
const char *pszError;
&hVfsIos,
&pszError);
if (RT_FAILURE(rc))
{
return RTMsgErrorExit(RTEXITCODE_FAILURE,
"RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
" '%s'\n",
" %*s^\n",
return RTMsgErrorExit(RTEXITCODE_FAILURE,
}
if (RT_FAILURE(rc))
return RTEXITCODE_SUCCESS;
}
/**
* Worker for the --list and --extract commands.
*
* @returns The appropriate exit code.
* @param pOpts The tar options.
* @param pfnCallback The command specific callback.
*/
{
/*
* Allocate a bitmap to go with the file list. This will be used to
* indicate which files we've processed and which not.
*/
{
if (!pbmFound)
}
/*
* Open the input archive.
*/
if (rcExit == RTEXITCODE_SUCCESS)
{
/*
* Process the stream.
*/
for (;;)
{
/*
* Retrieve the next object.
*/
char *pszName;
if (RT_FAILURE(rc))
{
break;
}
/*
* Should we process this object?
*/
{
if (pbmFound)
cFiles++;
}
/*
* Release the current object and string.
*/
}
/*
* Complain about any files we didn't find.
*/
{
}
}
return RTEXITCODE_SUCCESS;
}
{
/*
* Parse the command line.
*/
static const RTGETOPTDEF s_aOptions[] =
{
/* options */
/* modifiers */
(and files) */
};
if (RT_FAILURE(rc))
&& rc != VINF_GETOPT_NOT_OPTION)
{
switch (rc)
{
case 'd':
if (Opts.pszDirectory)
break;
case 'D':
if (!Opts.fNoModTimeDirectories)
else
break;
case 'l':
case 't': /* treat 'test' like 'list' */
if (Opts.iOperation)
return RTMsgErrorExit(RTEXITCODE_SYNTAX,
"Conflicting unzip operation (%s already set, now %s)",
break;
case 'v':
break;
default:
}
}
if (rc == VINF_GETOPT_NOT_OPTION)
{
{
}
}
switch (Opts.iOperation)
{
case 'l':
{
RTPrintf(" Length Date Time Name\n"
"--------- ---------- ----- ----\n");
RTPrintf("--------- -------\n"
"%9RU64 %u file%s\n",
return rcExit;
}
default:
}
return RTEXITCODE_SUCCESS;
}