Changeset 21810 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Jul 27, 2009 1:01:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/tar.cpp
r21784 r21810 29 29 */ 30 30 31 #include "iprt/tar.h" 32 31 32 /******************************************************************************* 33 * Header Files * 34 *******************************************************************************/ 35 #include "internal/iprt.h" 36 #include <iprt/tar.h> 37 38 #include <iprt/asm.h> 33 39 #include <iprt/assert.h> 40 #include <iprt/err.h> 34 41 #include <iprt/file.h> 42 #include <iprt/mem.h> 35 43 #include <iprt/path.h> 36 #include <iprt/err.h>37 #include <iprt/mem.h>38 #include <iprt/asm.h>39 44 #include <iprt/string.h> 45 40 46 41 47 /******************************************************************************* … … 43 49 *******************************************************************************/ 44 50 45 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */ 46 #define LF_NORMAL '0' /* Normal disk file */ 47 #define LF_LINK '1' /* Link to previously dumped file */ 48 #define LF_SYMLINK '2' /* Symbolic link */ 49 #define LF_CHR '3' /* Character special file */ 50 #define LF_BLK '4' /* Block special file */ 51 #define LF_DIR '5' /* Directory */ 52 #define LF_FIFO '6' /* FIFO special file */ 53 #define LF_CONTIG '7' /* Contiguous file */ 51 /** @name RTTARRECORD::h::linkflag 52 * @{ */ 53 #define LF_OLDNORMAL '\0' /**< Normal disk file, Unix compatible */ 54 #define LF_NORMAL '0' /**< Normal disk file */ 55 #define LF_LINK '1' /**< Link to previously dumped file */ 56 #define LF_SYMLINK '2' /**< Symbolic link */ 57 #define LF_CHR '3' /**< Character special file */ 58 #define LF_BLK '4' /**< Block special file */ 59 #define LF_DIR '5' /**< Directory */ 60 #define LF_FIFO '6' /**< FIFO special file */ 61 #define LF_CONTIG '7' /**< Contiguous file */ 62 /** @} */ 54 63 55 64 typedef union RTTARRECORD … … 75 84 } RTTARRECORD; 76 85 typedef RTTARRECORD *PRTTARRECORD; 77 86 AssertCompileSize(RTTARRECORD, 512); 87 AssertCompileMemberOffset(RTTARRECORD, h.size, 100+8*3); 88 89 #if 0 /* not currently used */ 78 90 typedef struct RTTARFILELIST 79 91 { … … 82 94 } RTTARFILELIST; 83 95 typedef RTTARFILELIST *PRTTARFILELIST; 96 #endif 97 84 98 85 99 /******************************************************************************* 86 * Private RTTar helper*100 * Internal Functions * 87 101 *******************************************************************************/ 88 102 … … 91 105 uint32_t check = 0; 92 106 uint32_t zero = 0; 93 for (size_t i =0; i < sizeof(RTTARRECORD); ++i)107 for (size_t i = 0; i < sizeof(RTTARRECORD); ++i) 94 108 { 95 109 /* Calculate the sum of every byte from the header. The checksum field 96 110 * itself is counted as all blanks. */ 97 if ( i < RT_UOFFSETOF(RTTARRECORD, h.chksum) ||98 i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))111 if ( i < RT_UOFFSETOF(RTTARRECORD, h.chksum) 112 || i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag)) 99 113 check += pRecord->d[i]; 100 114 else … … 123 137 uint32_t sum; 124 138 rc = RTStrToUInt32Full(pRecord->h.chksum, 8, &sum); 125 if ( sum == check)139 if (RT_SUCCESS(rc) && sum == check) 126 140 return VINF_SUCCESS; 127 else 128 return VERR_TAR_CHKSUM_MISMATCH; 129 } 130 131 static int rtTarCopyFileFrom(RTFILE hFile, const char* pszTargetName, PRTTARRECORD pRecord) 141 return VERR_TAR_CHKSUM_MISMATCH; 142 } 143 144 static int rtTarCopyFileFrom(RTFILE hFile, const char *pszTargetName, PRTTARRECORD pRecord) 132 145 { 133 146 RTFILE hNewFile; 134 147 /* Open the target file */ 135 int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE); 136 if (RT_FAILURE(rc)) 137 return rc; 148 int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE); 149 if (RT_FAILURE(rc)) 150 return rc; 151 152 /**@todo r=bird: Use a bigger buffer here, see comment in rtTarCopyFileTo. */ 138 153 139 154 uint64_t cbToCopy = RTStrToUInt64(pRecord->h.size); 140 size_t cbRead = 0;141 size_t cbWritten = 0;142 155 size_t cbAllWritten = 0; 143 156 RTTARRECORD record; … … 146 159 * a 512 byte boundary, regardless if the file copied is 512 byte size 147 160 * aligned. */ 148 do161 for (;;) 149 162 { 150 163 /* Finished already? */ … … 152 165 break; 153 166 /* Read one block */ 154 rc = RTFileRead(hFile, &record, sizeof(record), &cbRead); 155 if (RT_FAILURE(rc) || 156 cbRead != sizeof(record)) 157 { 158 rc = VERR_FILE_IO_ERROR; 159 break; 160 } 167 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 168 if (RT_FAILURE(rc)) 169 break; 161 170 size_t cbToWrite = sizeof(record); 162 171 /* Check for the last block which has not to be 512 bytes in size. */ … … 164 173 cbToWrite = cbToCopy - cbAllWritten; 165 174 /* Write the block */ 166 rc = RTFileWrite(hNewFile, &record, cbToWrite, &cbWritten); 167 if (RT_FAILURE(rc) || 168 cbWritten != cbToWrite) 169 { 170 rc = VERR_FILE_IO_ERROR; 171 break; 172 } 175 rc = RTFileWrite(hNewFile, &record, cbToWrite, NULL); 176 if (RT_FAILURE(rc)) 177 break; 173 178 /* Count how many bytes are written already */ 174 cbAllWritten += cbWritten; 175 } 176 while(1); 179 cbAllWritten += cbToWrite; 180 } 177 181 178 182 /* Now set all file attributes */ … … 188 192 } 189 193 } 194 /* Make sure the called doesn't mix trunacted tar files with the official 195 * end indicated by rtTarCalcChkSum. */ 196 else if (rc == VERR_EOF) 197 rc = VERR_FILE_IO_ERROR; 190 198 191 199 RTFileClose(hNewFile); … … 198 206 } 199 207 200 static int rtTarCopyFileTo(RTFILE hFile, const char *pszSrcName)208 static int rtTarCopyFileTo(RTFILE hFile, const char *pszSrcName) 201 209 { 202 210 RTFILE hOldFile; 203 211 /* Open the source file */ 204 int rc = RTFileOpen(&hOldFile, pszSrcName, RTFILE_O_ READ);212 int rc = RTFileOpen(&hOldFile, pszSrcName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 205 213 if (RT_FAILURE(rc)) 206 214 return rc; … … 232 240 /* Fill the header record */ 233 241 RTTARRECORD record; 234 ASMMemFill32(&record, sizeof(record), 0); /* Initialize with zeros */242 RT_ZERO(record); 235 243 RTStrPrintf(record.h.name, sizeof(record.h.name), "%s", RTPathFilename(pszSrcName)); 236 244 RTStrPrintf(record.h.mode, sizeof(record.h.mode), "%0.7o", fmode); … … 252 260 if (RT_SUCCESS(rc)) 253 261 { 254 size_t cbToRead = 0; 255 size_t cbWritten = 0;256 size_t cbAllWritten = 0;262 /** @todo r=bird: using a 64KB buffer here instead of 0.5KB would probably be 263 * a good thing. */ 264 uint64_t cbAllWritten = 0; 257 265 /* Copy the content from pszSrcName over to hFile. This is done block 258 266 * wise in 512 byte steps. After this copying is finished hFile will be 259 267 * on a 512 byte boundary, regardless if the file copied is 512 byte 260 268 * size aligned. */ 261 do269 for (;;) 262 270 { 263 271 if (cbAllWritten >= cbSize) 264 272 break; 265 cbToRead = sizeof(record);273 size_t cbToRead = sizeof(record); 266 274 /* Last record? */ 267 275 if (cbAllWritten + cbToRead > cbSize) 268 276 { 269 277 /* Initialize with zeros */ 270 ASMMemFill32(&record, sizeof(record), 0);278 RT_ZERO(record); 271 279 cbToRead = cbSize - cbAllWritten; 272 280 } … … 276 284 break; 277 285 /* Write one block */ 278 rc = RTFileWrite(hFile, &record, sizeof(record), &cbWritten);286 rc = RTFileWrite(hFile, &record, sizeof(record), NULL); 279 287 if (RT_FAILURE(rc)) 280 288 break; 281 289 /* Count how many bytes are written already */ 282 cbAllWritten += cbWritten;290 cbAllWritten += sizeof(record); 283 291 } 284 while(1); 292 293 /* Make sure the called doesn't mix trunacted tar files with the official 294 * end indicated by rtTarCalcChkSum. */ 295 if (rc == VERR_EOF) 296 rc == VERR_FILE_IO_ERROR; 285 297 } 286 298 RTFileClose(hOldFile); … … 292 304 { 293 305 int rc = VINF_SUCCESS; 294 uint64_t offAct;295 306 /* Seek over the data parts (512 bytes aligned) */ 296 307 int64_t offSeek = RT_ALIGN(RTStrToInt64(pRecord->h.size), sizeof(RTTARRECORD)); 297 308 if (offSeek > 0) 298 rc = RTFileSeek(hFile, offSeek, RTFILE_SEEK_CURRENT, &offAct); 299 return rc; 300 } 301 302 /******************************************************************************* 303 * Public RTTar interface * 304 *******************************************************************************/ 309 rc = RTFileSeek(hFile, offSeek, RTFILE_SEEK_CURRENT, NULL); 310 return rc; 311 } 312 305 313 306 314 RTR3DECL(int) RTTarExists(const char *pszTarFile, const char *pszFile) 307 315 { 308 316 /* Validate input */ 309 if (RT_UNLIKELY(!pszTarFile || !pszFile)) 310 { 311 AssertMsgFailed(("Must supply pszTarFile, pszFile\n")); 312 return VERR_INVALID_PARAMETER; 313 } 317 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 318 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 314 319 315 320 /* Open the tar file */ … … 321 326 bool fFound = false; 322 327 RTTARRECORD record; 323 size_t cbRead; 324 do 325 { 326 rc = RTFileRead(hFile, &record, sizeof(record), &cbRead); 328 for (;;) 329 { 330 /** @todo r=bird: the reading, validation and EOF check done here should be 331 * moved to a separate helper function. That would make it easiser to 332 * distinguish genuine-end-of-tar-file and VERR_EOF caused by a 333 * trunacted file. That said, rtTarSkipData won't return VERR_EOF, at 334 * least not on unix, since it's not a sin to seek beyond the end of a 335 * file. */ 336 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 327 337 /* Check for error or EOF. */ 328 338 if (RT_FAILURE(rc)) … … 333 343 break; 334 344 /* We support normal files only */ 335 if ( record.h.linkflag == LF_OLDNORMAL ||336 record.h.linkflag == LF_NORMAL)345 if ( record.h.linkflag == LF_OLDNORMAL 346 || record.h.linkflag == LF_NORMAL) 337 347 { 338 348 if (!RTStrCmp(record.h.name, pszFile)) … … 346 356 break; 347 357 } 348 while(1);349 358 350 359 RTFileClose(hFile); … … 354 363 355 364 /* Something found? */ 356 if ( RT_SUCCESS(rc) &&357 fFound == false)365 if ( RT_SUCCESS(rc) 366 && !fFound) 358 367 rc = VERR_FILE_NOT_FOUND; 359 368 … … 364 373 { 365 374 /* Validate input */ 366 if (RT_UNLIKELY(!pszTarFile || !ppapszFiles || !pcFiles)) 367 { 368 AssertMsgFailed(("Must supply pszTarFile, ppapszFiles, pcFiles!\n")); 369 return VERR_INVALID_PARAMETER; 370 } 375 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 376 AssertPtrReturn(ppapszFiles, VERR_INVALID_POINTER); 377 AssertPtrReturn(pcFiles, VERR_INVALID_POINTER); 371 378 372 379 /* Open the tar file */ … … 379 386 * didn't need them. */ 380 387 RTTARRECORD record; 381 size_t cbRead; 382 PRTTARFILELIST pCurr = NULL; 383 PRTTARFILELIST pFirst = NULL; 384 size_t cCount = 0; 385 do 386 { 387 rc = RTFileRead(hFile, &record, sizeof(record), &cbRead); 388 char **papszFiles = NULL; 389 size_t cFilesAlloc = 0; 390 size_t cFiles = 0; 391 for (;;) 392 { 393 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 388 394 /* Check for error or EOF. */ 389 395 if (RT_FAILURE(rc)) … … 394 400 break; 395 401 /* We support normal files only */ 396 if ( record.h.linkflag == LF_OLDNORMAL ||397 record.h.linkflag == LF_NORMAL)402 if ( record.h.linkflag == LF_OLDNORMAL 403 || record.h.linkflag == LF_NORMAL) 398 404 { 399 PRTTARFILELIST pNew = (PRTTARFILELIST)RTMemAllocZ(sizeof(RTTARFILELIST)); 400 ++cCount; 401 /* Fill our linked list */ 402 if (pCurr) 403 pCurr->pNext = pNew; 404 else 405 pFirst = pNew; 406 pCurr = pNew; 407 pCurr->pszFilename = RTStrDup(record.h.name); 405 if (cFiles >= cFilesAlloc) 406 { 407 /* Double the array size, make sure the size doesn't wrap. */ 408 void *pvNew = NULL; 409 size_t cbNew = cFilesAlloc * sizeof(char *) * 2; 410 if (cbNew / sizeof(char *) / 2 == cFilesAlloc) 411 pvNew = RTMemRealloc(papszFiles, cbNew); 412 if (!pvNew) 413 { 414 rc = VERR_NO_MEMORY; 415 break; 416 } 417 papszFiles = (char **)pvNew; 418 cFilesAlloc *= 2; 419 } 420 421 /* Duplicate the name */ 422 papszFiles[cFiles] = RTStrDup(record.h.name); 423 if (!papszFiles[cFiles]) 424 { 425 rc = VERR_NO_MEMORY; 426 break; 427 } 428 cFiles++; 408 429 } 409 430 rc = rtTarSkipData(hFile, &record); … … 411 432 break; 412 433 } 413 while(1);414 434 415 435 RTFileClose(hFile); … … 418 438 rc = VINF_SUCCESS; 419 439 420 /* On success copy the filenames over to the user provided array pointer */ 421 if (RT_SUCCESS(rc) && 422 cCount > 0) 423 { 424 *ppapszFiles = (char**)RTMemAlloc(sizeof(char*)*cCount); 425 pCurr = pFirst; 426 size_t i = 0; 427 while (pCurr) 428 { 429 (*ppapszFiles)[i++] = pCurr->pszFilename; 430 PRTTARFILELIST pTmp = pCurr->pNext; 431 /* Free the linked list node */ 432 RTMemFree(pCurr); 433 pCurr = pTmp; 434 } 435 *pcFiles = cCount; 436 } 437 440 /* Return the file array on success, dispose of it on failure. */ 441 if (RT_SUCCESS(rc)) 442 { 443 *pcFiles = cFiles; 444 *ppapszFiles = papszFiles; 445 } 446 else 447 { 448 while (cFiles-- > 0) 449 RTStrFree(papszFiles[cFiles]); 450 RTMemFree(papszFiles); 451 } 438 452 return rc; 439 453 } … … 442 456 { 443 457 /* Validate input */ 444 if (RT_UNLIKELY(!pszTarFile || !pszOutputDir || !papszFiles)) 445 { 446 AssertMsgFailed(("Must supply pszTarFile, pszOutputDir, papszFiles!\n")); 447 return VERR_INVALID_PARAMETER; 448 } 458 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 459 AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER); 460 AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); 449 461 450 462 /* Open the tar file */ … … 456 468 /* Iterate through the tar file record by record. */ 457 469 RTTARRECORD record; 458 PRTTARFILELIST pCurr = NULL; 459 PRTTARFILELIST pFirst = NULL; 460 size_t cbRead = 0; 461 size_t cCount = 0; 462 do 463 { 464 rc = RTFileRead(hFile, &record, sizeof(record), &cbRead); 465 /* Check for error or EOF. */ 466 if (RT_FAILURE(rc)) 467 break; 468 /* Check for EOF & data integrity */ 469 rc = rtTarCheckHeader(&record); 470 if (RT_FAILURE(rc)) 471 break; 472 /* We support normal files only */ 473 if (record.h.linkflag == LF_OLDNORMAL || 474 record.h.linkflag == LF_NORMAL) 470 char **paExtracted = (char **)RTMemTmpAllocZ(sizeof(char *) * cFiles); 471 if (paExtracted) 472 { 473 size_t cExtracted = 0; 474 for (;;) 475 475 { 476 bool fFound = false; 477 for (size_t i=0; i < cFiles; ++i) 476 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 477 /* Check for error or EOF. */ 478 if (RT_FAILURE(rc)) 479 break; 480 /* Check for EOF & data integrity */ 481 rc = rtTarCheckHeader(&record); 482 if (RT_FAILURE(rc)) 483 break; 484 /* We support normal files only */ 485 if ( record.h.linkflag == LF_OLDNORMAL 486 || record.h.linkflag == LF_NORMAL) 478 487 { 479 if (!RTStrCmp(record.h.name, papszFiles[i])) 488 bool fFound = false; 489 for (size_t i = 0; i < cFiles; ++i) 480 490 { 481 ++cCount; fFound = true; 482 char *pszTargetName; 483 RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, papszFiles[i]); 484 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record); 491 if (!RTStrCmp(record.h.name, papszFiles[i])) 492 { 493 fFound = true; 494 if (cExtracted < cFiles) 495 { 496 char *pszTargetFile; 497 rc = RTStrAPrintf(&pszTargetFile, "%s/%s", pszOutputDir, papszFiles[i]); 498 if (rc > 0) 499 { 500 rc = rtTarCopyFileFrom(hFile, paExtracted[cExtracted], &record); 501 if (RT_SUCCESS(rc)) 502 paExtracted[cExtracted++] = pszTargetFile; 503 else 504 RTStrFree(pszTargetFile); 505 } 506 else 507 rc = VERR_NO_MEMORY; 508 } 509 else 510 rc = VERR_ALREADY_EXISTS; 511 break; 512 } 513 } 514 if (RT_FAILURE(rc)) 515 break; 516 /* If the current record isn't a file in the file list we have to 517 * skip the data */ 518 if (!fFound) 519 { 520 rc = rtTarSkipData(hFile, &record); 485 521 if (RT_FAILURE(rc)) 486 522 break; 487 PRTTARFILELIST pNew = (PRTTARFILELIST)RTMemAllocZ(sizeof(RTTARFILELIST));488 /* Fill our linked list */489 if (pCurr)490 pCurr->pNext = pNew;491 else492 pFirst = pNew;493 pCurr = pNew;494 pCurr->pszFilename = pszTargetName;495 break;496 523 } 497 524 } 525 } 526 527 if (rc == VERR_EOF) 528 rc = VINF_SUCCESS; 529 530 /* If we didn't found all files, indicate an error */ 531 if (cExtracted != cFiles && RT_SUCCESS(rc)) 532 rc = VERR_FILE_NOT_FOUND; 533 534 /* Cleanup the names of the extracted files, deleting them on failure. */ 535 while (cExtracted-- > 0) 536 { 498 537 if (RT_FAILURE(rc)) 499 break; 500 /* If the current record isn't a file in the file list we have to 501 * skip the data */ 502 if (!fFound) 503 { 504 rc = rtTarSkipData(hFile, &record); 505 if (RT_FAILURE(rc)) 506 break; 507 } 538 RTFileDelete(paExtracted[cExtracted]); 539 RTStrFree(paExtracted[cExtracted]); 508 540 } 509 } 510 while(1); 541 RTMemTmpFree(paExtracted); 542 } 543 else 544 rc = VERR_NO_TMP_MEMORY; 511 545 512 546 RTFileClose(hFile); 513 514 if (rc == VERR_EOF) 515 rc = VINF_SUCCESS; 516 517 /* If we didn't found all files, indicate an error */ 518 if (cCount != cFiles) 519 rc = VERR_FILE_NOT_FOUND; 520 521 pCurr = pFirst; 522 while (pCurr) 523 { 524 /* If there was a failure during extraction, delete all files which 525 * were extracted already */ 526 if (RT_FAILURE(rc)) 527 RTFileDelete(pCurr->pszFilename); 528 /* Delete the filename string and the list node */ 529 RTStrFree(pCurr->pszFilename); 530 PRTTARFILELIST pTmp = pCurr->pNext; 531 RTMemFree(pCurr); 532 pCurr = pTmp; 533 } 534 535 return rc; 536 } 537 538 RTR3DECL(int) RTTarExtractIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char** ppszFileName) 547 return rc; 548 } 549 550 RTR3DECL(int) RTTarExtractIndex(const char *pszTarFile, const char *pszOutputDir, size_t iIndex, char **ppszFileName) 539 551 { 540 552 /* Validate input */ 541 if (RT_UNLIKELY(!pszTarFile || !pszOutputDir)) 542 { 543 AssertMsgFailed(("Must supply pszTarFile, pszOutputDir!\n")); 544 return VERR_INVALID_PARAMETER; 545 } 553 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 554 AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER); 546 555 547 556 /* Open the tar file */ … … 553 562 /* Iterate through the tar file record by record. */ 554 563 RTTARRECORD record; 555 size_t cbRead = 0; 556 size_t cCount = 0; 564 size_t iFile = 0; 557 565 bool fFound = false; 558 do559 { 560 rc = RTFileRead(hFile, &record, sizeof(record), &cbRead);566 for (;;) 567 { 568 rc = RTFileRead(hFile, &record, sizeof(record), NULL); 561 569 /* Check for error or EOF. */ 562 570 if (RT_FAILURE(rc)) … … 567 575 break; 568 576 /* We support normal files only */ 569 if ( record.h.linkflag == LF_OLDNORMAL ||570 record.h.linkflag == LF_NORMAL)577 if ( record.h.linkflag == LF_OLDNORMAL 578 || record.h.linkflag == LF_NORMAL) 571 579 { 572 if (iIndex == cCount)580 if (iIndex == iFile) 573 581 { 574 582 fFound = true; 575 583 char *pszTargetName; 576 RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, record.h.name); 577 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record); 578 /* On success copy the filename */ 579 if (RT_SUCCESS(rc) && 580 ppszFileName) 581 *ppszFileName = RTStrDup(record.h.name); 584 rc = RTStrAPrintf(&pszTargetName, "%s/%s", pszOutputDir, record.h.name); 585 if (rc > 0) 586 { 587 rc = rtTarCopyFileFrom(hFile, pszTargetName, &record); 588 /* On success pass on the filename if requested. */ 589 if ( RT_SUCCESS(rc) 590 && ppszFileName) 591 *ppszFileName = pszTargetName; 592 else 593 RTStrFree(pszTargetName); 594 } 595 else 596 rc = VERR_NO_MEMORY; 582 597 break; 583 598 } 584 ++ cCount;599 ++iFile; 585 600 } 586 601 rc = rtTarSkipData(hFile, &record); … … 588 603 break; 589 604 } 590 while(1);591 605 592 606 RTFileClose(hFile); … … 596 610 597 611 /* If we didn't found the index, indicate an error */ 598 if (!fFound )612 if (!fFound && RT_SUCCESS(rc)) 599 613 rc = VERR_FILE_NOT_FOUND; 600 614 … … 605 619 { 606 620 /* Validate input */ 607 if (RT_UNLIKELY(!pszTarFile || !papszFiles)) 608 { 609 AssertMsgFailed(("Must supply pszTarFile, papszFiles!\n")); 610 return VERR_INVALID_PARAMETER; 611 } 621 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER); 622 AssertPtrReturn(papszFiles, VERR_INVALID_POINTER); 612 623 613 624 /* Open the tar file */ 614 625 RTFILE hFile; 615 int rc = RTFileOpen(&hFile, pszTarFile, RTFILE_O_CREATE | RTFILE_O_WRITE );616 if (RT_FAILURE(rc)) 617 return rc; 618 619 for (size_t i =0; i < cFiles; ++i)626 int rc = RTFileOpen(&hFile, pszTarFile, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE); 627 if (RT_FAILURE(rc)) 628 return rc; 629 630 for (size_t i = 0; i < cFiles; ++i) 620 631 { 621 632 rc = rtTarCopyFileTo(hFile, papszFiles[i]); … … 626 637 /* gtar gives a warning, but the documentation says EOF is indicated by a 627 638 * zero block. Disabled for now. */ 628 // if (RT_SUCCESS(rc)) 629 // { 630 // /* Append the EOF record which is filled all by zeros */ 631 // RTTARRECORD record; 632 // ASMMemFill32(&record, sizeof(record), 0); 633 // rc = RTFileWrite(hFile, &record, sizeof(record), NULL); 634 // } 639 #if 0 640 if (RT_SUCCESS(rc)) 641 { 642 /* Append the EOF record which is filled all by zeros */ 643 RTTARRECORD record; 644 ASMMemFill32(&record, sizeof(record), 0); 645 rc = RTFileWrite(hFile, &record, sizeof(record), NULL); 646 } 647 #endif 635 648 636 649 /* Time to close the new tar archive */
Note:
See TracChangeset
for help on using the changeset viewer.