예제 #1
0
/**
 * A mini GZIP program.
 *
 * @returns Program exit code.
 *
 * @param   cArgs               The number of arguments.
 * @param   papszArgs           The argument vector.  (Note that this may be
 *                              reordered, so the memory must be writable.)
 */
RTEXITCODE RTZipGzipCmd(unsigned cArgs, char **papszArgs)
{

    /*
     * Parse the command line.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--ascii",        'a', RTGETOPT_REQ_NOTHING },
        { "--stdout",       'c', RTGETOPT_REQ_NOTHING },
        { "--to-stdout",    'c', RTGETOPT_REQ_NOTHING },
        { "--decompress",   'd', RTGETOPT_REQ_NOTHING },
        { "--uncompress",   'd', RTGETOPT_REQ_NOTHING },
        { "--force",        'f', RTGETOPT_REQ_NOTHING },
        { "--keep",         'k', RTGETOPT_REQ_NOTHING },
        { "--list",         'l', RTGETOPT_REQ_NOTHING },
        { "--no-name",      'n', RTGETOPT_REQ_NOTHING },
        { "--name",         'N', RTGETOPT_REQ_NOTHING },
        { "--quiet",        'q', RTGETOPT_REQ_NOTHING },
        { "--recursive",    'r', RTGETOPT_REQ_NOTHING },
        { "--suffix",       'S', RTGETOPT_REQ_STRING  },
        { "--test",         't', RTGETOPT_REQ_NOTHING },
        { "--verbose",      'v', RTGETOPT_REQ_NOTHING },
        { "--fast",         '1', RTGETOPT_REQ_NOTHING },
        { "-1",             '1', RTGETOPT_REQ_NOTHING },
        { "-2",             '2', RTGETOPT_REQ_NOTHING },
        { "-3",             '3', RTGETOPT_REQ_NOTHING },
        { "-4",             '4', RTGETOPT_REQ_NOTHING },
        { "-5",             '5', RTGETOPT_REQ_NOTHING },
        { "-6",             '6', RTGETOPT_REQ_NOTHING },
        { "-7",             '7', RTGETOPT_REQ_NOTHING },
        { "-8",             '8', RTGETOPT_REQ_NOTHING },
        { "-9",             '9', RTGETOPT_REQ_NOTHING },
        { "--best",         '9', RTGETOPT_REQ_NOTHING }
    };

    RTGZIPCMDOPTS Opts;
    Opts.fAscii      = false;
    Opts.fStdOut     = false;
    Opts.fDecompress = false;
    Opts.fForce      = false;
    Opts.fKeep       = false;
    Opts.fList       = false;
    Opts.fName       = true;
    Opts.fQuiet      = false;
    Opts.fRecursive  = false;
    Opts.pszSuff     = ".gz";
    Opts.fTest       = false;
    Opts.uLevel      = 6;

    RTEXITCODE  rcExit      = RTEXITCODE_SUCCESS;
    unsigned    cProcessed  = 0;
    //RTVFSIOSTREAM hVfsStdOut= NIL_RTVFSIOSTREAM;

    RTGETOPTSTATE GetState;
    int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
                          RTGETOPTINIT_FLAGS_OPTS_FIRST);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTGetOptInit: %Rrc", rc);

    for (;;)
    {
        RTGETOPTUNION ValueUnion;
        int chOpt = RTGetOpt(&GetState, &ValueUnion);
        switch (chOpt)
        {
            case 0:
                /*
                 * If we've processed any files we're done.  Otherwise take
                 * input from stdin and write the output to stdout.
                 */
                if (cProcessed > 0)
                    return rcExit;
                ValueUnion.psz = "-";
                Opts.fStdOut = true;
                /* Fall thru. */
            case VINF_GETOPT_NOT_OPTION:
            {
                if (!*Opts.pszSuff && !Opts.fStdOut)
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --suffix option specified an empty string");
                if (!Opts.fStdOut && RTVfsChainIsSpec(ValueUnion.psz))
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must use standard out with VFS chain specifications");
                if (Opts.fName)
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --name option has not yet been implemented. Use --no-name.");
                if (Opts.fAscii)
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --ascii option has not yet been implemented.");
                if (Opts.fRecursive)
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --recursive option has not yet been implemented.");

                /* Open the input file. */
                RTVFSIOSTREAM hVfsSrc;
                RTEXITCODE rcExit2 = gzipOpenInput(ValueUnion.psz, &Opts, &hVfsSrc);
                if (rcExit2 == RTEXITCODE_SUCCESS)
                {
                    if (Opts.fList)
                        rcExit2 = gzipListFile(&hVfsSrc, &Opts);
                    else if (Opts.fTest)
                        rcExit2 = gzipTestFile(&hVfsSrc, &Opts);
                    else
                    {
                        RTVFSIOSTREAM hVfsDst;
                        rcExit2 = gzipOpenOutput(ValueUnion.psz, &Opts, &hVfsDst);
                        if (rcExit2 == RTEXITCODE_SUCCESS)
                        {
                            if (Opts.fDecompress)
                                rcExit2 = gzipDecompressFile(&hVfsSrc, &Opts, &hVfsDst);
                            else
                                rcExit2 = gzipCompressFile(&hVfsSrc, &Opts, &hVfsDst);
                            RTVfsIoStrmRelease(hVfsDst);
                        }
                    }
                    RTVfsIoStrmRelease(hVfsSrc);
                }
                if (rcExit2 != RTEXITCODE_SUCCESS)
                    rcExit = rcExit2;

                cProcessed++;
                break;
            }

            case 'a':   Opts.fAscii      = true;  break;
            case 'c':
                Opts.fStdOut = true;
                Opts.fKeep   = true;
                break;
            case 'd':   Opts.fDecompress = true;  break;
            case 'f':   Opts.fForce      = true;  break;
            case 'k':   Opts.fKeep       = true;  break;
            case 'l':   Opts.fList       = true;  break;
            case 'n':   Opts.fName       = false; break;
            case 'N':   Opts.fName       = true;  break;
            case 'q':   Opts.fQuiet      = true;  break;
            case 'r':   Opts.fRecursive  = true;  break;
            case 'S':   Opts.pszSuff     = ValueUnion.psz; break;
            case 't':   Opts.fTest       = true;  break;
            case 'v':   Opts.fQuiet      = false; break;
            case '1':   Opts.uLevel      = 1;     break;
            case '2':   Opts.uLevel      = 2;     break;
            case '3':   Opts.uLevel      = 3;     break;
            case '4':   Opts.uLevel      = 4;     break;
            case '5':   Opts.uLevel      = 5;     break;
            case '6':   Opts.uLevel      = 6;     break;
            case '7':   Opts.uLevel      = 7;     break;
            case '8':   Opts.uLevel      = 8;     break;
            case '9':   Opts.uLevel      = 9;     break;

            case 'h':
                RTPrintf("Usage: to be written\nOption dump:\n");
                for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
                    RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
                return RTEXITCODE_SUCCESS;

            case 'V':
                RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
                return RTEXITCODE_SUCCESS;

            default:
                return RTGetOptPrintError(chOpt, &ValueUnion);
        }
    }
}
예제 #2
0
int main(int argc, char **argv)
{
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * Parse the command line.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--ascii",        'a', RTGETOPT_REQ_NOTHING },
        { "--stdout",       'c', RTGETOPT_REQ_NOTHING },
        { "--to-stdout",    'c', RTGETOPT_REQ_NOTHING },
        { "--decompress",   'd', RTGETOPT_REQ_NOTHING },
        { "--uncompress",   'd', RTGETOPT_REQ_NOTHING },
        { "--force",        'f', RTGETOPT_REQ_NOTHING },
        { "--list",         'l', RTGETOPT_REQ_NOTHING },
        { "--no-name",      'n', RTGETOPT_REQ_NOTHING },
        { "--name",         'N', RTGETOPT_REQ_NOTHING },
        { "--quiet",        'q', RTGETOPT_REQ_NOTHING },
        { "--recursive",    'r', RTGETOPT_REQ_NOTHING },
        { "--suffix",       'S', RTGETOPT_REQ_STRING  },
        { "--test",         't', RTGETOPT_REQ_NOTHING },
        { "--verbose",      'v', RTGETOPT_REQ_NOTHING },
        { "--fast",         '1', RTGETOPT_REQ_NOTHING },
        { "-1",             '1', RTGETOPT_REQ_NOTHING },
        { "-2",             '2', RTGETOPT_REQ_NOTHING },
        { "-3",             '3', RTGETOPT_REQ_NOTHING },
        { "-4",             '4', RTGETOPT_REQ_NOTHING },
        { "-5",             '5', RTGETOPT_REQ_NOTHING },
        { "-6",             '6', RTGETOPT_REQ_NOTHING },
        { "-7",             '7', RTGETOPT_REQ_NOTHING },
        { "-8",             '8', RTGETOPT_REQ_NOTHING },
        { "-9",             '9', RTGETOPT_REQ_NOTHING },
        { "--best",         '9', RTGETOPT_REQ_NOTHING }
    };

    bool        fAscii      = false;
    bool        fStdOut     = false;
    bool        fDecompress = false;
    bool        fForce      = false;
    bool        fList       = false;
    bool        fName       = true;
    bool        fQuiet      = false;
    bool        fRecursive  = false;
    const char *pszSuff     = ".gz";
    bool        fTest       = false;
    unsigned    uLevel      = 6;

    RTEXITCODE  rcExit      = RTEXITCODE_SUCCESS;
    unsigned    cProcessed  = 0;
    RTVFSIOSTREAM hVfsStdOut= NIL_RTVFSIOSTREAM;

    RTGETOPTSTATE GetState;
    rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
                      RTGETOPTINIT_FLAGS_OPTS_FIRST);
    for (;;)
    {
        RTGETOPTUNION ValueUnion;
        rc = RTGetOpt(&GetState, &ValueUnion);
        switch (rc)
        {
        case 0:
        {
            /*
             * If we've processed any files we're done.  Otherwise take
             * input from stdin and write the output to stdout.
             */
            if (cProcessed > 0)
                return rcExit;
#if 0
            rc = RTVfsFileFromRTFile(1,
                                     RTFILE_O_WRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE,
                                     true /*fLeaveOpen*/,
                                     &hVfsOut);


            if (!fForce && isStdHandleATty(fDecompress ? 0 : 1))
                return RTMsgErrorExit(RTEXITCODE_SYNTAX,
                                      "Yeah, right. I'm not %s any compressed data %s the terminal without --force.\n",
                                      fDecompress ? "reading" : "writing",
                                      fDecompress ? "from"    : "to");
#else
            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "reading from standard input has not yet been implemented");
#endif
            return rcExit;
        }

        case VINF_GETOPT_NOT_OPTION:
        {
            if (!*pszSuff && !fStdOut)
                return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --suffix option specified an empty string");
            if (!fStdOut && RTVfsChainIsSpec(ValueUnion.psz))
                return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must use standard out with VFS chain specifications");

            RTEXITCODE rcExit2;
            if (fList)
                rcExit2 = gzipListFile(ValueUnion.psz, fForce);
            else if (fTest)
                rcExit2 = gzipTestFile(ValueUnion.psz, fForce);
            else if (fDecompress)
                rcExit2 = gzipDecompressFile(ValueUnion.psz, fStdOut, fForce, &hVfsStdOut);
            else
                rcExit2 = gzipCompressFile(ValueUnion.psz, fStdOut, fForce, &hVfsStdOut);
            if (rcExit2 != RTEXITCODE_SUCCESS)
                rcExit = rcExit2;

            cProcessed++;
            break;
        }

        case 'a':
            fAscii      = true;
            break;
        case 'c':
            fStdOut     = true;
            break;
        case 'd':
            fDecompress = true;
            break;
        case 'f':
            fForce      = true;
            break;
        case 'l':
            fList       = true;
            break;
        case 'n':
            fName       = false;
            break;
        case 'N':
            fName       = true;
            break;
        case 'q':
            fQuiet      = true;
            break;
        case 'r':
            fRecursive  = true;
            break;
        case 'S':
            pszSuff     = ValueUnion.psz;
            break;
        case 't':
            fTest       = true;
            break;
        case 'v':
            fQuiet      = false;
            break;
        case '1':
            uLevel      = 1;
            break;
        case '2':
            uLevel      = 2;
            break;
        case '3':
            uLevel      = 3;
            break;
        case '4':
            uLevel      = 4;
            break;
        case '5':
            uLevel      = 5;
            break;
        case '6':
            uLevel      = 6;
            break;
        case '7':
            uLevel      = 7;
            break;
        case '8':
            uLevel      = 8;
            break;
        case '9':
            uLevel      = 9;
            break;

        case 'h':
            RTPrintf("Usage: to be written\nOption dump:\n");
            for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
                RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
            return RTEXITCODE_SUCCESS;

        case 'V':
            RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
            return RTEXITCODE_SUCCESS;

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