/** * Attach a decompressor to the given source stream, replacing and releasing the * input handle with the decompressor. * * @returns Exit code. * @param phVfsSrc The input stream. Replaced on success. */ static RTEXITCODE gzipSetupDecompressor(PRTVFSIOSTREAM phVfsSrc) { /* * Attach the decompressor to the input stream. */ uint32_t fFlags = 0; fFlags |= RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR; RTVFSIOSTREAM hVfsGunzip; int rc = RTZipGzipDecompressIoStream(*phVfsSrc, fFlags, &hVfsGunzip); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTZipGzipDecompressIoStream failed: %Rrc", rc); uint32_t cRefs = RTVfsIoStrmRelease(*phVfsSrc); Assert(cRefs > 0); RT_NOREF_PV(cRefs); *phVfsSrc = hVfsGunzip; #if 0 /* This is a good place for testing stuff. */ rc = RTVfsCreateReadAheadForIoStream(*phVfsSrc, 0, 16, _4K+1, &hVfsGunzip); AssertRC(rc); if (RT_SUCCESS(rc)) { uint32_t cRefs = RTVfsIoStrmRelease(*phVfsSrc); Assert(cRefs > 0); *phVfsSrc = hVfsGunzip; } #endif return RTEXITCODE_SUCCESS; }
static RTEXITCODE gzipDecompress(RTVFSIOSTREAM hVfsIn, RTVFSIOSTREAM hVfsOut) { RTEXITCODE rcExit; RTVFSIOSTREAM hVfsGunzip; int rc = RTZipGzipDecompressIoStream(hVfsIn, 0 /*fFlags*/, &hVfsGunzip); if (RT_SUCCESS(rc)) { rcExit = gzipPush(hVfsGunzip, hVfsOut); RTVfsIoStrmRelease(hVfsGunzip); } else rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTZipGzipDecompressIoStream failed: %Rrc", rc); return rcExit; }
/** * Attach a decompressor to the given source stream, replacing and releasing the * input handle with the decompressor. * * @returns Exit code. * @param phVfsSrc The input stream. Replaced on success. */ static RTEXITCODE gzipSetupDecompressor(PRTVFSIOSTREAM phVfsSrc) { /* * Attach the decompressor to the input stream. */ uint32_t fFlags = 0; fFlags |= RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR; RTVFSIOSTREAM hVfsGunzip; int rc = RTZipGzipDecompressIoStream(*phVfsSrc, fFlags, &hVfsGunzip); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTZipGzipDecompressIoStream failed: %Rrc", rc); uint32_t cRefs = RTVfsIoStrmRelease(*phVfsSrc); Assert(cRefs > 0); *phVfsSrc = hVfsGunzip; return RTEXITCODE_SUCCESS; }
/** * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} */ static DECLCALLBACK(int) rtVfsChainGunzip_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo) { RT_NOREF(pProviderReg, pSpec, pElement, poffError, pErrInfo); AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE); RTVFSIOSTREAM hVfsIosIn = RTVfsObjToIoStream(hPrevVfsObj); if (hVfsIosIn == NIL_RTVFSIOSTREAM) return VERR_VFS_CHAIN_CAST_FAILED; RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM; int rc = RTZipGzipDecompressIoStream(hVfsIosIn, 0 /*fFlags*/, &hVfsIos); RTVfsObjFromIoStream(hVfsIosIn); if (RT_SUCCESS(rc)) { *phVfsObj = RTVfsObjFromIoStream(hVfsIos); RTVfsIoStrmRelease(hVfsIos); if (*phVfsObj != NIL_RTVFSOBJ) return VINF_SUCCESS; rc = VERR_VFS_CHAIN_CAST_FAILED; } return rc; }
/** * 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! */
/** * Rewinds the tarball file handle and creates a gunzip | tar chain that * results in a filesystem stream. * * @returns VBox status code, failures with message. * @param hTarballFile The handle to the tarball file. * @param pszError Where to store an error message on failure. * @param cbError The size of the buffer @a pszError points to. * @param phTarFss Where to return the filesystem stream handle. * @param phFileManifest Where to return a manifest where the tarball is * gettting hashed. The entry will be called * "extpack" and be ready when the file system * stream is at an end. Optional. */ int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest) { Assert(cbError > 0); *pszError = '\0'; *phTarFss = NIL_RTVFSFSSTREAM; /* * Rewind the file and set up a VFS chain for it. */ int rc = RTFileSeek(hTarballFile, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) return vboxExtPackReturnError(rc, pszError, cbError, "Failed seeking to the start of the tarball: %Rrc", rc); RTVFSIOSTREAM hTarballIos; rc = RTVfsIoStrmFromRTFile(hTarballFile, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, true /*fLeaveOpen*/, &hTarballIos); if (RT_FAILURE(rc)) return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsIoStrmFromRTFile failed: %Rrc", rc); RTMANIFEST hFileManifest = NIL_RTMANIFEST; rc = RTManifestCreate(0 /*fFlags*/, &hFileManifest); if (RT_SUCCESS(rc)) { RTVFSIOSTREAM hPtIos; rc = RTManifestEntryAddPassthruIoStream(hFileManifest, hTarballIos, "extpack", RTMANIFEST_ATTR_SHA256, true /*read*/, &hPtIos); if (RT_SUCCESS(rc)) { RTVFSIOSTREAM hGunzipIos; rc = RTZipGzipDecompressIoStream(hPtIos, 0 /*fFlags*/, &hGunzipIos); if (RT_SUCCESS(rc)) { RTVFSFSSTREAM hTarFss; rc = RTZipTarFsStreamFromIoStream(hGunzipIos, 0 /*fFlags*/, &hTarFss); if (RT_SUCCESS(rc)) { RTVfsIoStrmRelease(hPtIos); RTVfsIoStrmRelease(hGunzipIos); RTVfsIoStrmRelease(hTarballIos); *phTarFss = hTarFss; if (phFileManifest) *phFileManifest = hFileManifest; else RTManifestRelease(hFileManifest); return VINF_SUCCESS; } vboxExtPackSetError(pszError, cbError, "RTZipTarFsStreamFromIoStream failed: %Rrc", rc); RTVfsIoStrmRelease(hGunzipIos); } else vboxExtPackSetError(pszError, cbError, "RTZipGzipDecompressIoStream failed: %Rrc", rc); RTVfsIoStrmRelease(hPtIos); } else vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddPassthruIoStream failed: %Rrc", rc); RTManifestRelease(hFileManifest); } else vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc); RTVfsIoStrmRelease(hTarballIos); return rc; }