Exemple #1
0
/**
 * Opens the output file.
 *
 * @returns Command exit, error messages written using RTMsg*.
 *
 * @param   pszFile             The input filename.
 * @param   pOpts               The options, szOutput will be filled in by this
 *                              function on success.
 * @param   phVfsIos            Where to return the output stream handle.
 *
 * @remarks This is actually not quite the way we need to do things.
 *
 *          First of all, we need a GZIP file system stream for a real GZIP
 *          implementation, since there may be more than one file in the gzipped
 *          file.
 *
 *          Second, we need to open the output files as we encounter files in the input
 *          file system stream. The gzip format contains timestamp and usually a
 *          filename, the default is to use this name (see the --no-name
 *          option).
 */
static RTEXITCODE gzipOpenOutput(const char *pszFile, PRTGZIPCMDOPTS pOpts, PRTVFSIOSTREAM phVfsIos)
{
    int rc;
    if (!strcmp(pszFile, "-") || pOpts->fStdOut)
    {
        strcpy(pOpts->szOutput, "-");

        if (   !pOpts->fForce
            && !pOpts->fDecompress
            && gzipIsStdHandleATty(RTHANDLESTD_OUTPUT))
            return RTMsgErrorExit(RTEXITCODE_SYNTAX,
                                  "Yeah, right. I'm not writing any compressed data to the terminal without --force.\n");

        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT,
                                      RTFILE_O_WRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE,
                                      true /*fLeaveOpen*/,
                                      phVfsIos);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening standard output: %Rrc", rc);
    }
    else
    {
        Assert(!RTVfsChainIsSpec(pszFile));

        /* Construct an output filename. */
        rc = RTStrCopy(pOpts->szOutput, sizeof(pOpts->szOutput), pszFile);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing output filename: %Rrc", rc);
        if (pOpts->fDecompress)
        {
            /** @todo take filename from archive? */
            size_t cchSuff = strlen(pOpts->pszSuff); Assert(cchSuff > 0);
            size_t cch = strlen(pOpts->szOutput);
            if (   cch <= cchSuff
                || strcmp(&pOpts->szOutput[cch - cchSuff], pOpts->pszSuff))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Input file does not end with: '%s'", pOpts->pszSuff);
            pOpts->szOutput[cch - cchSuff] = '\0';
            if (!RTPathFilename(pOpts->szOutput))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing output filename: Input file name is all suffix.");
        }
        else
        {
            rc = RTStrCat(pOpts->szOutput, sizeof(pOpts->szOutput), pOpts->pszSuff);
            if (RT_FAILURE(rc))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing output filename: %Rrc", rc);
        }

        /* Open the output file. */
        uint32_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_WRITE;
        if (pOpts->fForce)
            fOpen |= RTFILE_O_CREATE_REPLACE;
        else
            fOpen |= RTFILE_O_CREATE;
        rc = RTVfsIoStrmOpenNormal(pOpts->szOutput, fOpen, phVfsIos);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening output file '%s': %Rrc", pOpts->szOutput, rc);
    }

    return RTEXITCODE_SUCCESS;
}
Exemple #2
0
static void tstVfsIoFromStandardHandle(RTTEST hTest, RTHANDLESTD enmHandle)
{
    RTTestSubF(hTest, "RTVfsIoStrmFromStdHandle(%s)", StandardHandleToString(enmHandle));

    RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM;
    int rc = RTVfsIoStrmFromStdHandle(enmHandle, 0, true /*fLeaveOpen*/, &hVfsIos);
    if (RT_SUCCESS(rc))
    {
        if (   enmHandle == RTHANDLESTD_OUTPUT
            || enmHandle == RTHANDLESTD_ERROR)
        {
            char szTmp[80];
            size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "Test output to %s\n", StandardHandleToString(enmHandle));

            size_t cbWritten;
            RTTESTI_CHECK_RC(rc = RTVfsIoStrmWrite(hVfsIos, szTmp, cchTmp, true /*fBlocking*/, &cbWritten), VINF_SUCCESS);
            if (RT_SUCCESS(rc))
                RTTESTI_CHECK(cbWritten == cchTmp);
        }

        uint32_t cRefs = RTVfsIoStrmRelease(hVfsIos);
        RTTESTI_CHECK_MSG(cRefs == 0, ("cRefs=%#x\n", cRefs));
    }
    else
        RTTestFailed(hTest, "Error creating VFS I/O stream for %s: %Rrc\n", StandardHandleToString(enmHandle), rc);
}
/**
 * Opens the input file.
 *
 * @returns Command exit, error messages written using RTMsg*.
 *
 * @param   pszFile             The input filename.
 * @param   pOpts               The options, szOutput will be filled in by this
 *                              function on success.
 * @param   phVfsIos            Where to return the input stream handle.
 */
