RTManifest.cpp revision 53ef3f0380481e398f8edd344fc07b4e5763ba65
/* $Id$ */
/** @file
* IPRT - Manifest Utility.
*/
/*
* Copyright (C) 2010 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 *
*******************************************************************************/
#include <iprt/manifest.h>
#include <iprt/buildconfig.h>
#include <iprt/initterm.h>
/**
* Verify a manifest.
*
* @returns Program exit code, failures with error message.
* @param pszManifest The manifest file. NULL if standard input.
* @param fStdFormat Whether to expect standard format (true) or
* java format (false).
* @param pszChDir The directory to change into before processing
* the files in the manifest.
*/
static RTEXITCODE rtManifestDoVerify(const char *pszManifest, bool fStdFormat, const char *pszChDir)
{
/*
* Open the manifest.
*/
int rc;
if (!pszManifest)
{
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to prepare standard input for reading: %Rrc", rc);
}
else
{
const char *pszError;
rc = RTVfsChainOpenIoStream(pszManifest, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, &hVfsIos, &pszError);
if (RT_FAILURE(rc))
{
return RTMsgErrorExit(RTEXITCODE_FAILURE,
"RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
" '%s'\n",
" %*s^\n",
return RTMsgErrorExit(RTEXITCODE_FAILURE,
}
}
/*
* Read it.
*/
if (RT_SUCCESS(rc))
{
if (fStdFormat)
{
if (RT_SUCCESS(rc))
{
/*
* Do the verification.
*/
/** @todo We're missing some enumeration APIs here! */
RTMsgError("The manifest read fine, but the actual verification code is yet to be written. Sorry.");
#if 1 /* For now, just write the manifest to stdout so we can test the read routine. */
rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, false /*fLeaveOpen*/, &hVfsIosOut);
if (RT_SUCCESS(rc))
{
}
#endif
}
else if (szErr[0])
else
}
else
{
RTMsgError("Support for Java manifest files is not implemented yet");
}
}
}
/**
* Adds a file to the manifest.
*
* @returns IPRT status code, failures with error message.
* @param hManifest The manifest to add it to.
* @param pszFilename The name of the file to add.
* @param fAttr The manifest attributes to add.
*/
static int rtManifestAddFileToManifest(RTMANIFEST hManifest, const char *pszFilename, uint32_t fAttr)
{
const char *pszError;
int rc = RTVfsChainOpenIoStream(pszFilename, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, &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 rc;
}
/**
* Create a manifest from the specified input files.
*
* @returns Program exit code, failures with error message.
* @param pszManifest The name of the output manifest file. NULL if
* it should be written to standard output.
* @param fStdFormat Whether to expect standard format (true) or
* java format (false).
* @param pszChDir The directory to change into before processing
* the file arguments.
* @param fAttr The file attributes to put in the manifest.
* @param pGetState The RTGetOpt state.
* @param pUnion What the last RTGetOpt() call returned.
* @param chOpt What the last RTGetOpt() call returned.
*/
static RTEXITCODE rtManifestDoCreate(const char *pszManifest, bool fStdFormat, const char *pszChDir, uint32_t fAttr,
{
/*
* Open the manifest file.
*/
int rc;
if (!pszManifest)
{
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to prepare standard output for writing: %Rrc", rc);
}
else
{
const char *pszError;
rc = RTVfsChainOpenIoStream(pszManifest, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
if (RT_FAILURE(rc))
{
return RTMsgErrorExit(RTEXITCODE_FAILURE,
"RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
" '%s'\n",
" %*s^\n",
return RTMsgErrorExit(RTEXITCODE_FAILURE,
}
}
/*
* Create the internal manifest.
*/
if (RT_SUCCESS(rc))
{
/*
* Change directory and start processing the specified files.
*/
if (pszChDir)
{
if (RT_FAILURE(rc))
}
if (RT_SUCCESS(rc))
{
while (chOpt == VINF_GETOPT_NOT_OPTION)
{
if (RT_FAILURE(rc))
break;
/* next */
}
{
}
}
/*
* Write the manifest.
*/
if (RT_SUCCESS(rc))
{
if (fStdFormat)
{
if (RT_FAILURE(rc))
}
else
{
RTMsgError("Support for Java manifest files is not implemented yet");
}
}
}
}
{
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
/*
* Parse arguments.
*/
static RTGETOPTDEF const s_aOptions[] =
{
};
bool fVerify = false;
bool fStdFormat = true;
const char *pszManifest = NULL;
rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
if (RT_FAILURE(rc))
&& rc != VINF_GETOPT_NOT_OPTION)
{
switch (rc)
{
case 'a':
{
static struct
{
const char *pszAttr;
} s_aAttributes[] =
{
{ "size", RTMANIFEST_ATTR_SIZE },
{ "md5", RTMANIFEST_ATTR_MD5 },
{ "sha1", RTMANIFEST_ATTR_SHA1 },
{ "sha256", RTMANIFEST_ATTR_SHA256 },
{ "sha512", RTMANIFEST_ATTR_SHA512 }
};
for (unsigned i = 0; i < RT_ELEMENTS(s_aAttributes); i++)
{
break;
}
if (fThisAttr == RTMANIFEST_ATTR_UNKNOWN)
if (fAttr == RTMANIFEST_ATTR_UNKNOWN)
else
break;
}
case 'j':
fStdFormat = false;
break;
case 'm':
if (pszManifest)
break;
case 'v':
fVerify = true;
break;
case 'C':
if (pszChDir)
break;
case 'h':
RTMsgInfo("Usage: %s [--manifest <file>] [--chdir <dir>] [--attribute <attrib-name> [..]] <files>\n"
" or %s --verify [--manifest <file>] [--chdir <dir>]\n"
"\n"
"attrib-name: size, md5, sha1, sha256 or sha512\n"
return RTEXITCODE_SUCCESS;
case 'V':
return RTEXITCODE_SUCCESS;
default:
}
}
/*
* Take action.
*/
if (!fVerify)
{
if (rc != VINF_GETOPT_NOT_OPTION)
RTMsgWarning("No files specified, the manifest will be empty.");
if (fAttr == RTMANIFEST_ATTR_UNKNOWN)
}
else
{
if (rc == VINF_GETOPT_NOT_OPTION)
return RTMsgErrorExit(RTEXITCODE_SYNTAX,
"No files should be specified when verifying a manifest (--verfiy), "
"only a manifest via the --manifest option");
if (fAttr != RTMANIFEST_ATTR_UNKNOWN)
return RTMsgErrorExit(RTEXITCODE_SYNTAX,
"The --attribute (-a) option does not combine with --verify (-v)");
}
return rcExit;
}