/** * 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); } } }
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); } } }