Changeset 33804 in vbox for trunk/src/VBox/Runtime/common/misc/tar.cpp
- Timestamp:
- Nov 5, 2010 5:16:12 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/tar.cpp
r33540 r33804 41 41 #include <iprt/string.h> 42 42 43 43 44 /****************************************************************************** 44 45 * Structures and Typedefs * … … 58 59 /** @} */ 59 60 61 /** 62 * A tar file header. 63 */ 60 64 typedef union RTTARRECORD 61 65 { … … 79 83 } h; 80 84 } RTTARRECORD; 81 typedef RTTARRECORD *PRTTARRECORD;82 85 AssertCompileSize(RTTARRECORD, 512); 83 86 AssertCompileMemberOffset(RTTARRECORD, h.size, 100+8*3); 87 /** Pointer to a tar file header. */ 88 typedef RTTARRECORD *PRTTARRECORD; 89 84 90 85 91 #if 0 /* not currently used */ … … 92 98 #endif 93 99 94 typedef struct RTTARFILEINTERNAL* PRTTARFILEINTERNAL; 100 /** Pointer to a tar file handle. */ 101 typedef struct RTTARFILEINTERNAL *PRTTARFILEINTERNAL; 102 103 /** 104 * The internal data of a tar handle. 105 */ 95 106 typedef struct RTTARINTERNAL 96 107 { 108 /** The magic (RTTAR_MAGIC). */ 109 uint32_t u32Magic; 110 /** The handle to the tar file. */ 111 RTFILE hTarFile; 112 /** The open mode for hTarFile. */ 113 uint32_t fOpenMode; 114 /** Whether a file within the archive is currently open for writing. 115 * Only one can be open. */ 116 bool fFileOpenForWrite; 117 /** Whether operating in stream mode. */ 118 bool fStreamMode; 119 /** The file cache of one file. */ 120 PRTTARFILEINTERNAL pFileCache; 121 } RTTARINTERNAL; 122 /** Pointer to a the internal data of a tar handle. */ 123 typedef RTTARINTERNAL* PRTTARINTERNAL; 124 125 /** 126 * The internal data of a file within a tar file. 127 */ 128 typedef struct RTTARFILEINTERNAL 129 { 130 /** The magic (RTTARFILE_MAGIC). */ 97 131 uint32_t u32Magic; 98 RTFILE hTarFile; 99 bool fFileOpenForWrite; 100 uint32_t fOpenMode; 101 bool fStreamMode; 102 PRTTARFILEINTERNAL pFileCache; 103 } RTTARINTERNAL; 104 typedef RTTARINTERNAL* PRTTARINTERNAL; 105 106 typedef struct RTTARFILEINTERNAL 107 { 108 uint32_t u32Magic; 132 /** Pointer to back to the tar file. */ 109 133 PRTTARINTERNAL pTar; 134 /** The name of the file. */ 110 135 char *pszFilename; 111 uint64_t uStart; 136 /** The offset into the archive where the file header starts. */ 137 uint64_t offStart; 138 /** The size of the file. */ 112 139 uint64_t cbSize; 140 /** The size set by RTTarFileSetSize(). */ 113 141 uint64_t cbSetSize; 114 uint64_t uCurrentPos; 142 /** The current offset within this file. */ 143 uint64_t offCurrent; 144 /** The open mode. */ 115 145 uint32_t fOpenMode; 116 146 } RTTARFILEINTERNAL; 117 typedef RTTARFILEINTERNAL* PRTTARFILEINTERNAL; 147 /** Pointer to the internal data of a tar file. */ 148 typedef RTTARFILEINTERNAL *PRTTARFILEINTERNAL; 149 118 150 119 151 /****************************************************************************** … … 155 187 } while (0) 156 188 189 157 190 /****************************************************************************** 158 191 * Internal Functions * … … 220 253 } 221 254 222 DECLINLINE(int) rtTarCreateHeaderRecord(PRTTARRECORD pRecord, const char *pszSrcName, uint64_t cbSize, RTUID uid, RTGID gid, RTFMODE fmode, int64_t mtime) 223 { 255 DECLINLINE(int) rtTarCreateHeaderRecord(PRTTARRECORD pRecord, const char *pszSrcName, uint64_t cbSize, 256 RTUID uid, RTGID gid, RTFMODE fmode, int64_t mtime) 257 { 258 /** @todo check for field overflows. */ 224 259 /* Fill the header record */ 225 260 // RT_ZERO(pRecord); … … 236 271 237 272 /* Create the checksum out of the new header */ 238 uint32_t chksum = 0;239 int rc = rtTarCalcChkSum(pRecord, & chksum);273 uint32_t uChkSum = 0; 274 int rc = rtTarCalcChkSum(pRecord, &uChkSum); 240 275 if (RT_FAILURE(rc)) 241 276 return rc; 242 277 /* Format the checksum */ 243 RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", chksum);278 RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", uChkSum); 244 279 245 280 return VINF_SUCCESS; 246 281 } 247 282 248 DECLINLINE(void *) rtTarMemTmpAlloc(size_t *pcbSize)283 DECLINLINE(void *) rtTarMemTmpAlloc(size_t *pcbSize) 249 284 { 250 285 *pcbSize = 0; 251 /* Allocate a reasonably large buffer, fall back on a tiny one. Note:252 * has to be 512 byte aligned and >= 512 byte. */286 /* Allocate a reasonably large buffer, fall back on a tiny one. 287 * Note: has to be 512 byte aligned and >= 512 byte. */ 253 288 size_t cbTmp = _1M; 254 289 void *pvTmp = RTMemTmpAlloc(cbTmp); … … 298 333 pFileInt->u32Magic = RTTARFILE_MAGIC; 299 334 pFileInt->pTar = pInt; 335 pFileInt->fOpenMode = fOpen; 300 336 pFileInt->pszFilename = RTStrDup(pszFilename); 301 pFileInt->fOpenMode = fOpen; 337 if (!pFileInt->pszFilename) 338 { 339 RTMemFree(pFileInt); 340 return NULL; 341 } 302 342 303 343 return pFileInt; … … 312 352 memcpy(pNewInt, pInt, sizeof(RTTARFILEINTERNAL)); 313 353 pNewInt->pszFilename = RTStrDup(pInt->pszFilename); 354 if (!pNewInt->pszFilename) 355 { 356 RTMemFree(pNewInt); 357 return NULL; 358 } 314 359 315 360 return pNewInt; … … 329 374 static int rtTarExtractFileToFile(RTTARFILE hFile, const char *pszTargetName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 330 375 { 376 /* Open the target file */ 331 377 RTFILE hNewFile; 332 /* Open the target file */333 378 int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE); 334 379 if (RT_FAILURE(rc)) 335 380 return rc; 336 381 337 void *pvTmp = 0;382 void *pvTmp = NULL; 338 383 do 339 384 { … … 346 391 break; 347 392 } 393 348 394 /* Get the size of the source file */ 349 395 uint64_t cbToCopy = 0; … … 351 397 if (RT_FAILURE(rc)) 352 398 break; 399 353 400 /* Copy the content from hFile over to pszTargetName. */ 354 401 uint64_t cbAllWritten = 0; /* Already copied */ … … 358 405 if (pfnProgressCallback) 359 406 pfnProgressCallback((unsigned)(100.0 / cbOverallSize * cbOverallWritten), pvUser); 407 360 408 /* Finished already? */ 361 409 if (cbAllWritten == cbToCopy) 362 410 break; 411 363 412 /* Read one block. */ 364 413 cbRead = RT_MIN(cbToCopy - cbAllWritten, cbTmp); … … 366 415 if (RT_FAILURE(rc)) 367 416 break; 417 368 418 /* Write the block */ 369 419 rc = RTFileWrite(hNewFile, pvTmp, cbRead, NULL); 370 420 if (RT_FAILURE(rc)) 371 421 break; 422 372 423 /* Count how many bytes are written already */ 373 424 cbAllWritten += cbRead; … … 375 426 } 376 427 377 } 378 while(0); 428 } while(0); 379 429 380 430 /* Cleanup */ … … 406 456 static int rtTarAppendFileFromFile(RTTAR hTar, const char *pszSrcName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 407 457 { 458 /* Open the source file */ 408 459 RTFILE hOldFile; 409 /* Open the source file */410 460 int rc = RTFileOpen(&hOldFile, pszSrcName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 411 461 if (RT_FAILURE(rc)) … … 413 463 414 464 RTTARFILE hFile = NIL_RTTARFILE; 415 void *pvTmp = 0;465 void *pvTmp = NULL; 416 466 do 417 467 { … … 432 482 RTFMODE fmode = 0600; /* Make some save default */ 433 483 int64_t mtime = 0; 484 434 485 /* This isn't critical. Use the defaults if it fails. */ 435 486 rc = RTFileQueryInfo(hOldFile, &info, RTFSOBJATTRADD_UNIX); … … 441 492 mtime = RTTimeSpecGetSeconds(&info.ModificationTime); 442 493 } 494 443 495 /* Set the mode from the other file */ 444 496 rc = RTTarFileSetMode(hFile, fmode); 445 497 if (RT_FAILURE(rc)) 446 498 break; 499 447 500 /* Set the modification time from the other file */ 448 501 RTTIMESPEC time; … … 451 504 if (RT_FAILURE(rc)) 452 505 break; 506 453 507 /* Set the owner from the other file */ 454 508 rc = RTTarFileSetOwner(hFile, uid, gid); … … 465 519 } 466 520 467 uint64_t cbAllWritten = 0; /* Already copied */468 uint64_t cbRead = 0; /* Actually read in the last step */469 uint64_t cbWrite = 0; /* Actually write in the last step */470 521 /* Copy the content from pszSrcName over to hFile. This is done block 471 522 * wise in 512 byte steps. After this copying is finished hFile will be 472 523 * on a 512 byte boundary, regardless if the file copied is 512 byte 473 524 * size aligned. */ 525 uint64_t cbAllWritten = 0; /* Already copied */ 526 uint64_t cbRead = 0; /* Actually read in the last step */ 527 uint64_t cbWrite = 0; /* Actually write in the last step */ 474 528 for (;;) 475 529 { … … 478 532 if (cbAllWritten >= cbToCopy) 479 533 break; 534 480 535 /* Read one block. Either its the buffer size or the rest of the 481 536 * file. */ 482 537 cbRead = RT_MIN(cbToCopy - cbAllWritten, cbTmp); 483 /* Read one block */484 538 rc = RTFileRead(hOldFile, pvTmp, cbRead, NULL); 485 539 if (RT_FAILURE(rc)) 486 540 break; 541 487 542 /* Write one block. */ 488 543 rc = RTTarFileWriteAt(hFile, cbAllWritten, pvTmp, cbRead, NULL); 489 544 if (RT_FAILURE(rc)) 490 545 break; 546 491 547 /* Count how many bytes (of the original file) are written already */ 492 548 cbAllWritten += cbRead; 493 549 cbOverallWritten += cbRead; 494 550 } 495 } 496 while(0); 551 } while (0); 497 552 498 553 /* Cleanup */ … … 518 573 } 519 574 520 static int rtTarFindFile(RTFILE hFile, const char *pszFile, uint64_t *p uOffset, uint64_t *pcbSize)575 static int rtTarFindFile(RTFILE hFile, const char *pszFile, uint64_t *poff, uint64_t *pcbSize) 521 576 { 522 577 /* Assume we are on the file head. */ 523 int rc= VINF_SUCCESS;524 bool fFound= false;578 int rc = VINF_SUCCESS; 579 bool fFound = false; 525 580 RTTARRECORD record; 526 581 for (;;) … … 531 586 if (RT_FAILURE(rc)) 532 587 break; 588 533 589 /* We support normal files only */ 534 590 if ( record.h.linkflag == LF_OLDNORMAL … … 541 597 if (RT_FAILURE(rc)) 542 598 break; 599 543 600 /* Seek back, to position the file pointer at the start of the header. */ 544 rc = RTFileSeek(hFile, -(int64_t)sizeof(RTTARRECORD), RTFILE_SEEK_CURRENT, p uOffset);601 rc = RTFileSeek(hFile, -(int64_t)sizeof(RTTARRECORD), RTFILE_SEEK_CURRENT, poff); 545 602 fFound = true; 546 603 break; … … 575 632 if (RT_FAILURE(rc)) 576 633 break; 634 577 635 /* We support normal files only */ 578 636 if ( record.h.linkflag == LF_OLDNORMAL … … 583 641 if (!RTStrCmp(record.h.name, papszFiles[i])) 584 642 { 585 uint64_t cbSize;586 643 /* Get the file size */ 644 uint64_t cbSize = 0; 587 645 rc = RTStrToUInt64Full(record.h.size, 8, &cbSize); 646 588 647 /* Sum up the overall size */ 589 648 *pcbOverallSize += cbSize; … … 613 672 ******************************************************************************/ 614 673 615 RTR3DECL(int) RTTarOpen(PRTTAR phTar, const char* pszTarname, uint32_t fMode, bool fStream) 616 { 617 PRTTARINTERNAL pInt = (PRTTARINTERNAL)RTMemAllocZ(sizeof(RTTARINTERNAL)); 618 if (!pInt) 674 RTR3DECL(int) RTTarOpen(PRTTAR phTar, const char *pszTarname, uint32_t fMode, bool fStream) 675 { 676 /* 677 * Create a tar instance. 678 */ 679 PRTTARINTERNAL pThis = (PRTTARINTERNAL)RTMemAllocZ(sizeof(RTTARINTERNAL)); 680 if (!pThis) 619 681 return VERR_NO_MEMORY; 620 682 621 pInt->u32Magic = RTTAR_MAGIC; 622 pInt->fOpenMode = fMode; 623 pInt->fStreamMode = fStream && (fMode & RTFILE_O_READ); 624 625 int rc = VINF_SUCCESS; 626 do 627 { 628 /* Open the tar file. */ 629 rc = RTFileOpen(&pInt->hTarFile, pszTarname, fMode); 630 if (RT_FAILURE(rc)) 631 break; 632 } 633 while(0); 634 635 if (RT_FAILURE(rc)) 636 { 637 /* Todo: remove if created by us */ 638 if (pInt->hTarFile) 639 RTFileClose(pInt->hTarFile); 640 RTMemFree(pInt); 641 }else 642 *phTar = (RTTAR)pInt; 643 683 pThis->u32Magic = RTTAR_MAGIC; 684 pThis->fOpenMode = fMode; 685 pThis->fStreamMode = fStream && (fMode & RTFILE_O_READ); 686 687 /* 688 * Open the tar file. 689 */ 690 int rc = RTFileOpen(&pThis->hTarFile, pszTarname, fMode); 691 if (RT_SUCCESS(rc)) 692 { 693 *phTar = pThis; 694 return VINF_SUCCESS; 695 } 696 697 RTMemFree(pThis); 644 698 return rc; 645 699 } … … 666 720 #endif 667 721 668 if (pInt->hTarFile )722 if (pInt->hTarFile != NIL_RTFILE) 669 723 rc = RTFileClose(pInt->hTarFile); 670 724 … … 673 727 { 674 728 rtDeleteTarFileInternal(pInt->pFileCache); 675 pInt->pFileCache = 0;729 pInt->pFileCache = NULL; 676 730 } 677 731 … … 709 763 710 764 int rc = VINF_SUCCESS; 711 do 765 do /* break loop */ 712 766 { 713 767 if (pFileInt->fOpenMode & RTFILE_O_WRITE) 714 768 { 715 769 pInt->fFileOpenForWrite = true; 770 716 771 /* If we are in write mode, we also in append mode. Add an dummy 717 772 * header at the end of the current file. It will be filled by the 718 773 * close operation. */ 719 rc = RTFileSeek(pFileInt->pTar->hTarFile, 0, RTFILE_SEEK_END, &pFileInt-> uStart);774 rc = RTFileSeek(pFileInt->pTar->hTarFile, 0, RTFILE_SEEK_END, &pFileInt->offStart); 720 775 if (RT_FAILURE(rc)) 721 776 break; … … 732 787 if (RT_FAILURE(rc)) 733 788 break; 789 734 790 /* Search for the file. */ 735 rc = rtTarFindFile(pFileInt->pTar->hTarFile, pszFilename, &pFileInt-> uStart, &pFileInt->cbSize);791 rc = rtTarFindFile(pFileInt->pTar->hTarFile, pszFilename, &pFileInt->offStart, &pFileInt->cbSize); 736 792 if (RT_FAILURE(rc)) 737 793 break; … … 739 795 else 740 796 { 741 }742 743 } 744 while(0);797 /** @todo is something missing here? */ 798 } 799 800 } while (0); 745 801 746 802 /* Cleanup on failure */ … … 773 829 /* In read mode, we want to make sure to stay at the aligned end of this 774 830 * file, so the next file could be read immediately. */ 775 uint64_t uCurPos = RTFileTell(pFileInt->pTar->hTarFile); 831 uint64_t offCur = RTFileTell(pFileInt->pTar->hTarFile); 832 776 833 /* Check that the file pointer is somewhere within the last open file. 777 834 * If we are at the beginning (nothing read yet) nothing will be done. 778 835 * A user could open/close a file more than once, without reading 779 836 * something. */ 780 if (pFileInt->uStart + sizeof(RTTARRECORD) < uCurPos && uCurPos < RT_ALIGN(pFileInt->uStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD))) 837 if ( pFileInt->offStart + sizeof(RTTARRECORD) < offCur 838 && offCur < RT_ALIGN(pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD))) 781 839 { 782 840 /* Seek to the next file header. */ 783 uint64_t uNextPos = RT_ALIGN(pFileInt->uStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD));784 rc = RTFileSeek(pFileInt->pTar->hTarFile, uNextPos - uCurPos, RTFILE_SEEK_CURRENT, NULL);841 uint64_t offNext = RT_ALIGN(pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize, sizeof(RTTARRECORD)); 842 rc = RTFileSeek(pFileInt->pTar->hTarFile, offNext - offCur, RTFILE_SEEK_CURRENT, NULL); 785 843 } 786 844 } … … 798 856 break; 799 857 } 858 800 859 /* If the written size isn't 512 byte aligned, we need to fix this. */ 801 860 RTTARRECORD record; … … 805 864 { 806 865 /* Note the RTFile method. We didn't increase the cbSize or cbCurrentPos here. */ 807 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->uStart + sizeof(RTTARRECORD) + pFileInt->cbSize, &record, cbSizeAligned - pFileInt->cbSize, NULL); 866 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, 867 pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize, 868 &record, 869 cbSizeAligned - pFileInt->cbSize, 870 NULL); 808 871 if (RT_FAILURE(rc)) 809 872 break; 810 873 } 874 811 875 /* Create a header record for the file */ 812 876 /* Todo: mode, gid, uid, mtime should be setable (or detected myself) */ 813 877 RTTIMESPEC time; 814 878 RTTimeNow(&time); 815 rc = rtTarCreateHeaderRecord(&record, pFileInt->pszFilename, pFileInt->cbSize, 0, 0, 0600, RTTimeSpecGetSeconds(&time)); 879 rc = rtTarCreateHeaderRecord(&record, pFileInt->pszFilename, pFileInt->cbSize, 880 0, 0, 0600, RTTimeSpecGetSeconds(&time)); 816 881 if (RT_FAILURE(rc)) 817 882 break; 883 818 884 /* Write this at the start of the file data */ 819 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt-> uStart, &record, sizeof(RTTARRECORD), NULL);885 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart, &record, sizeof(RTTARRECORD), NULL); 820 886 if (RT_FAILURE(rc)) 821 887 break; … … 830 896 } 831 897 832 RTR3DECL(int) RTTarFileSeek(RTTARFILE hFile, uint64_t uOffset,unsigned uMethod, uint64_t *poffActual)898 RTR3DECL(int) RTTarFileSeek(RTTARFILE hFile, uint64_t offSeek, unsigned uMethod, uint64_t *poffActual) 833 899 { 834 900 PRTTARFILEINTERNAL pFileInt = hFile; … … 842 908 case RTFILE_SEEK_BEGIN: 843 909 { 844 if ( uOffset> pFileInt->cbSize)910 if (offSeek > pFileInt->cbSize) 845 911 return VERR_SEEK_ON_DEVICE; 846 pFileInt-> uCurrentPos = uOffset;912 pFileInt->offCurrent = offSeek; 847 913 break; 848 914 } 849 915 case RTFILE_SEEK_CURRENT: 850 916 { 851 if (pFileInt-> uCurrentPos + uOffset> pFileInt->cbSize)917 if (pFileInt->offCurrent + offSeek > pFileInt->cbSize) 852 918 return VERR_SEEK_ON_DEVICE; 853 pFileInt-> uCurrentPos += uOffset;919 pFileInt->offCurrent += offSeek; 854 920 break; 855 921 } 856 922 case RTFILE_SEEK_END: 857 923 { 858 if ((int64_t)pFileInt->cbSize - (int64_t) uOffset< 0)924 if ((int64_t)pFileInt->cbSize - (int64_t)offSeek < 0) 859 925 return VERR_NEGATIVE_SEEK; 860 pFileInt-> uCurrentPos = pFileInt->cbSize - uOffset;926 pFileInt->offCurrent = pFileInt->cbSize - offSeek; 861 927 break; 862 928 } … … 870 936 { 871 937 PRTTARFILEINTERNAL pFileInt = hFile; 872 RTTARFILE_VALID_RETURN_RC(pFileInt, ~0ULL);873 874 return pFileInt-> uCurrentPos;938 RTTARFILE_VALID_RETURN_RC(pFileInt, UINT64_MAX); 939 940 return pFileInt->offCurrent; 875 941 } 876 942 … … 881 947 882 948 /* Todo: optimize this, by checking the current pos */ 883 return RTTarFileReadAt(hFile, pFileInt-> uCurrentPos, pvBuf, cbToRead, pcbRead);884 } 885 886 RTR3DECL(int) RTTarFileReadAt(RTTARFILE hFile, uint64_t uOffset, void *pvBuf, size_t cbToRead, size_t *pcbRead)949 return RTTarFileReadAt(hFile, pFileInt->offCurrent, pvBuf, cbToRead, pcbRead); 950 } 951 952 RTR3DECL(int) RTTarFileReadAt(RTTARFILE hFile, uint64_t off, void *pvBuf, size_t cbToRead, size_t *pcbRead) 887 953 { 888 954 PRTTARFILEINTERNAL pFileInt = hFile; … … 890 956 891 957 /* Check that we not read behind the end of file. If so return immediately. */ 892 if ( uOffset> pFileInt->cbSize)958 if (off > pFileInt->cbSize) 893 959 { 894 960 if (pcbRead) … … 897 963 } 898 964 899 size_t cbToCopy = RT_MIN(pFileInt->cbSize - uOffset, cbToRead);965 size_t cbToCopy = RT_MIN(pFileInt->cbSize - off, cbToRead); 900 966 size_t cbTmpRead = 0; 901 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt-> uStart + 512 + uOffset, pvBuf, cbToCopy, &cbTmpRead);902 pFileInt-> uCurrentPos = uOffset+ cbTmpRead;967 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->offStart + 512 + off, pvBuf, cbToCopy, &cbTmpRead); 968 pFileInt->offCurrent = off + cbTmpRead; 903 969 if (pcbRead) 904 970 *pcbRead = cbTmpRead; … … 912 978 RTTARFILE_VALID_RETURN(pFileInt); 913 979 914 /* Todo: optimize this, by checking the current pos */915 return RTTarFileWriteAt(hFile, pFileInt-> uCurrentPos, pvBuf, cbToWrite, pcbWritten);916 } 917 918 RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t uOffset, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)980 /** @todo Optimize this, by checking the current pos */ 981 return RTTarFileWriteAt(hFile, pFileInt->offCurrent, pvBuf, cbToWrite, pcbWritten); 982 } 983 984 RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) 919 985 { 920 986 PRTTARFILEINTERNAL pFileInt = hFile; … … 925 991 926 992 size_t cbTmpWritten = 0; 927 int rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt-> uStart + 512 + uOffset, pvBuf, cbToWrite, &cbTmpWritten);993 int rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart + 512 + off, pvBuf, cbToWrite, &cbTmpWritten); 928 994 pFileInt->cbSize += cbTmpWritten; 929 pFileInt-> uCurrentPos = uOffset+ cbTmpWritten;995 pFileInt->offCurrent = off + cbTmpWritten; 930 996 if (pcbWritten) 931 997 *pcbWritten = cbTmpWritten; … … 955 1021 return VERR_WRITE_ERROR; 956 1022 957 /* Todo: if cbSize is smaller than pFileInt->cbSize we have to truncate the958 1023 /** @todo If cbSize is smaller than pFileInt->cbSize we have to 1024 * truncate the current file. */ 959 1025 pFileInt->cbSetSize = cbSize; 960 1026 … … 971 1037 972 1038 /* Read the mode out of the header entry */ 973 char mode[8]; 974 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.mode), mode, 8, NULL); 1039 char szMode[RT_SIZEOFMEMB(RTTARRECORD, h.mode)+1]; 1040 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, 1041 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mode), 1042 szMode, 1043 RT_SIZEOFMEMB(RTTARRECORD, h.mode), 1044 NULL); 975 1045 if (RT_FAILURE(rc)) 976 1046 return rc; 1047 szMode[sizeof(szMode) - 1] = '\0'; 1048 977 1049 /* Convert it to an integer */ 978 return RTStrToUInt32Full( mode, 8, pfMode);1050 return RTStrToUInt32Full(szMode, 8, pfMode); 979 1051 } 980 1052 … … 988 1060 989 1061 /* Convert the mode to an string. */ 990 char mode[8]; 991 RTStrPrintf(mode, sizeof(mode), "%0.7o", fMode); 1062 char szMode[RT_SIZEOFMEMB(RTTARRECORD, h.mode)]; 1063 RTStrPrintf(szMode, sizeof(szMode), "%0.7o", fMode); 1064 992 1065 /* Write it directly into the header */ 993 return RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.mode), mode, 8, NULL); 1066 return RTFileWriteAt(pFileInt->pTar->hTarFile, 1067 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mode), 1068 szMode, 1069 RT_SIZEOFMEMB(RTTARRECORD, h.mode), 1070 NULL); 994 1071 } 995 1072 … … 1000 1077 1001 1078 /* Read the time out of the header entry */ 1002 char mtime[12]; 1003 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.mtime), mtime, 12, NULL); 1079 char szModTime[RT_SIZEOFMEMB(RTTARRECORD, h.mtime) + 1]; 1080 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, 1081 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mtime), 1082 szModTime, 1083 RT_SIZEOFMEMB(RTTARRECORD, h.mtime), 1084 NULL); 1004 1085 if (RT_FAILURE(rc)) 1005 1086 return rc; 1087 szModTime[sizeof(szModTime) - 1] = '\0'; 1088 1006 1089 /* Convert it to an integer */ 1007 int64_t tmpSeconds; 1008 rc = RTStrToInt64Full(mtime, 12, &tmpSeconds); 1090 int64_t cSeconds; 1091 rc = RTStrToInt64Full(szModTime, 12, &cSeconds); 1092 1009 1093 /* And back to our time structure */ 1010 1094 if (RT_SUCCESS(rc)) 1011 RTTimeSpecSetSeconds(pTime, tmpSeconds);1095 RTTimeSpecSetSeconds(pTime, cSeconds); 1012 1096 1013 1097 return rc; … … 1023 1107 1024 1108 /* Convert the time to an string. */ 1025 char mtime[12]; 1026 RTStrPrintf(mtime, sizeof(mtime), "%0.11o", RTTimeSpecGetSeconds(pTime)); 1109 char szModTime[RT_SIZEOFMEMB(RTTARRECORD, h.mtime)]; 1110 RTStrPrintf(szModTime, sizeof(szModTime), "%0.11o", RTTimeSpecGetSeconds(pTime)); 1111 1027 1112 /* Write it directly into the header */ 1028 return RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.mtime), mtime, 12, NULL); 1113 return RTFileWriteAt(pFileInt->pTar->hTarFile, 1114 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mtime), 1115 szModTime, 1116 RT_SIZEOFMEMB(RTTARRECORD, h.mtime), 1117 NULL); 1029 1118 } 1030 1119 … … 1035 1124 1036 1125 /* Read the uid and gid out of the header entry */ 1037 char uid[8]; 1038 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.uid), uid, 8, NULL); 1126 AssertCompileAdjacentMembers(RTTARRECORD, h.uid, h.gid); 1127 char szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid) + RT_SIZEOFMEMB(RTTARRECORD, h.gid) + 1]; 1128 int rc = RTFileReadAt(pFileInt->pTar->hTarFile, 1129 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.uid), 1130 szUidGid, 1131 sizeof(szUidGid) - 1, 1132 NULL); 1039 1133 if (RT_FAILURE(rc)) 1040 1134 return rc; 1041 char gid[8]; 1042 rc = RTFileReadAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.gid), gid, 8, NULL); 1043 if (RT_FAILURE(rc)) 1044 return rc; 1135 szUidGid[sizeof(szUidGid) - 1] = '\0'; 1136 1045 1137 /* Convert it to integer */ 1046 rc = RTStrToUInt32Full(uid, 8, pUid); 1047 if (RT_FAILURE(rc)) 1048 return rc; 1049 1050 return RTStrToUInt32Full(gid, 8, pGid); 1138 rc = RTStrToUInt32Full(&szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid)], 8, pGid); 1139 if (RT_SUCCESS(rc)) 1140 { 1141 szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid)] = '\0'; 1142 rc = RTStrToUInt32Full(szUidGid, 8, pUid); 1143 } 1144 return rc; 1051 1145 } 1052 1146 … … 1058 1152 if ((pFileInt->fOpenMode & RTFILE_O_WRITE) != RTFILE_O_WRITE) 1059 1153 return VERR_WRITE_ERROR; 1154 AssertReturn(uid == (uint32_t)-1 || uid <= 07777777, VERR_OUT_OF_RANGE); 1155 AssertReturn(gid == (uint32_t)-1 || gid <= 07777777, VERR_OUT_OF_RANGE); 1060 1156 1061 1157 int rc = VINF_SUCCESS; … … 1064 1160 { 1065 1161 /* Convert the uid to an string. */ 1066 char tmpUid[8]; 1067 RTStrPrintf(tmpUid, sizeof(tmpUid), "%0.7o", uid); 1162 char szUid[RT_SIZEOFMEMB(RTTARRECORD, h.uid)]; 1163 RTStrPrintf(szUid, sizeof(szUid), "%0.7o", uid); 1164 1068 1165 /* Write it directly into the header */ 1069 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.uid), tmpUid, 8, NULL); 1166 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, 1167 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.uid), 1168 szUid, 1169 RT_SIZEOFMEMB(RTTARRECORD, h.uid), 1170 NULL); 1070 1171 if (RT_FAILURE(rc)) 1071 1172 return rc; 1072 1173 } 1174 1073 1175 if (gid != (uint32_t)-1) 1074 1176 { 1075 1177 /* Convert the gid to an string. */ 1076 char tmpGid[8]; 1077 RTStrPrintf(tmpGid, sizeof(tmpGid), "%0.7o", gid); 1178 char szGid[RT_SIZEOFMEMB(RTTARRECORD, h.gid)]; 1179 RTStrPrintf(szGid, sizeof(szGid), "%0.7o", gid); 1180 1078 1181 /* Write it directly into the header */ 1079 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->uStart + RT_OFFSETOF(RTTARRECORD, h.gid), tmpGid, 8, NULL); 1182 rc = RTFileWriteAt(pFileInt->pTar->hTarFile, 1183 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.gid), 1184 szGid, 1185 RT_SIZEOFMEMB(RTTARRECORD, h.gid), 1186 NULL); 1080 1187 if (RT_FAILURE(rc)) 1081 1188 return rc; … … 1097 1204 /* Open the tar file */ 1098 1205 RTTAR hTar; 1099 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false );1206 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/); 1100 1207 if (RT_FAILURE(rc)) 1101 1208 return rc; … … 1121 1228 /* Open the tar file */ 1122 1229 RTTAR hTar; 1123 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false );1230 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/); 1124 1231 if (RT_FAILURE(rc)) 1125 1232 return rc; … … 1129 1236 1130 1237 PRTTARINTERNAL pInt = hTar; 1131 char **papszFiles = 0;1238 char **papszFiles = NULL; 1132 1239 size_t cFiles = 0; 1133 do 1240 do /* break loop */ 1134 1241 { 1135 1242 /* Initialize the file name array with one slot */ 1136 1243 size_t cFilesAlloc = 1; 1137 papszFiles = (char **)RTMemAlloc(sizeof(char *));1244 papszFiles = (char **)RTMemAlloc(sizeof(char *)); 1138 1245 if (!papszFiles) 1139 1246 { 1140 r eturnVERR_NO_MEMORY;1247 rc = VERR_NO_MEMORY; 1141 1248 break; 1142 1249 } … … 1185 1292 break; 1186 1293 } 1187 } 1188 while(0); 1294 } while(0); 1189 1295 1190 1296 if (rc == VERR_TAR_END_OF_FILE) … … 1209 1315 } 1210 1316 1211 RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, size_t *pcbSize, const char *pszFile, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 1212 { 1213 /* Validate input */ 1317 RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, size_t *pcbSize, const char *pszFile, 1318 PFNRTPROGRESS pfnProgressCallback, void *pvUser) 1319 { 1320 /* 1321 * Validate input 1322 */ 1214 1323 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 1215 1324 AssertPtrReturn(ppvBuf, VERR_INVALID_POINTER); … … 1219 1328 AssertPtrNullReturn(pvUser, VERR_INVALID_POINTER); 1220 1329 1221 /* Todo: progress bar*/1222 1223 int rc= VINF_SUCCESS;1224 RTTAR hTar= NIL_RTTAR;1225 RTTARFILE hFile= NIL_RTTARFILE;1226 char *pvTmp = 0;1227 uint64_t cbToCopy= 0;1228 do 1229 { 1230 rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false );1330 /** @todo progress bar - is this TODO still valid? */ 1331 1332 int rc = VINF_SUCCESS; 1333 RTTAR hTar = NIL_RTTAR; 1334 RTTARFILE hFile = NIL_RTTARFILE; 1335 char *pvTmp = NULL; 1336 uint64_t cbToCopy= 0; 1337 do /* break loop */ 1338 { 1339 rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/); 1231 1340 if (RT_FAILURE(rc)) 1232 1341 break; … … 1237 1346 if (RT_FAILURE(rc)) 1238 1347 break; 1348 1239 1349 /* Allocate the memory for the file content. */ 1240 pvTmp = (char *)RTMemAlloc(cbToCopy);1350 pvTmp = (char *)RTMemAlloc(cbToCopy); 1241 1351 if (!pvTmp) 1242 1352 { … … 1257 1367 cbAllRead += cbRead; 1258 1368 } 1259 } 1260 while(0); 1369 } while (0); 1261 1370 1262 1371 /* Set output values on success */ … … 1279 1388 } 1280 1389 1281 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 1390 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, 1391 size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 1282 1392 { 1283 1393 /* Validate input */ … … 1291 1401 /* Open the tar file */ 1292 1402 RTTAR hTar; 1293 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false );1403 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/); 1294 1404 if (RT_FAILURE(rc)) 1295 1405 return rc; 1296 1406 1297 do 1407 do /* break loop */ 1298 1408 { 1299 1409 /* Get the overall size of all files to extract out of the tar archive … … 1315 1425 break; 1316 1426 char *pszTargetFile = RTPathJoinA(pszOutputDir, papszFiles[i]); 1317 if (!pszTargetFile) 1318 { 1427 if (pszTargetFile) 1428 rc = rtTarExtractFileToFile(hFile, pszTargetFile, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser); 1429 else 1319 1430 rc = VERR_NO_STR_MEMORY; 1320 break;1321 }1322 rc = rtTarExtractFileToFile(hFile, pszTargetFile, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser);1323 1431 RTStrFree(pszTargetFile); 1324 1432 RTTarFileClose(hFile); … … 1326 1434 break; 1327 1435 } 1328 } 1329 while(0); 1436 } while (0); 1330 1437 1331 1438 RTTarClose(hTar); … … 1364 1471 1365 1472 RTTAR hTar; 1366 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_NONE, false );1473 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_NONE, false /*fStream*/); 1367 1474 if (RT_FAILURE(rc)) 1368 1475 return rc; … … 1431 1538 if (!pInt->pFileCache) 1432 1539 { 1433 rc = RTTarCurrentFile(hTar, 0);1540 rc = RTTarCurrentFile(hTar, NULL); 1434 1541 if (RT_FAILURE(rc)) 1435 1542 return rc; … … 1438 1545 /* Check that the file pointer is somewhere within the last open file. 1439 1546 * If not we are somehow busted. */ 1440 uint64_t uCurPos = RTFileTell(pInt->hTarFile); 1441 if (!(pInt->pFileCache->uStart <= uCurPos && uCurPos < pInt->pFileCache->uStart + sizeof(RTTARRECORD) + pInt->pFileCache->cbSize)) 1547 uint64_t offCur = RTFileTell(pInt->hTarFile); 1548 if (!( pInt->pFileCache->offStart <= offCur 1549 && offCur < pInt->pFileCache->offStart + sizeof(RTTARRECORD) + pInt->pFileCache->cbSize)) 1442 1550 return VERR_INVALID_STATE; 1443 1551 1444 1552 /* Seek to the next file header. */ 1445 uint64_t uNextPos = RT_ALIGN(pInt->pFileCache->uStart + sizeof(RTTARRECORD) + pInt->pFileCache->cbSize, sizeof(RTTARRECORD));1446 rc = RTFileSeek(pInt->hTarFile, uNextPos - uCurPos, RTFILE_SEEK_CURRENT, NULL);1553 uint64_t offNext = RT_ALIGN(pInt->pFileCache->offStart + sizeof(RTTARRECORD) + pInt->pFileCache->cbSize, sizeof(RTTARRECORD)); 1554 rc = RTFileSeek(pInt->hTarFile, offNext - offCur, RTFILE_SEEK_CURRENT, NULL); 1447 1555 if (RT_FAILURE(rc)) 1448 1556 return rc; 1449 1557 1450 1558 /* Again check the current filename to fill the cache with the new value. */ 1451 return RTTarCurrentFile(hTar, 0);1559 return RTTarCurrentFile(hTar, NULL); 1452 1560 } 1453 1561 … … 1471 1579 { 1472 1580 /* Are we still direct behind that header? */ 1473 if (pInt->pFileCache-> uStart + sizeof(RTTARRECORD) == RTFileTell(pInt->hTarFile))1581 if (pInt->pFileCache->offStart + sizeof(RTTARRECORD) == RTFileTell(pInt->hTarFile)) 1474 1582 { 1475 1583 /* Yes, so the streaming can start. Just return the cached file … … 1479 1587 *ppszFilename = RTStrDup(pInt->pFileCache->pszFilename); 1480 1588 return VINF_SUCCESS; 1481 }else 1482 { 1483 /* Else delete the last open file cache. Might be recreated below. */ 1484 rtDeleteTarFileInternal(pInt->pFileCache); 1485 pInt->pFileCache = 0; 1486 } 1487 } 1488 1489 PRTTARFILEINTERNAL pFileInt = 0; 1490 do 1589 } 1590 1591 /* Else delete the last open file cache. Might be recreated below. */ 1592 rtDeleteTarFileInternal(pInt->pFileCache); 1593 pInt->pFileCache = NULL; 1594 } 1595 1596 PRTTARFILEINTERNAL pFileInt = NULL; 1597 do /* break loop */ 1491 1598 { 1492 1599 /* Try to read a header entry from the current position. If we aren't … … 1499 1606 if (RT_FAILURE(rc)) 1500 1607 break; 1608 1501 1609 /* We support normal files only */ 1502 1610 if ( record.h.linkflag == LF_OLDNORMAL … … 1509 1617 break; 1510 1618 } 1619 1511 1620 /* Get the file size */ 1512 1621 rc = RTStrToUInt64Full(record.h.size, 8, &pFileInt->cbSize); 1513 1622 if (RT_FAILURE(rc)) 1514 1623 break; 1624 1515 1625 /* The start is -512 from here. */ 1516 pFileInt->uStart = RTFileTell(pInt->hTarFile) - sizeof(RTTARRECORD); 1626 pFileInt->offStart = RTFileTell(pInt->hTarFile) - sizeof(RTTARRECORD); 1627 1517 1628 /* Copy the new file structure to our cache. */ 1518 1629 pInt->pFileCache = rtCopyTarFileInternal(pFileInt); … … 1520 1631 *ppszFilename = RTStrDup(pFileInt->pszFilename); 1521 1632 } 1522 } while (0);1633 } while (0); 1523 1634 1524 1635 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.