static RTEXITCODE gzipOpenInput(const char *pszFile, PRTGZIPCMDOPTS pOpts, PRTVFSIOSTREAM phVfsIos)
{
    int rc;

    pOpts->pszInput = pszFile;
    if (!strcmp(pszFile, "-"))
    {
        if (   !pOpts->fForce
            && pOpts->fDecompress
            && gzipIsStdHandleATty(RTHANDLESTD_OUTPUT))
            return RTMsgErrorExit(RTEXITCODE_SYNTAX,
                                  "Yeah, right. I'm not reading any compressed data from the terminal without --force.\n");

        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT,
                                      RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE,
                                      true /*fLeaveOpen*/,
                                      phVfsIos);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening standard input: %Rrc", rc);
    }
    else
    {
        uint32_t        offError = 0;
        RTERRINFOSTATIC ErrInfo;
        rc = RTVfsChainOpenIoStream(pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE,
                                    phVfsIos, &offError, RTErrInfoInitStatic(&ErrInfo));
        if (RT_FAILURE(rc))
            return RTVfsChainMsgErrorExitFailure("RTVfsChainOpenIoStream", pszFile, rc, offError, &ErrInfo.Core);
    }

    return RTEXITCODE_SUCCESS;

}
Exemple #4
0
/**
 * Opens the input file.
 *
 * @returns Command exit, error messages written using RTMsg*.
 *
 * @param   pszFile             The input filename.
 * @param   pOpts               The options, szOutput will be filled in by this
 *                              function on success.
 * @param   phVfsIos            Where to return the input stream handle.
 */
