Changeset 47359 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Jul 24, 2013 12:45:47 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87505
- Location:
- trunk/src/VBox/Runtime/common/zip
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/gzipvfs.cpp
r39083 r47359 56 56 }; 57 57 #endif /* RT_OS_OS2 || RT_OS_SOLARIS || RT_OS_WINDOWS */ 58 58 59 59 60 /******************************************************************************* … … 168 169 169 170 171 /******************************************************************************* 172 * Internal Functions * 173 *******************************************************************************/ 174 static int rtZipGzip_FlushIt(PRTZIPGZIPSTREAM pThis, uint8_t fFlushType); 175 176 170 177 /** 171 178 * Convert from zlib to IPRT status codes. … … 224 231 int rc; 225 232 if (pThis->fDecompress) 233 { 226 234 rc = inflateEnd(&pThis->Zlib); 235 if (rc != Z_OK) 236 rc = rtZipGzipConvertErrFromZlib(pThis, rc); 237 } 227 238 else 228 rc = deflateEnd(&pThis->Zlib); 229 if (rc != Z_OK) 230 rc = rtZipGzipConvertErrFromZlib(pThis, rc); 239 { 240 /* Flush the compression stream before terminating it. */ 241 rc = VINF_SUCCESS; 242 if (!pThis->fFatalError) 243 rc = rtZipGzip_FlushIt(pThis, Z_FINISH); 244 245 int rc2 = deflateEnd(&pThis->Zlib); 246 if (RT_SUCCESS(rc) && rc2 != Z_OK) 247 rc = rtZipGzipConvertErrFromZlib(pThis, rc); 248 } 231 249 232 250 RTVfsIoStrmRelease(pThis->hVfsIos); … … 350 368 } 351 369 370 352 371 /** 353 372 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} … … 356 375 { 357 376 PRTZIPGZIPSTREAM pThis = (PRTZIPGZIPSTREAM)pvThis; 358 int rc; 359 377 378 Assert(pSgBuf->cSegs == 1); 360 379 AssertReturn(off == -1, VERR_INVALID_PARAMETER); 361 380 if (!pThis->fDecompress) 362 381 return VERR_ACCESS_DENIED; 363 382 364 if (pSgBuf->cSegs == 1) 365 rc = rtZipGzip_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead); 366 else 367 { 368 rc = VINF_SUCCESS; 369 size_t cbRead = 0; 370 size_t cbReadSeg; 371 size_t *pcbReadSeg = pcbRead ? &cbReadSeg : NULL; 372 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++) 383 return rtZipGzip_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead); 384 } 385 386 387 /** 388 * Internal helper for rtZipGzip_Write, rtZipGzip_Flush and rtZipGzip_Close. 389 * 390 * @returns IPRT status code. 391 * @retval VINF_SUCCESS 392 * @retval VINF_TRY_AGAIN - the only informational status. 393 * @retval VERR_INTERRUPTED - call again. 394 * 395 * @param pThis The gzip I/O stream instance data. 396 * @param fBlocking Whether to block or not. 397 */ 398 static int rtZipGzip_WriteOutputBuffer(PRTZIPGZIPSTREAM pThis, bool fBlocking) 399 { 400 /* 401 * Anything to write? No, then just return immediately. 402 */ 403 size_t cbToWrite = sizeof(pThis->abBuffer) - pThis->Zlib.avail_out; 404 if (cbToWrite == 0) 405 { 406 Assert(pThis->Zlib.next_out == &pThis->abBuffer[0]); 407 return VINF_SUCCESS; 408 } 409 Assert(cbToWrite <= sizeof(pThis->abBuffer)); 410 411 /* 412 * Loop write on VERR_INTERRUPTED. 413 * 414 * Note! Asserting a bit extra here to make sure the 415 * RTVfsIoStrmSgWrite works correctly. 416 */ 417 int rc; 418 size_t cbWrittenOut; 419 for (;;) 420 { 421 /* Set up the buffer. */ 422 pThis->SgSeg.cbSeg = cbToWrite; 423 Assert(pThis->SgSeg.pvSeg == &pThis->abBuffer[0]); 424 RTSgBufReset(&pThis->SgBuf); 425 426 cbWrittenOut = ~(size_t)0; 427 rc = RTVfsIoStrmSgWrite(pThis->hVfsIos, &pThis->SgBuf, fBlocking, &cbWrittenOut); 428 if (rc != VINF_SUCCESS) 373 429 { 374 cbReadSeg = 0; 375 rc = rtZipGzip_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg); 376 if (RT_FAILURE(rc)) 377 break; 378 if (pcbRead) 430 AssertMsg(RT_FAILURE(rc) || rc == VINF_TRY_AGAIN, ("%Rrc\n", rc)); 431 if (rc == VERR_INTERRUPTED) 379 432 { 380 cbRead += cbReadSeg; 381 if (cbReadSeg != pSgBuf->paSegs[iSeg].cbSeg) 382 break; 433 Assert(cbWrittenOut == 0); 434 continue; 435 } 436 if (RT_FAILURE(rc) || rc == VINF_TRY_AGAIN || cbWrittenOut == 0) 437 { 438 AssertReturn(cbWrittenOut == 0, VERR_INTERNAL_ERROR_3); 439 AssertReturn(rc != VINF_SUCCESS, VERR_IPE_UNEXPECTED_INFO_STATUS); 440 return rc; 383 441 } 384 442 } 385 if (pcbRead) 386 *pcbRead = cbRead; 387 } 388 389 return rc; 443 break; 444 } 445 AssertMsgReturn(cbWrittenOut > 0 && cbWrittenOut <= sizeof(pThis->abBuffer), 446 ("%zu %Rrc\n", cbWrittenOut, rc), 447 VERR_INTERNAL_ERROR_4); 448 449 /* 450 * Adjust the Zlib output buffer members. 451 */ 452 if (cbWrittenOut == pThis->SgBuf.paSegs[0].cbSeg) 453 { 454 pThis->Zlib.avail_out = sizeof(pThis->abBuffer); 455 pThis->Zlib.next_out = &pThis->abBuffer[0]; 456 } 457 else 458 { 459 Assert(cbWrittenOut <= pThis->SgBuf.paSegs[0].cbSeg); 460 size_t cbLeft = pThis->SgBuf.paSegs[0].cbSeg - cbWrittenOut; 461 memmove(&pThis->abBuffer[0], &pThis->abBuffer[cbWrittenOut], cbLeft); 462 pThis->Zlib.avail_out += (uInt)cbWrittenOut; 463 pThis->Zlib.next_out = &pThis->abBuffer[cbWrittenOut]; 464 } 465 466 return VINF_SUCCESS; 467 } 468 469 470 /** 471 * Processes all available input. 472 * 473 * @returns IPRT status code. 474 * 475 * @param pThis The gzip I/O stream instance data. 476 * @param fBlocking Whether to block or not. 477 */ 478 static int rtZipGzip_CompressIt(PRTZIPGZIPSTREAM pThis, bool fBlocking) 479 { 480 /* 481 * Processes all the intput currently lined up for us. 482 */ 483 while (pThis->Zlib.avail_in > 0) 484 { 485 /* Make sure there is some space in the output buffer before calling 486 deflate() so we don't waste time filling up the corners. */ 487 static const size_t s_cbFlushThreshold = 4096; 488 AssertCompile(sizeof(pThis->abBuffer) >= s_cbFlushThreshold * 4); 489 if (pThis->Zlib.avail_out < s_cbFlushThreshold) 490 { 491 int rc = rtZipGzip_WriteOutputBuffer(pThis, fBlocking); 492 if (rc != VINF_SUCCESS) 493 return rc; 494 Assert(pThis->Zlib.avail_out >= s_cbFlushThreshold); 495 } 496 497 int rcZlib = deflate(&pThis->Zlib, Z_NO_FLUSH); 498 if (rcZlib != Z_OK) 499 return rtZipGzipConvertErrFromZlib(pThis, rcZlib); 500 } 501 return VINF_SUCCESS; 390 502 } 391 503 … … 397 509 { 398 510 PRTZIPGZIPSTREAM pThis = (PRTZIPGZIPSTREAM)pvThis; 399 //int rc;400 511 401 512 AssertReturn(off == -1, VERR_INVALID_PARAMETER); 402 NOREF(fBlocking); 513 Assert(pSgBuf->cSegs == 1); NOREF(fBlocking); 514 403 515 if (pThis->fDecompress) 404 516 return VERR_ACCESS_DENIED; 405 517 406 /** @todo implement compression. */ 407 NOREF(pSgBuf); NOREF(pcbWritten); 408 return VERR_NOT_IMPLEMENTED; 518 /* 519 * Write out the intput buffer. Using a loop here because of potential 520 * integer type overflow since avail_in is uInt and cbSeg is size_t. 521 */ 522 int rc = VINF_SUCCESS; 523 size_t cbWritten = 0; 524 uint8_t const *pbSrc = (uint8_t const *)pSgBuf->paSegs[0].pvSeg; 525 size_t cbLeft = pSgBuf->paSegs[0].cbSeg; 526 if (cbLeft > 0) 527 for (;;) 528 { 529 size_t cbThis = cbLeft < ~(uInt)0 ? cbLeft : ~(uInt)0 / 2; 530 pThis->Zlib.next_in = (Bytef * )pbSrc; 531 pThis->Zlib.avail_in = (uInt)cbThis; 532 rc = rtZipGzip_CompressIt(pThis, fBlocking); 533 534 Assert(cbThis >= pThis->Zlib.avail_in); 535 cbThis -= pThis->Zlib.avail_in; 536 cbWritten += cbThis; 537 if (cbLeft == cbThis || rc != VINF_SUCCESS) 538 break; 539 pbSrc += cbThis; 540 cbLeft -= cbThis; 541 } 542 543 if (pcbWritten) 544 *pcbWritten = cbWritten; 545 return rc; 546 } 547 548 549 /** 550 * Processes all available input. 551 * 552 * @returns IPRT status code. 553 * 554 * @param pThis The gzip I/O stream instance data. 555 * @param fFlushType The flush type to pass to deflate(). 556 */ 557 static int rtZipGzip_FlushIt(PRTZIPGZIPSTREAM pThis, uint8_t fFlushType) 558 { 559 /* 560 * Tell Zlib to flush until it stops producing more output. 561 */ 562 int rc; 563 bool fMaybeMore = true; 564 for (;;) 565 { 566 /* Write the entire output buffer. */ 567 do 568 { 569 rc = rtZipGzip_WriteOutputBuffer(pThis, true /*fBlocking*/); 570 if (RT_FAILURE(rc)) 571 return rc; 572 Assert(rc == VINF_SUCCESS); 573 } while (pThis->Zlib.avail_out < sizeof(pThis->abBuffer)); 574 575 if (!fMaybeMore) 576 return VINF_SUCCESS; 577 578 /* Do the flushing. */ 579 pThis->Zlib.next_in = NULL; 580 pThis->Zlib.avail_in = 0; 581 int rcZlib = deflate(&pThis->Zlib, fFlushType); 582 if (rcZlib == Z_OK) 583 fMaybeMore = pThis->Zlib.avail_out < 64 || fFlushType == Z_FINISH; 584 else if (rcZlib == Z_STREAM_END) 585 fMaybeMore = false; 586 else 587 { 588 rtZipGzip_WriteOutputBuffer(pThis, true /*fBlocking*/); 589 return rtZipGzipConvertErrFromZlib(pThis, rcZlib); 590 } 591 } 409 592 } 410 593 … … 416 599 { 417 600 PRTZIPGZIPSTREAM pThis = (PRTZIPGZIPSTREAM)pvThis; 601 if (!pThis->fDecompress) 602 { 603 int rc = rtZipGzip_FlushIt(pThis, Z_SYNC_FLUSH); 604 if (RT_FAILURE(rc)) 605 return rc; 606 } 607 418 608 return RTVfsIoStrmFlush(pThis->hVfsIos); 419 609 } … … 481 671 }, 482 672 RTVFSIOSTREAMOPS_VERSION, 483 0,673 RTVFSIOSTREAMOPS_FEAT_NO_SG, 484 674 rtZipGzip_Read, 485 675 rtZipGzip_Write, … … 571 761 } 572 762 763 764 RTDECL(int) RTZipGzipCompressIoStream(RTVFSIOSTREAM hVfsIosDst, uint32_t fFlags, uint8_t uLevel, PRTVFSIOSTREAM phVfsIosZip) 765 { 766 AssertPtrReturn(hVfsIosDst, VERR_INVALID_HANDLE); 767 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); 768 AssertPtrReturn(phVfsIosZip, VERR_INVALID_POINTER); 769 AssertReturn(uLevel > 0 && uLevel <= 9, VERR_INVALID_PARAMETER); 770 771 uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosDst); 772 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); 773 774 /* 775 * Create the compression I/O stream. 776 */ 777 RTVFSIOSTREAM hVfsIos; 778 PRTZIPGZIPSTREAM pThis; 779 int rc = RTVfsNewIoStream(&g_rtZipGzipOps, sizeof(RTZIPGZIPSTREAM), RTFILE_O_WRITE, NIL_RTVFS, NIL_RTVFSLOCK, 780 &hVfsIos, (void **)&pThis); 781 if (RT_SUCCESS(rc)) 782 { 783 pThis->hVfsIos = hVfsIosDst; 784 pThis->offStream = 0; 785 pThis->fDecompress = false; 786 pThis->SgSeg.pvSeg = &pThis->abBuffer[0]; 787 pThis->SgSeg.cbSeg = sizeof(pThis->abBuffer); 788 RTSgBufInit(&pThis->SgBuf, &pThis->SgSeg, 1); 789 790 RT_ZERO(pThis->Zlib); 791 pThis->Zlib.opaque = pThis; 792 pThis->Zlib.next_out = &pThis->abBuffer[0]; 793 pThis->Zlib.avail_out = sizeof(pThis->abBuffer); 794 795 rc = deflateInit2(&pThis->Zlib, 796 uLevel, 797 Z_DEFLATED, 798 15 /* Windows Size */ + 16 /* GZIP header */, 799 9 /* Max memory level for optimal speed */, 800 Z_DEFAULT_STRATEGY); 801 802 if (rc >= 0) 803 { 804 *phVfsIosZip = hVfsIos; 805 return VINF_SUCCESS; 806 } 807 808 rc = rtZipGzipConvertErrFromZlib(pThis, rc); /** @todo cleaning up in this situation is going to go wrong. */ 809 RTVfsIoStrmRelease(hVfsIos); 810 } 811 else 812 RTVfsIoStrmRelease(hVfsIosDst); 813 return rc; 814 } 815 -
trunk/src/VBox/Runtime/common/zip/tarcmd.cpp
r44300 r47359 912 912 } 913 913 914 914 915 RTDECL(RTEXITCODE) RTZipTarCmd(unsigned cArgs, char **papszArgs) 915 916 {
Note:
See TracChangeset
for help on using the changeset viewer.