Changeset 67166 in vbox for trunk/src/VBox/Runtime/common/zip/tarvfswriter.cpp
- Timestamp:
- May 31, 2017 11:14:37 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/tarvfswriter.cpp
r67150 r67166 131 131 /** The current I/O stream position (relative to offData). */ 132 132 uint64_t offCurrent; 133 /** The expected size amount of file content. This is set to UINT64_MAX if 134 * open-ended file size. */ 133 /** The expected size amount of file content, or max file size if open-ended. */ 135 134 uint64_t cbExpected; 136 135 /** The current amount of file content written. */ … … 138 137 /** Object info copy for rtZipTarWriterPush_QueryInfo. */ 139 138 RTFSOBJINFO ObjInfo; 139 /** Set if open-ended file size requiring a tar header update when done. */ 140 bool fOpenEnded; 140 141 } RTZIPTARFSSTREAMWRITERPUSH; 141 142 /** Pointer to a push I/O instance. */ … … 176 177 * Internal Functions * 177 178 *********************************************************************************************************************************/ 179 static DECLCALLBACK(int) rtZipTarWriterPush_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual); 178 180 static int rtZipTarFssWriter_CompleteCurrentPushFile(PRTZIPTARFSSTREAMWRITER pThis); 179 181 static int rtZipTarFssWriter_AddFile(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, RTVFSIOSTREAM hVfsIos, … … 506 508 PRTZIPTARFSSTREAMWRITER pParent = pPush->pParent; 507 509 AssertPtrReturn(pParent, VERR_WRONG_ORDER); 508 Assert(!pcbWritten || !*pcbWritten /* assume caller sets this to zero so we can be lazy here */);509 510 510 511 int rc = pParent->rcFatal; … … 519 520 520 521 /* 521 * Deal with simple non-seeking write first. 522 */ 523 size_t cbWritten = 0; 524 Assert(pPush->offCurrent <= pPush->cbExpected); 525 Assert(pPush->offCurrent <= pPush->cbCurrent); 522 * Hopefully we don't need to seek. But if we do, let the seek method do 523 * it as it's not entirely trivial. 524 */ 526 525 if ( off < 0 527 526 || (uint64_t)off == pPush->offCurrent) 528 { 527 rc = VINF_SUCCESS; 528 else 529 rc = rtZipTarWriterPush_Seek(pvThis, off, RTFILE_SEEK_BEGIN, NULL); 530 if (RT_SUCCESS(rc)) 531 { 532 Assert(pPush->offCurrent <= pPush->cbExpected); 533 Assert(pPush->offCurrent <= pPush->cbCurrent); 529 534 AssertMsgReturn(cbToWrite <= pPush->cbExpected - pPush->offCurrent, 530 535 ("offCurrent=%#RX64 + cbToWrite=%#zx = %#RX64; cbExpected=%RX64\n", 531 536 pPush->offCurrent, cbToWrite, pPush->offCurrent + cbToWrite, pPush->cbExpected), 532 537 VERR_DISK_FULL); 538 size_t cbWritten = 0; 533 539 rc = RTVfsIoStrmWrite(pParent->hVfsIos, pvToWrite, cbToWrite, fBlocking, &cbWritten); 534 540 if (RT_SUCCESS(rc)) … … 540 546 pPush->cbCurrent = pPush->offCurrent; 541 547 } 542 } 543 } 544 /* 545 * Needs to seek, more validation, possible zero filling of the space in between. 546 */ 547 else 548 { 549 AssertMsgReturn((uint64_t)off <= pPush->cbExpected, 550 ("off=%#RX64 cbExpected=%#RX64", (uint64_t)off, pPush->cbExpected), 551 VERR_SEEK); 552 AssertMsgReturn(cbToWrite <= pPush->cbExpected - (uint64_t)off, 553 ("off=%#RX64 + cbToWrite=%#zx = %#RX64; cbExpected=%RX64\n", 554 (uint64_t)off, cbToWrite, (uint64_t)off + cbToWrite, pPush->cbExpected), 555 VERR_DISK_FULL); 556 557 /* Zero fill seek gap if necessary. */ 558 if ((uint64_t)off > pPush->cbCurrent) 559 { 560 if (pPush->offCurrent == pPush->cbCurrent) 561 rc = VINF_SUCCESS; 562 else 563 { 564 AssertReturn(pParent->hVfsFile != NIL_RTVFSFILE, VERR_NOT_A_FILE); 565 rc = RTVfsFileSeek(pParent->hVfsFile, pPush->offData + pPush->cbCurrent, RTFILE_SEEK_BEGIN, NULL); 566 if (RT_SUCCESS(rc)) 567 pPush->offCurrent = pPush->cbCurrent; 568 } 569 570 if (RT_SUCCESS(rc)) 571 { 572 uint64_t cbToZero = (uint64_t)off - pPush->cbCurrent; 573 rc = RTVfsIoStrmZeroFill(pParent->hVfsIos, cbToZero); 574 if (RT_SUCCESS(rc)) 575 { 576 pPush->offCurrent += cbToZero; 577 pParent->cbWritten += cbToZero; 578 } 579 } 580 } 581 /* Seek backwards to the desired position. */ 582 else 583 { 584 AssertReturn(pParent->hVfsFile != NIL_RTVFSFILE, VERR_NOT_A_FILE); 585 rc = RTVfsFileSeek(pParent->hVfsFile, pPush->offData + (uint64_t)off, RTFILE_SEEK_BEGIN, NULL); 586 if (RT_SUCCESS(rc)) 587 pPush->offCurrent = (uint64_t)off; 588 } 589 590 /* Do the write. */ 591 if (RT_SUCCESS(rc)) 592 { 593 rc = RTVfsIoStrmWrite(pParent->hVfsIos, pvToWrite, cbToWrite, fBlocking, &cbWritten); 594 if (RT_SUCCESS(rc)) 595 { 596 pPush->offCurrent += cbWritten; 597 if (pPush->offCurrent > pPush->cbCurrent) 598 { 599 pParent->cbWritten = pPush->offCurrent - pPush->cbCurrent; 600 pPush->cbCurrent = pPush->offCurrent; 601 } 602 } 548 if (pcbWritten) 549 *pcbWritten = cbWritten; 603 550 } 604 551 } … … 607 554 * Fatal errors get down here, non-fatal ones returns earlier. 608 555 */ 609 if (pcbWritten)610 *pcbWritten = cbWritten;611 556 if (RT_SUCCESS(rc)) 612 557 return VINF_SUCCESS; … … 711 656 int rc = pParent->rcFatal; 712 657 AssertRCReturn(rc, rc); 658 Assert(pPush->offCurrent <= pPush->cbCurrent); 713 659 714 660 /* 715 661 * Calculate the new file offset. 716 662 */ 717 uint64_t offNew;663 RTFOFF offNewSigned; 718 664 switch (uMethod) 719 665 { 720 666 case RTFILE_SEEK_BEGIN: 721 AssertReturn(offSeek >= 0, VERR_NEGATIVE_SEEK); 722 offNew = (uint64_t)offSeek; 667 offNewSigned = offSeek; 723 668 break; 724 725 669 case RTFILE_SEEK_CURRENT: 726 if (offSeek >= 0) 727 { 728 offNew = (uint64_t)offSeek + pPush->offCurrent; 729 AssertReturn(offNew >= pPush->offCurrent, VERR_SEEK); 730 } 731 else if ((uint64_t)-offSeek <= pPush->offCurrent) 732 offNew = 0; 733 else 734 offNew = pPush->offCurrent + offSeek; 670 offNewSigned = pPush->offCurrent + offSeek; 735 671 break; 736 737 672 case RTFILE_SEEK_END: 738 if (offSeek >= 0) 739 { 740 offNew = (uint64_t)offSeek + pPush->cbCurrent; 741 AssertReturn(offNew >= pPush->cbCurrent, VERR_SEEK); 742 } 743 else if ((uint64_t)-offSeek <= pPush->cbCurrent) 744 offNew = 0; 745 else 746 offNew = pPush->cbCurrent + offSeek; 673 offNewSigned = pPush->cbCurrent + offSeek; 747 674 break; 748 749 675 default: 750 AssertFailedReturn(VERR_IN TERNAL_ERROR_5);676 AssertFailedReturn(VERR_INVALID_PARAMETER); 751 677 } 752 678 … … 754 680 * Check the new file offset against expectations. 755 681 */ 682 AssertMsgReturn(offNewSigned >= 0, ("offNewSigned=%RTfoff\n", offNewSigned), VERR_NEGATIVE_SEEK); 683 684 uint64_t offNew = (uint64_t)offNewSigned; 756 685 AssertMsgReturn(offNew <= pPush->cbExpected, ("offNew=%#RX64 cbExpected=%#Rx64\n", offNew, pPush->cbExpected), VERR_SEEK); 757 686 … … 783 712 } 784 713 /* 785 * Just change the file position s.714 * Just change the file position to somewhere we've already written. 786 715 */ 787 716 else … … 793 722 pPush->offCurrent = offNew; 794 723 } 724 Assert(pPush->offCurrent <= pPush->cbCurrent); 795 725 796 726 *poffActual = pPush->offCurrent; … … 911 841 * content at pPush->offHdr and we only need to update the size. 912 842 */ 913 if (pPush-> cbExpected == UINT64_MAX)843 if (pPush->fOpenEnded) 914 844 { 915 845 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pPush->cbCurrent); … … 1850 1780 * Create an I/O stream object for the caller to use. 1851 1781 */ 1782 RTFOFF const offHdr = RTVfsIoStrmTell(pThis->hVfsIos); 1783 AssertReturn(offHdr >= 0, (int)offHdr); 1784 1852 1785 PRTZIPTARFSSTREAMWRITERPUSH pPush; 1853 1786 RTVFSIOSTREAM hVfsIos; … … 1871 1804 pPush->pParent = NULL; 1872 1805 pPush->cbExpected = cbFile; 1873 pPush->offHdr = RTVfsIoStrmTell(pThis->hVfsIos);1806 pPush->offHdr = (uint64_t)offHdr; 1874 1807 pPush->offData = 0; 1875 1808 pPush->offCurrent = 0; 1876 1809 pPush->cbCurrent = 0; 1877 1810 pPush->ObjInfo = ObjInfo; 1811 pPush->fOpenEnded = cbFile == UINT64_MAX; 1878 1812 1879 1813 /* … … 1883 1817 if (RT_SUCCESS(rc)) 1884 1818 { 1885 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL); 1819 size_t cbHdrs = pThis->cHdrs * sizeof(pThis->aHdrs[0]); 1820 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, cbHdrs, true /*fBlocking*/, NULL); 1886 1821 if (RT_SUCCESS(rc)) 1887 1822 { 1888 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);1823 pThis->cbWritten += cbHdrs; 1889 1824 1890 1825 /* 1891 1826 * Complete the object and return. 1892 1827 */ 1893 pPush->offData = RTVfsIoStrmTell(pThis->hVfsIos); 1828 pPush->offData = pPush->offHdr + cbHdrs; 1829 if (cbFile == UINT64_MAX) 1830 pPush->cbExpected = (uint64_t)(RTFOFF_MAX - _4K) - pPush->offData; 1894 1831 pPush->pParent = pThis; 1895 1832 pThis->pPush = pPush;
Note:
See TracChangeset
for help on using the changeset viewer.