static RTEXITCODE gzipOpenInput(const char *pszFile, PRTGZIPCMDOPTS pOpts, PRTVFSIOSTREAM phVfsIos)
{
    int rc;

    pOpts->pszInput = pszFile;
    if (!strcmp(pszFile, "-"))
    {
        if (   !pOpts->fForce
            && pOpts->fDecompress
            && gzipIsStdHandleATty(RTHANDLESTD_OUTPUT))
            return RTMsgErrorExit(RTEXITCODE_SYNTAX,
                                  "Yeah, right. I'm not reading any compressed data from the terminal without --force.\n");

        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT,
                                      RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE,
                                      true /*fLeaveOpen*/,
                                      phVfsIos);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening standard input: %Rrc", rc);
    }
    else
    {
        const char *pszError;
        rc = RTVfsChainOpenIoStream(pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, phVfsIos, &pszError);
        if (RT_FAILURE(rc))
        {
            if (pszError && *pszError)
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                      "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
                                      "    '%s'\n"
                                      "     %*s^\n",
                                      rc, pszFile, pszError - pszFile, "");
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "RTVfsChainOpenIoStream failed with rc=%Rrc: '%s'",
                                  rc, pszFile);
        }
    }

    return RTEXITCODE_SUCCESS;

}
Exemple #5
0
int main(int argc, char **argv)
{
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * Create a HTTP client instance.
     */
    RTHTTP hHttp;
    rc = RTHttpCreate(&hHttp);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTHttpCreate failed: %Rrc", rc);

    /*
     * Parse arguments.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--output",       'o', RTGETOPT_REQ_STRING },
        { "--quiet",        'q', RTGETOPT_REQ_NOTHING },
        { "--verbose",      'v', RTGETOPT_REQ_NOTHING },
    };

    RTEXITCODE      rcExit          = RTEXITCODE_SUCCESS;
    const char     *pszOutput       = NULL;
    unsigned        uVerbosityLevel = 1;

    RTGETOPTUNION   ValueUnion;
    RTGETOPTSTATE   GetState;
    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (rc)
        {
            case 'o':
                pszOutput = ValueUnion.psz;
                break;

            case 'q':
                uVerbosityLevel--;
                break;
            case 'v':
                uVerbosityLevel++;
                break;

            case 'h':
                RTPrintf("Usage: %s [options] URL0 [URL1 [...]]\n"
                         "\n"
                         "Options:\n"
                         "  -o,--output=file\n"
                         "      Output file. If not given, the file is displayed on stdout.\n"
                         "  -q, --quiet\n"
                         "  -v, --verbose\n"
                         "      Controls the verbosity level.\n"
                         "  -h, -?, --help\n"
                         "      Display this help text and exit successfully.\n"
                         "  -V, --version\n"
                         "      Display the revision and exit successfully.\n"
                         , RTPathFilename(argv[0]));
                return RTEXITCODE_SUCCESS;

            case 'V':
                RTPrintf("$Revision: 102641 $\n");
                return RTEXITCODE_SUCCESS;

            case VINF_GETOPT_NOT_OPTION:
            {
                int rcHttp;
                if (pszOutput && strcmp("-", pszOutput))
                {
                    if (uVerbosityLevel > 0)
                        RTStrmPrintf(g_pStdErr, "Fetching '%s' into '%s'...\n", ValueUnion.psz, pszOutput);
                    rcHttp = RTHttpGetFile(hHttp, ValueUnion.psz, pszOutput);
                }
                else
                {
                    if (uVerbosityLevel > 0)
                        RTStrmPrintf(g_pStdErr, "Fetching '%s'...\n", ValueUnion.psz);

                    void  *pvResp;
                    size_t cbResp;
                    rcHttp = RTHttpGetBinary(hHttp, ValueUnion.psz, &pvResp, &cbResp);
                    if (RT_SUCCESS(rcHttp))
                    {
                        RTVFSIOSTREAM hVfsIos;
                        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, 0, true /*fLeaveOpen*/, &hVfsIos);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTVfsIoStrmWrite(hVfsIos, pvResp, cbResp, true /*fBlocking*/, NULL);
                            if (RT_FAILURE(rc))
                                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error writing to stdout: %Rrc", rc);
                            RTVfsIoStrmRelease(hVfsIos);
                        }
                        else
                            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening stdout: %Rrc", rc);
                        RTHttpFreeResponse(pvResp);
                    }
                }
                if (RT_FAILURE(rcHttp))
                    rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error %Rrc getting '%s'", rcHttp, ValueUnion.psz);
                break;
            }

            default:
                return RTGetOptPrintError(rc, &ValueUnion);
        }
    }

    return rcExit;
}
Exemple #6
0
/**
 * 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 TAR filesystem stream handle.
 */
