Changeset 32566 in vbox for trunk/src/VBox/Runtime/common/misc
- Timestamp:
- Sep 16, 2010 2:42:36 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/tar.cpp
r31624 r32566 134 134 return VINF_SUCCESS; 135 135 return VERR_TAR_CHKSUM_MISMATCH; 136 } 137 138 static int rtTarCopyFileFromToBuf(RTFILE hFile, void **ppvBuf, uint64_t *pcbSize, PRTTARRECORD pRecord, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 139 { 140 int rc = VINF_SUCCESS; 141 142 uint64_t cbToCopy = RTStrToUInt64(pRecord->h.size); 143 144 *ppvBuf = RTMemAlloc(cbToCopy); 145 char* pcsTmp = (char*)*ppvBuf; 146 if (!pcsTmp) 147 return VERR_NO_MEMORY; 148 149 uint64_t cbAllWritten = 0; 150 RTTARRECORD record; 151 /* Copy the content from hFile over to the memory. This is done block 152 * wise in 512 byte steps. After this copying is finished hFile will be on 153 * a 512 byte boundary, regardless if the file copied is 512 byte size 154 * aligned. */ 155 for (;;) 156 { 157 if (pfnProgressCallback) 158 pfnProgressCallback((unsigned)(100.0 / cbOverallSize * cbOverallWritten), pvUser); 159 /* Finished already? */ 160 if (cbAllWritten == cbToCopy) 161 break; 162 /* Read one block */ 163 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 164 if (RT_FAILURE(rc)) 165 break; 166 uint64_t cbToWrite = sizeof(record); 167 /* Check for the last block which has not to be 512 bytes in size. */ 168 if (cbAllWritten + cbToWrite > cbToCopy) 169 cbToWrite = cbToCopy - cbAllWritten; 170 /* Write the block */ 171 memcpy(pcsTmp, &record, cbToWrite); 172 /* Count how many bytes are written already */ 173 cbAllWritten += cbToWrite; 174 cbOverallWritten += cbToWrite; 175 pcsTmp += cbToWrite; 176 } 177 178 /* Make sure the called doesn't mix truncated tar files with the official 179 * end indicated by rtTarCalcChkSum. */ 180 if (rc == VERR_EOF) 181 rc = VERR_FILE_IO_ERROR; 182 183 if (RT_FAILURE(rc)) 184 RTMemFree(*ppvBuf); 185 else 186 *pcbSize = cbToCopy; 187 188 return rc; 136 189 } 137 190 … … 516 569 RTMemFree(papszFiles); 517 570 } 571 return rc; 572 } 573 574 RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, uint64_t *pcbSize, const char *pszFile, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 575 { 576 /* Validate input */ 577 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 578 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 579 580 /* Open the tar file */ 581 RTFILE hFile; 582 int rc = RTFileOpen(&hFile, pszTarFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 583 if (RT_FAILURE(rc)) 584 return rc; 585 586 /* Get the overall size of all files to extract out of the tar archive 587 headers. Only necessary if there is a progress callback. */ 588 uint64_t cbOverallSize = 0; 589 if (pfnProgressCallback) 590 rc = rtTarGetFilesOverallSize(hFile, &pszFile, 1, &cbOverallSize); 591 if (RT_SUCCESS(rc)) 592 { 593 /* Iterate through the tar file record by record. */ 594 RTTARRECORD record; 595 bool fFound = false; 596 uint64_t cbOverallWritten = 0; 597 for (;;) 598 { 599 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 600 /* Check for error or EOF. */ 601 if (RT_FAILURE(rc)) 602 break; 603 /* Check for EOF & data integrity */ 604 rc = rtTarCheckHeader(&record); 605 if (RT_FAILURE(rc)) 606 break; 607 /* We support normal files only */ 608 if ( record.h.linkflag == LF_OLDNORMAL 609 || record.h.linkflag == LF_NORMAL) 610 { 611 if (!RTStrCmp(record.h.name, pszFile)) 612 { 613 fFound = true; 614 rc = rtTarCopyFileFromToBuf(hFile, ppvBuf, pcbSize, &record, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser); 615 /* We are finished */ 616 break; 617 } 618 else 619 { 620 rc = rtTarSkipData(hFile, &record); 621 if (RT_FAILURE(rc)) 622 break; 623 } 624 } 625 } 626 627 if (rc == VERR_EOF) 628 rc = VINF_SUCCESS; 629 630 /* If we didn't found the file, indicate an error */ 631 if (!fFound && RT_SUCCESS(rc)) 632 rc = VERR_FILE_NOT_FOUND; 633 } 634 635 RTFileClose(hFile); 518 636 return rc; 519 637 }
Note:
See TracChangeset
for help on using the changeset viewer.