53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * IPRT - Manifest Utility.
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2010-2011 Oracle Corporation
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * available from http://www.virtualbox.org. This file is free software;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * you can redistribute it and/or modify it under the terms of the GNU
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * General Public License (GPL) as published by the Free Software
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * The contents of this file may alternatively be used under the terms
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * of the Common Development and Distribution License Version 1.0
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * VirtualBox OSE distribution, in which case the provisions of the
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * CDDL are applicable instead of those of the GPL.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * You may elect to license modified versions of this file under the
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * terms and conditions of either the GPL or the CDDL or both.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync/*******************************************************************************
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync* Header Files *
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync*******************************************************************************/
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Verify a manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @returns Program exit code, failures with error message.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pszManifest The manifest file. NULL if standard input.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param fStdFormat Whether to expect standard format (true) or
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * java format (false).
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pszChDir The directory to change into before processing
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * the files in the manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsyncstatic RTEXITCODE rtManifestDoVerify(const char *pszManifest, bool fStdFormat, const char *pszChDir)
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Open the manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT, RTFILE_O_READ, false /*fLeaveOpen*/, &hVfsIos);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to prepare standard input for reading: %Rrc", rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTVfsChainOpenIoStream(pszManifest, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, &hVfsIos, &pszError);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "Failed with %Rrc opening the input manifest '%s'", rc, pszManifest);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTManifestReadStandardEx(hManifest, hVfsIos, szErr, sizeof(szErr));
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Do the verification.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync /** @todo We're missing some enumeration APIs here! */
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("The manifest read fine, but the actual verification code is yet to be written. Sorry.");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync#if 1 /* For now, just write the manifest to stdout so we can test the read routine. */
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, false /*fLeaveOpen*/, &hVfsIosOut);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync else if (szErr[0])
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("Support for Java manifest files is not implemented yet");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Adds a file to the manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @returns IPRT status code, failures with error message.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param hManifest The manifest to add it to.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pszFilename The name of the file to add.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param fAttr The manifest attributes to add.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsyncstatic int rtManifestAddFileToManifest(RTMANIFEST hManifest, const char *pszFilename, uint32_t fAttr)
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync int rc = RTVfsChainOpenIoStream(pszFilename, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, &hVfsIos, &pszError);
36fed7bf894fc0880657eeaf16cc97bbc745b593vboxsync RTMsgError("RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
36fed7bf894fc0880657eeaf16cc97bbc745b593vboxsync RTMsgError("Failed with %Rrc opening '%s'", rc, pszFilename);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTManifestEntryAddIoStream(hManifest, hVfsIos, pszFilename, fAttr);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("RTManifestEntryAddIoStream failed for '%s': %Rrc", rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Create a manifest from the specified input files.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @returns Program exit code, failures with error message.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pszManifest The name of the output manifest file. NULL if
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * it should be written to standard output.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param fStdFormat Whether to expect standard format (true) or
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * java format (false).
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pszChDir The directory to change into before processing
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * the file arguments.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param fAttr The file attributes to put in the manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pGetState The RTGetOpt state.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param pUnion What the last RTGetOpt() call returned.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * @param chOpt What the last RTGetOpt() call returned.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsyncstatic RTEXITCODE rtManifestDoCreate(const char *pszManifest, bool fStdFormat, const char *pszChDir, uint32_t fAttr,
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync PRTGETOPTSTATE pGetState, PRTGETOPTUNION pUnion, int chOpt)
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Open the manifest file.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, false /*fLeaveOpen*/, &hVfsIos);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to prepare standard output for writing: %Rrc", rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTVfsChainOpenIoStream(pszManifest, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "Failed with %Rrc opening the manifest '%s'", rc, pszManifest);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Create the internal manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Change directory and start processing the specified files.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("Failed to change directory to '%s': %Rrc", pszChDir, rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = rtManifestAddFileToManifest(hManifest, pUnion->psz, fAttr);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Write the manifest.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("RTManifestWriteStandard failed: %Rrc", rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgError("Support for Java manifest files is not implemented yet");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Parse arguments.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync bool fVerify = false;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc", rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync while ( (rc = RTGetOpt(&GetState, &ValueUnion)) != 0
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync static struct
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync const char *pszAttr;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aAttributes); i++)
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync if (!RTStrICmp(s_aAttributes[i].pszAttr, ValueUnion.psz))
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown attribute type '%s'", ValueUnion.psz);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Only one manifest can be specified");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Only one directory change can be specified");
e078c42d830539a4c29a33b8f09fc28647686743vboxsync RTPrintf("Usage: %s [--manifest <file>] [--chdir <dir>] [--attribute <attrib-name> [..]] <files>\n"
e078c42d830539a4c29a33b8f09fc28647686743vboxsync " or %s --verify [--manifest <file>] [--chdir <dir>]\n"
e078c42d830539a4c29a33b8f09fc28647686743vboxsync "attrib-name: size, md5, sha1, sha256 or sha512\n"
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync * Take action.
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync RTMsgWarning("No files specified, the manifest will be empty.");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync | RTMANIFEST_ATTR_SHA1 | RTMANIFEST_ATTR_SHA256 | RTMANIFEST_ATTR_SHA512;
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync rcExit = rtManifestDoCreate(pszManifest, fStdFormat, pszChDir, fAttr, &GetState, &ValueUnion, rc);
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "No files should be specified when verifying a manifest (--verfiy), "
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "only a manifest via the --manifest option");
53ef3f0380481e398f8edd344fc07b4e5763ba65vboxsync "The --attribute (-a) option does not combine with --verify (-v)");