static RTEXITCODE rtZipTarCmdOpenInputArchive(PRTZIPTARCMDOPS pOpts, PRTVFSFSSTREAM phVfsFss)
{
    int rc;

    /*
     * Open the input file.
     */
    RTVFSIOSTREAM   hVfsIos;
    if (   pOpts->pszFile
        && strcmp(pOpts->pszFile, "-") != 0)
    {
        const char *pszError;
        rc = RTVfsChainOpenIoStream(pOpts->pszFile,
                                    RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN,
                                    &hVfsIos,
                                    &pszError);
        if (RT_FAILURE(rc))
        {
            if (pszError && *pszError)
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                      "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
                                      "    '%s'\n",
                                      "     %*s^\n",
                                      rc, pOpts->pszFile, pszError - pOpts->pszFile, "");
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "Failed with %Rrc opening the input archive '%s'", rc, pOpts->pszFile);
        }
    }
    else
    {
        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT,
                                      RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN,
                                      true /*fLeaveOpen*/,
                                      &hVfsIos);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to prepare standard in for reading: %Rrc", rc);
    }

    /*
     * Pass it thru a decompressor?
     */
    RTVFSIOSTREAM hVfsIosDecomp = NIL_RTVFSIOSTREAM;
    switch (pOpts->chZipper)
    {
        /* no */
        case '\0':
            rc = VINF_SUCCESS;
            break;

        /* gunzip */
        case 'z':
            rc = RTZipGzipDecompressIoStream(hVfsIos, 0 /*fFlags*/, &hVfsIosDecomp);
            if (RT_FAILURE(rc))
                RTMsgError("Failed to open gzip decompressor: %Rrc", rc);
            break;

        /* bunzip2 */
        case 'j':
            rc = VERR_NOT_SUPPORTED;
            RTMsgError("bzip2 is not supported by this build");
            break;

        /* bug */
        default:
            rc = VERR_INTERNAL_ERROR_2;
            RTMsgError("unknown decompression method '%c'",  pOpts->chZipper);
            break;
    }
    if (RT_FAILURE(rc))
    {
        RTVfsIoStrmRelease(hVfsIos);
        return RTEXITCODE_FAILURE;
    }

    if (hVfsIosDecomp != NIL_RTVFSIOSTREAM)
    {
        RTVfsIoStrmRelease(hVfsIos);
        hVfsIos = hVfsIosDecomp;
        hVfsIosDecomp = NIL_RTVFSIOSTREAM;
    }

    /*
     * Open the filesystem stream.
     */
    if (pOpts->enmFormat == RTZIPTARFORMAT_TAR)
        rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss);
    else if (pOpts->enmFormat == RTZIPTARFORMAT_XAR)
#ifdef IPRT_WITH_XAR /* Requires C++ and XML, so only in some configruation of IPRT. */
        rc = RTZipXarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss);
#else
        rc = VERR_NOT_SUPPORTED;
#endif
    else /** @todo make RTZipTarFsStreamFromIoStream fail if not tar file! */
Exemple #7
0
/**
 * Verifies the manifest and its signature.
 *
 * @returns VBox status code, failures with message.
 * @param   hOurManifest    The manifest we compiled.
 * @param   hManifestFile   The manifest file in the extension pack.
 * @param   hSignatureFile  The manifest signature file.
 * @param   pszError            Where to store an error message on failure.
 * @param   cbError             The size of the buffer @a pszError points to.
 */
static int vboxExtPackVerifyManifestAndSignature(RTMANIFEST hOurManifest, RTVFSFILE hManifestFile, RTVFSFILE hSignatureFile,
                                                 char *pszError, size_t cbError)
{
    /*
     * Read the manifest from the extension pack.
     */
    int rc = RTVfsFileSeek(hManifestFile, 0, RTFILE_SEEK_BEGIN, NULL);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsFileSeek failed: %Rrc", rc);

    RTMANIFEST hTheirManifest;
    rc = RTManifestCreate(0 /*fFlags*/, &hTheirManifest);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "RTManifestCreate failed: %Rrc", rc);

    RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hManifestFile);
    rc = RTManifestReadStandard(hTheirManifest, hVfsIos);
    RTVfsIoStrmRelease(hVfsIos);
    if (RT_SUCCESS(rc))
    {
        /*
         * Compare the manifests.
         */
        static const char *s_apszIgnoreEntries[] =
        {
            VBOX_EXTPACK_MANIFEST_NAME,
            VBOX_EXTPACK_SIGNATURE_NAME,
            "./" VBOX_EXTPACK_MANIFEST_NAME,
            "./" VBOX_EXTPACK_SIGNATURE_NAME,
            NULL
        };
        char szError[RTPATH_MAX];
        rc = RTManifestEqualsEx(hOurManifest, hTheirManifest, &s_apszIgnoreEntries[0], NULL,
                                RTMANIFEST_EQUALS_IGN_MISSING_ATTRS /*fFlags*/,
                                szError, sizeof(szError));
        if (RT_SUCCESS(rc))
        {
            /*
             * Validate the manifest file signature.
             */
            /** @todo implement signature stuff */
            NOREF(hSignatureFile);

        }
        else if (rc == VERR_NOT_EQUAL && szError[0])
            vboxExtPackSetError(pszError, cbError, "Manifest mismatch: %s", szError);
        else
            vboxExtPackSetError(pszError, cbError, "RTManifestEqualsEx failed: %Rrc", rc);
#if 0
        RTVFSIOSTREAM hVfsIosStdOut = NIL_RTVFSIOSTREAM;
        RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, true, &hVfsIosStdOut);
        RTVfsIoStrmWrite(hVfsIosStdOut, "Our:\n", sizeof("Our:\n") - 1, true, NULL);
        RTManifestWriteStandard(hOurManifest, hVfsIosStdOut);
        RTVfsIoStrmWrite(hVfsIosStdOut, "Their:\n", sizeof("Their:\n") - 1, true, NULL);
        RTManifestWriteStandard(hTheirManifest, hVfsIosStdOut);
