Changeset 31623 in vbox
- Timestamp:
- Aug 13, 2010 12:24:14 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/tar.h
r28800 r31623 4 4 5 5 /* 6 * Copyright (C) 2009 Oracle Corporation6 * Copyright (C) 2009-2010 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 76 76 * (The matching is case sensitive.) 77 77 * 78 * @note Currently only regular files are supported. Also some of the heade 78 * @note Currently only regular files are supported. Also some of the header 79 79 * fields are not used (uid, gid, uname, gname, mtime). 80 80 * 81 81 * @returns iprt status code. 82 82 * 83 * @param pszTarFile Tar file to extract files from. 84 * @param pszOutputDir Where to store the extracted files. Must exist. 85 * @param papszFiles Which files should be extracted. 86 * @param cFiles The number of files in papszFiles. 83 * @param pszTarFile Tar file to extract files from. 84 * @param pszOutputDir Where to store the extracted files. Must exist. 85 * @param papszFiles Which files should be extracted. 86 * @param cFiles The number of files in papszFiles. 87 * @param pfnProgressCallback Progress callback function. Optional. 88 * @param pvUser User defined data for the progress 89 * callback. Optional. 87 90 */ 88 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles );91 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser); 89 92 90 93 /** … … 97 100 * @retval VERR_FILE_NOT_FOUND when the index isn't valid. 98 101 * 99 * @param pszTarFile Tar file to extract the file from. 100 * @param pszOutputDir Where to store the extracted file. Must exist. 101 * @param iIndex Which file should be extracted, 0 based. 102 * @param ppszFileName On success the filename of the extracted file. Must 103 * be freed with RTStrFree. 102 * @param pszTarFile Tar file to extract the file from. 103 * @param pszOutputDir Where to store the extracted file. Must exist. 104 * @param iIndex Which file should be extracted, 0 based. 105 * @param ppszFileName On success the filename of the extracted file. Must 106 * be freed with RTStrFree. 107 * @param pfnProgressCallback Progress callback function. Optional. 108 * @param pvUser User defined data for the progress 109 * callback. Optional. 104 110 */ 105 RTR3DECL(int) RTTarExtractByIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName); 111 RTR3DECL(int) RTTarExtractByIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName, PFNRTPROGRESS pfnProgressCallback, void *pvUser); 112 113 /** 114 * Extract all files of the archive. 115 * 116 * @note Currently only regular files are supported. Also some of the header 117 * fields are not used (uid, gid, uname, gname, mtime). 118 * 119 * @returns iprt status code. 120 * 121 * @param pszTarFile Tar file to extract the files from. 122 * @param pszOutputDir Where to store the extracted files. Must exist. 123 * @param pfnProgressCallback Progress callback function. Optional. 124 * @param pvUser User defined data for the progress 125 * callback. Optional. 126 */ 127 RTR3DECL(int) RTTarExtractAll(const char *pszTarFile, const char *pszOutputDir, PFNRTPROGRESS pfnProgressCallback, void *pvUser); 106 128 107 129 /** … … 112 134 * @returns iprt status code. 113 135 * 114 * @param pszTarFile Where to create the Tar archive. 115 * @param papszFiles Which files should be included. 116 * @param cFiles The number of files in papszFiles. 136 * @param pszTarFile Where to create the Tar archive. 137 * @param papszFiles Which files should be included. 138 * @param cFiles The number of files in papszFiles. 139 * @param pfnProgressCallback Progress callback function. Optional. 140 * @param pvUser User defined data for the progress 141 * callback. Optional. 117 142 */ 118 RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles );143 RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser); 119 144 120 145 /** @} */ -
trunk/src/VBox/Runtime/common/misc/tar.cpp
r28800 r31623 40 40 #include <iprt/string.h> 41 41 42 43 42 /******************************************************************************* 44 43 * Structures and Typedefs * … … 92 91 #endif 93 92 94 95 93 /******************************************************************************* 96 94 * Internal Functions * … … 138 136 } 139 137 140 static int rtTarCopyFileFrom(RTFILE hFile, const char *pszTargetName, PRTTARRECORD pRecord )138 static int rtTarCopyFileFrom(RTFILE hFile, const char *pszTargetName, PRTTARRECORD pRecord, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 141 139 { 142 140 RTFILE hNewFile; … … 157 155 for (;;) 158 156 { 157 if (pfnProgressCallback) 158 pfnProgressCallback(100.0 / cbOverallSize * cbOverallWritten, pvUser); 159 159 /* Finished already? */ 160 160 if (cbAllWritten == cbToCopy) … … 174 174 /* Count how many bytes are written already */ 175 175 cbAllWritten += cbToWrite; 176 cbOverallWritten += cbToWrite; 176 177 } 177 178 … … 202 203 } 203 204 204 static int rtTarCopyFileTo(RTFILE hFile, const char *pszSrcName )205 static int rtTarCopyFileTo(RTFILE hFile, const char *pszSrcName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 205 206 { 206 207 RTFILE hOldFile; … … 268 269 for (;;) 269 270 { 271 if (pfnProgressCallback) 272 pfnProgressCallback(100.0 / cbOverallSize * cbOverallWritten, pvUser); 270 273 if (cbAllWritten >= cbSize) 271 274 break; … … 288 291 /* Count how many bytes are written already */ 289 292 cbAllWritten += sizeof(record); 293 cbOverallWritten += sizeof(record); 290 294 } 291 295 … … 311 315 } 312 316 317 static int rtTarGetFilesOverallSize(RTFILE hFile, const char * const *papszFiles, size_t cFiles, uint64_t *pcbOverallSize) 318 { 319 int rc; 320 size_t cFound = 0; 321 RTTARRECORD record; 322 for (;;) 323 { 324 /** @todo r=bird: the reading, validation and EOF check done here should be 325 * moved to a separate helper function. That would make it easiser to 326 * distinguish genuine-end-of-tar-file and VERR_EOF caused by a 327 * trunacted file. That said, rtTarSkipData won't return VERR_EOF, at 328 * least not on unix, since it's not a sin to seek beyond the end of a 329 * file. */ 330 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 331 /* Check for error or EOF. */ 332 if (RT_FAILURE(rc)) 333 break; 334 /* Check for EOF & data integrity */ 335 rc = rtTarCheckHeader(&record); 336 if (RT_FAILURE(rc)) 337 break; 338 /* We support normal files only */ 339 if ( record.h.linkflag == LF_OLDNORMAL 340 || record.h.linkflag == LF_NORMAL) 341 { 342 for (size_t i = 0; i < cFiles; ++i) 343 { 344 if (!RTStrCmp(record.h.name, papszFiles[i])) 345 { 346 uint64_t cbSize; 347 /* Get the file size */ 348 rc = RTStrToUInt64Full(record.h.size, 8, &cbSize); 349 /* Sum up the overall size */ 350 *pcbOverallSize += cbSize; 351 ++cFound; 352 break; 353 } 354 } 355 if ( cFound == cFiles 356 || RT_FAILURE(rc)) 357 break; 358 } 359 rc = rtTarSkipData(hFile, &record); 360 if (RT_FAILURE(rc)) 361 break; 362 } 363 /* Make sure the file pointer is at the begin of the file again. */ 364 if (RT_SUCCESS(rc)) 365 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_BEGIN, 0); 366 return rc; 367 } 368 369 /******************************************************************************* 370 * Public Functions * 371 *******************************************************************************/ 313 372 314 373 RTR3DECL(int) RTTarQueryFileExists(const char *pszTarFile, const char *pszFile) … … 460 519 } 461 520 462 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles )521 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 463 522 { 464 523 /* Validate input */ … … 473 532 return rc; 474 533 475 /* Iterate through the tar file record by record. */ 476 RTTARRECORD record; 477 char **paExtracted = (char **)RTMemTmpAllocZ(sizeof(char *) * cFiles); 478 if (paExtracted) 479 { 480 size_t cExtracted = 0; 481 for (;;) 482 { 483 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 484 /* Check for error or EOF. */ 485 if (RT_FAILURE(rc)) 486 break; 487 /* Check for EOF & data integrity */ 488 rc = rtTarCheckHeader(&record); 489 if (RT_FAILURE(rc)) 490 break; 491 /* We support normal files only */ 492 if ( record.h.linkflag == LF_OLDNORMAL 493 || record.h.linkflag == LF_NORMAL) 534 /* Get the overall size of all files to extract out of the tar archive 535 headers. Only necessary if there is a progress callback. */ 536 uint64_t cbOverallSize = 0; 537 if (pfnProgressCallback) 538 rc = rtTarGetFilesOverallSize(hFile, papszFiles, cFiles, &cbOverallSize); 539 if (RT_SUCCESS(rc)) 540 { 541 /* Iterate through the tar file record by record. */ 542 RTTARRECORD record; 543 char **paExtracted = (char **)RTMemTmpAllocZ(sizeof(char *) * cFiles); 544 if (paExtracted) 545 { 546 size_t cExtracted = 0; 547 uint64_t cbOverallWritten = 0; 548 for (;;) 494 549 { 495 bool fFound = false; 496 for (size_t i = 0; i < cFiles; ++i) 550 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 551 /* Check for error or EOF. */ 552 if (RT_FAILURE(rc)) 553 break; 554 /* Check for EOF & data integrity */ 555 rc = rtTarCheckHeader(&record); 556 if (RT_FAILURE(rc)) 557 break; 558 /* We support normal files only */ 559 if ( record.h.linkflag == LF_OLDNORMAL 560 || record.h.linkflag == LF_NORMAL) 497 561 { 498 if (!RTStrCmp(record.h.name, papszFiles[i])) 562 bool fFound = false; 563 for (size_t i = 0; i < cFiles; ++i) 499 564 { 500 fFound = true; 501 if (cExtracted < cFiles) 565 if (!RTStrCmp(record.h.name, papszFiles[i])) 502 566 { 503 char *pszTargetFile; 504 rc = RTStrAPrintf(&pszTargetFile, "%s/%s", pszOutputDir, papszFiles[i]); 505 if (rc > 0) 567 fFound = true; 568 if (cExtracted < cFiles) 506 569 { 507 rc = rtTarCopyFileFrom(hFile, pszTargetFile, &record); 508 if (RT_SUCCESS(rc)) 509 paExtracted[cExtracted++] = pszTargetFile; 570 char *pszTargetFile; 571 rc = RTStrAPrintf(&pszTargetFile, "%s/%s", pszOutputDir, papszFiles[i]); 572 if (rc > 0) 573 { 574 rc = rtTarCopyFileFrom(hFile, pszTargetFile, &record, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser); 575 if (RT_SUCCESS(rc)) 576 paExtracted[cExtracted++] = pszTargetFile; 577 else 578 RTStrFree(pszTargetFile); 579 } 510 580 else 511 RTStrFree(pszTargetFile);581 rc = VERR_NO_MEMORY; 512 582 } 513 583 else 514 rc = VERR_NO_MEMORY; 584 rc = VERR_ALREADY_EXISTS; 585 break; 515 586 } 516 else517 rc = VERR_ALREADY_EXISTS;587 } 588 if (RT_FAILURE(rc)) 518 589 break; 590 /* If the current record isn't a file in the file list we have to 591 * skip the data */ 592 if (!fFound) 593 { 594 rc = rtTarSkipData(hFile, &record); 595 if (RT_FAILURE(rc)) 596 break; 519 597 } 520 598 } 599 } 600 601 if (rc == VERR_EOF) 602 rc = VINF_SUCCESS; 603 604 /* If we didn't found all files, indicate an error */ 605 if (cExtracted != cFiles && RT_SUCCESS(rc)) 606 rc = VERR_FILE_NOT_FOUND; 607 608 /* Cleanup the names of the extracted files, deleting them on failure. */ 609 while (cExtracted-- > 0) 610 { 521 611 if (RT_FAILURE(rc)) 522 break; 523 /* If the current record isn't a file in the file list we have to 524 * skip the data */ 525 if (!fFound) 526 { 527 rc = rtTarSkipData(hFile, &record); 528 if (RT_FAILURE(rc)) 529 break; 530 } 612 RTFileDelete(paExtracted[cExtracted]); 613 RTStrFree(paExtracted[cExtracted]); 531 614 } 532 } 533 534 if (rc == VERR_EOF) 535 rc = VINF_SUCCESS; 536 537 /* If we didn't found all files, indicate an error */ 538 if (cExtracted != cFiles && RT_SUCCESS(rc)) 539 rc = VERR_FILE_NOT_FOUND; 540 541 /* Cleanup the names of the extracted files, deleting them on failure. */ 542 while (cExtracted-- > 0) 543 { 544 if (RT_FAILURE(rc)) 545 RTFileDelete(paExtracted[cExtracted]); 546 RTStrFree(paExtracted[cExtracted]); 547 } 548 RTMemTmpFree(paExtracted); 549 } 550 else 551 rc = VERR_NO_TMP_MEMORY; 615 RTMemTmpFree(paExtracted); 616 } 617 else 618 rc = VERR_NO_TMP_MEMORY; 619 } 552 620 553 621 RTFileClose(hFile); … … 555 623 } 556 624 557 RTR3DECL(int) RTTarExtractByIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName )625 RTR3DECL(int) RTTarExtractByIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 558 626 { 559 627 /* Validate input */ … … 592 660 if (rc > 0) 593 661 { 594 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record); 662 uint64_t cbOverallSize; 663 uint64_t cbOverallWritten = 0; 664 /* Get the file size */ 665 rc = RTStrToUInt64Full(record.h.size, 8, &cbOverallSize); 666 if (RT_FAILURE(rc)) 667 break; 668 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser); 595 669 /* On success pass on the filename if requested. */ 596 670 if ( RT_SUCCESS(rc) … … 623 697 } 624 698 625 RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles) 699 RTR3DECL(int) RTTarExtractAll(const char *pszTarFile, const char *pszOutputDir, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 700 { 701 /* Validate input */ 702 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 703 AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER); 704 705 char **papszFiles; 706 size_t cFiles; 707 708 /* First fetch the files names contained in the tar file */ 709 int rc = RTTarList(pszTarFile, &papszFiles, &cFiles); 710 if (RT_FAILURE(rc)) 711 return rc; 712 713 /* Extract all files */ 714 return RTTarExtractFiles(pszTarFile, pszOutputDir, papszFiles, cFiles, pfnProgressCallback, pvUser); 715 } 716 717 RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 626 718 { 627 719 /* Validate input */ … … 635 727 return rc; 636 728 637 for (size_t i = 0; i < cFiles; ++i) 638 { 639 rc = rtTarCopyFileTo(hFile, papszFiles[i]); 640 if (RT_FAILURE(rc)) 641 break; 642 } 643 644 /* gtar gives a warning, but the documentation says EOF is indicated by a 645 * zero block. Disabled for now. */ 729 /* Get the overall size of all files to pack into the tar archive. Only 730 necessary if there is a progress callback. */ 731 uint64_t cbOverallSize = 0; 732 if (pfnProgressCallback) 733 for (size_t i = 0; i < cFiles; ++i) 734 { 735 uint64_t cbSize; 736 rc = RTFileQuerySize(papszFiles[i], &cbSize); 737 if (RT_FAILURE(rc)) 738 break; 739 cbOverallSize += cbSize; 740 } 741 742 if (RT_SUCCESS(rc)) 743 { 744 uint64_t cbOverallWritten = 0; 745 746 for (size_t i = 0; i < cFiles; ++i) 747 { 748 rc = rtTarCopyFileTo(hFile, papszFiles[i], cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser); 749 if (RT_FAILURE(rc)) 750 break; 751 } 752 753 /* gtar gives a warning, but the documentation says EOF is indicated by a 754 * zero block. Disabled for now. */ 646 755 #if 0 647 if (RT_SUCCESS(rc))648 {649 /* Append the EOF record which is filled all by zeros */650 RTTARRECORD record;651 ASMMemFill32(&record, sizeof(record), 0);652 rc = RTFileWrite(hFile, &record, sizeof(record), NULL);653 }756 if (RT_SUCCESS(rc)) 757 { 758 /* Append the EOF record which is filled all by zeros */ 759 RTTARRECORD record; 760 ASMMemFill32(&record, sizeof(record), 0); 761 rc = RTFileWrite(hFile, &record, sizeof(record), NULL); 762 } 654 763 #endif 764 } 655 765 656 766 /* Time to close the new tar archive */
Note:
See TracChangeset
for help on using the changeset viewer.