int main(int argc, char **argv) { /* * Initialize IPRT and create the test. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTFilesystem", &hTest); if (rc) return rc; RTTestBanner(hTest); /* * If no args, display usage. */ if (argc < 2) { RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Syntax: %s <image>\n", argv[0]); return RTTestSkipAndDestroy(hTest, "Missing required arguments\n"); } /* Open image. */ RTFILE hFile; RTVFSFILE hVfsFile; rc = RTFileOpen(&hFile, argv[1], RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ); if (RT_FAILURE(rc)) { RTTestIFailed("RTFileOpen -> %Rrc", rc); return RTTestSummaryAndDestroy(hTest); } rc = RTVfsFileFromRTFile(hFile, 0, false, &hVfsFile); if (RT_FAILURE(rc)) { RTTestIFailed("RTVfsFileFromRTFile -> %Rrc", rc); return RTTestSummaryAndDestroy(hTest); } rc = tstRTFilesystem(hTest, hVfsFile); RTTESTI_CHECK(rc == VINF_SUCCESS); RTVfsFileRelease(hVfsFile); /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
RTR3DECL(int) RTTarFileOpen(RTTAR hTar, PRTTARFILE phFile, const char *pszFilename, uint32_t fOpen) { /* Write only interface now. */ AssertReturn(fOpen & RTFILE_O_WRITE, VERR_INVALID_PARAMETER); PRTTARINTERNAL pInt = hTar; RTTAR_VALID_RETURN(pInt); if (!pInt->hTarFile) return VERR_INVALID_HANDLE; if (fOpen & RTFILE_O_WRITE) { if (!(pInt->fOpenMode & RTFILE_O_WRITE)) return VERR_WRITE_PROTECT; if (pInt->fFileOpenForWrite) return VERR_TOO_MANY_OPEN_FILES; } int rc = VINF_SUCCESS; if (!(fOpen & RTFILE_O_WRITE)) { /* * Rewind the stream if necessary. */ if (!pInt->fFssAtStart) { if (pInt->hVfsFss != NIL_RTVFSFSSTREAM) { uint32_t cRefs = RTVfsFsStrmRelease(pInt->hVfsFss); Assert(cRefs != UINT32_MAX); pInt->hVfsFss = NIL_RTVFSFSSTREAM; } if (pInt->hVfsFile == NIL_RTVFSFILE) { rc = RTVfsFileFromRTFile(pInt->hTarFile, RTFILE_O_READ, true /*fLeaveOpen*/, &pInt->hVfsFile); if (RT_FAILURE(rc)) return rc; } RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(pInt->hVfsFile); rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0 /*fFlags*/, &pInt->hVfsFss); RTVfsIoStrmRelease(hVfsIos); if (RT_FAILURE(rc)) return rc; } /* * Search the file system stream. */ pInt->fFssAtStart = false; for (;;) { char *pszName; RTVFSOBJTYPE enmType; RTVFSOBJ hVfsObj; rc = RTVfsFsStrmNext(pInt->hVfsFss, &pszName, &enmType, &hVfsObj); if (rc == VERR_EOF) return VERR_FILE_NOT_FOUND; if (RT_FAILURE(rc)) return rc; if (!RTStrCmp(pszName, pszFilename)) { if (enmType == RTVFSOBJTYPE_FILE || enmType == RTVFSOBJTYPE_IO_STREAM) rc = rtTarFileCreateHandleForReadOnly(pszName, RTVfsObjToIoStream(hVfsObj), fOpen, phFile); else { rc = VERR_UNEXPECTED_FS_OBJ_TYPE; RTStrFree(pszName); } RTVfsObjRelease(hVfsObj); break; } RTStrFree(pszName); RTVfsObjRelease(hVfsObj); } /* Search loop. */ } else { PRTTARFILEINTERNAL pFileInt = rtTarFileCreateForWrite(pInt, pszFilename, fOpen); if (!pFileInt) return VERR_NO_MEMORY; pInt->fFileOpenForWrite = true; /* If we are in write mode, we also in append mode. Add an dummy * header at the end of the current file. It will be filled by the * close operation. */ rc = RTFileSeek(pFileInt->pTar->hTarFile, 0, RTFILE_SEEK_END, &pFileInt->offStart); if (RT_SUCCESS(rc)) { RTTARRECORD record; RT_ZERO(record); rc = RTFileWrite(pFileInt->pTar->hTarFile, &record, sizeof(RTTARRECORD), NULL); } if (RT_SUCCESS(rc)) *phFile = (RTTARFILE)pFileInt; else { /* Cleanup on failure */ if (pFileInt->pszFilename) RTStrFree(pFileInt->pszFilename); RTMemFree(pFileInt); } } return rc; }
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); } } }