#endif
    }
    else
        vboxExtPackSetError(pszError, cbError, "Error parsing '%s': %Rrc", VBOX_EXTPACK_MANIFEST_NAME, rc);

    RTManifestRelease(hTheirManifest);
    return rc;
}
/**
 * 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;
    RTVFSIOSTREAM   hVfsIos;
    if (!pszManifest)
    {
        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT, RTFILE_O_READ, false /*fLeaveOpen*/, &hVfsIos);
        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))
        {
            if (pszError && *pszError)
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                      "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
                                      "    '%s'\n",
                                      "     %*s^\n",
                                      rc, pszManifest, pszError - pszManifest, "");
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "Failed with %Rrc opening the input manifest '%s'", rc, pszManifest);
        }
    }

    /*
     * Read it.
     */
    RTMANIFEST hManifest;
    rc = RTManifestCreate(0 /*fFlags*/, &hManifest);
    if (RT_SUCCESS(rc))
    {
        if (fStdFormat)
        {
            char szErr[4096 + 1024];
            rc = RTManifestReadStandardEx(hManifest, hVfsIos, szErr, sizeof(szErr));
            if (RT_SUCCESS(rc))
            {
                RTVfsIoStrmRelease(hVfsIos);
                hVfsIos = NIL_RTVFSIOSTREAM;

                /*
                 * 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.");
                rc = VERR_NOT_IMPLEMENTED;
#if 1 /* For now, just write the manifest to stdout so we can test the read routine. */
                RTVFSIOSTREAM hVfsIosOut;
                rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, false /*fLeaveOpen*/, &hVfsIosOut);
                if (RT_SUCCESS(rc))
                {
                    RTManifestWriteStandard(hManifest, hVfsIosOut);
                    RTVfsIoStrmRelease(hVfsIosOut);
                }
#endif
            }
            else if (szErr[0])
                RTMsgError("Error reading manifest: %s", szErr);
            else
                RTMsgError("Error reading manifest: %Rrc", rc);
        }
        else
        {
            RTMsgError("Support for Java manifest files is not implemented yet");
            rc = VERR_NOT_IMPLEMENTED;
        }
        RTManifestRelease(hManifest);
    }

    RTVfsIoStrmRelease(hVfsIos);
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
/**
 * 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,
                                     PRTGETOPTSTATE pGetState, PRTGETOPTUNION pUnion, int chOpt)
{
    /*
     * Open the manifest file.
     */
    int rc;
    RTVFSIOSTREAM hVfsIos;
    if (!pszManifest)
    {
        rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, false /*fLeaveOpen*/, &hVfsIos);
        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,
                                    &hVfsIos, &pszError);
        if (RT_FAILURE(rc))
        {
            if (pszError && *pszError)
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                      "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
                                      "    '%s'\n",
                                      "     %*s^\n",
                                      rc, pszManifest, pszError - pszManifest, "");
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "Failed with %Rrc opening the manifest '%s'", rc, pszManifest);
        }
    }

    /*
     * Create the internal manifest.
     */
    RTMANIFEST hManifest;
    rc = RTManifestCreate(0 /*fFlags*/, &hManifest);
    if (RT_SUCCESS(rc))
    {
        /*
         * Change directory and start processing the specified files.
         */
        if (pszChDir)
        {
            rc = RTPathSetCurrent(pszChDir);
            if (RT_FAILURE(rc))
                RTMsgError("Failed to change directory to '%s': %Rrc", pszChDir, rc);
        }
        if (RT_SUCCESS(rc))
        {
            while (chOpt == VINF_GETOPT_NOT_OPTION)
            {
                rc = rtManifestAddFileToManifest(hManifest, pUnion->psz, fAttr);
                if (RT_FAILURE(rc))
                    break;

                /* next */
                chOpt = RTGetOpt(pGetState, pUnion);
            }
            if (RT_SUCCESS(rc) && chOpt != 0)
            {
                RTGetOptPrintError(chOpt, pUnion);
                rc = chOpt < 0 ? chOpt : -chOpt;
            }
        }

        /*
         * Write the manifest.
         */
        if (RT_SUCCESS(rc))
        {
            if (fStdFormat)
            {
                rc = RTManifestWriteStandard(hManifest, hVfsIos);
                if (RT_FAILURE(rc))
                    RTMsgError("RTManifestWriteStandard failed: %Rrc", rc);
            }
            else
            {
                RTMsgError("Support for Java manifest files is not implemented yet");
                rc = VERR_NOT_IMPLEMENTED;
            }
        }

        RTManifestRelease(hManifest);
    }

    RTVfsIoStrmRelease(hVfsIos);
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
Exemple #10
0
/**
 * Handles a file on the command line.
 *
 * @returns exit code.
 * @param   pszFile             The file to handle.
 * @param   fStdOut             Whether to output to standard output or not.
 * @param   fForce              Whether to output to or input from terminals.
 * @param   phVfsStdOut         Pointer to the standard out handle.
 *                              (input/output)
 */
static RTEXITCODE gzipDecompressFile(const char *pszFile, bool fStdOut, bool fForce, PRTVFSIOSTREAM phVfsStdOut)
{
    /*
     * Open the specified input file.
     */
    const char *pszError;
    RTVFSIOSTREAM hVfsIn;
    int rc = RTVfsChainOpenIoStream(pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsIn, &pszError);
    if (RT_FAILURE(rc))
    {
        if (pszError && *pszError)
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "RTVfsChainOpenIoStream failed with rc=%Rrc:\n"
                                  "    '%s'\n",
                                  "     %*s^\n",
                                  rc, pszFile, pszError - pszFile, "");
        return RTMsgErrorExit(RTEXITCODE_FAILURE,
                              "RTVfsChainOpenIoStream failed with rc=%Rrc: '%s'",
                              rc, pszFile);
    }

    /*
     * Output the output file.
     */
    RTVFSIOSTREAM hVfsOut;
    char szFinal[RTPATH_MAX];
    if (fStdOut)
    {
        if (*phVfsStdOut == NIL_RTVFSIOSTREAM)
        {
            rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, 0 /*fOpen*/, true /*fLeaveOpen*/, phVfsStdOut);
            if (RT_FAILURE(rc))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to set up standard out: %Rrc", rc);
        }
        hVfsOut = *phVfsStdOut;
        szFinal[0] = '\0';
    }
    else
    {
        rc = RTStrCopy(szFinal, sizeof(szFinal), pszFile);
        /** @todo remove the extension?  Or are we supposed
         *        to get the org name from the gzip stream? */
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Decompressing to file is not implemented");
    }

    /*
     * Do the decompressing, then flush and close the output stream (unless
     * it is stdout).
     */
    RTEXITCODE rcExit = gzipDecompress(hVfsIn, hVfsOut);
    RTVfsIoStrmRelease(hVfsIn);
    rc = RTVfsIoStrmFlush(hVfsOut);
    if (RT_FAILURE(rc))
        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to flush the output file: %Rrc", rc);
    RTVfsIoStrmRelease(hVfsOut);

    /*
     * Remove the input file, if that's the desire of the caller, or
     * remove the output file on decompression failure.
     */
    if (!fStdOut)
    {
        if (rcExit == RTEXITCODE_SUCCESS)
        {
            rc = RTFileDelete(pszFile);
            if (RT_FAILURE(rc))
                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileDelete failed with %rc: '%s'", rc, pszFile);
        }
        else
        {
            /* should we do this? */
            rc = RTFileDelete(szFinal);
            if (RT_FAILURE(rc))
                RTMsgError("RTFileDelete failed with %rc: '%s'", rc, pszFile);
        }
    }

    return rcExit;
}