Changeset 98457 in vbox for trunk/src/VBox/Runtime/common/zip
- Timestamp:
- Feb 3, 2023 10:54:21 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 155711
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/tarvfswriter.cpp
r98325 r98457 54 54 55 55 #include "tarvfsreader.h" 56 #include "cpiovfsreader.h" 56 57 57 58 … … 196 197 /** When in update mode (RTZIPTAR_C_UPDATE) we have an reader FSS instance, 197 198 * though w/o the RTVFSFSSTREAM bits. (Allocated after this structure.) */ 198 PRTZIPTARFSSTREAM pRead; 199 PRTZIPTARFSSTREAM pReadTar; 200 /** Same when a CPIO archive is used. */ 201 /** @todo Possible to merge it with the tar reader maybe? */ 202 PRTZIPCPIOFSSTREAM pReadCpio; 199 203 /** Set if we're in writing mode and pfnNext shall fail. */ 200 204 bool fWriting; … … 203 207 /** Number of headers returned by rtZipTarFssWriter_ObjInfoToHdr. */ 204 208 uint32_t cHdrs; 205 /** Header buffers returned by rtZipTarFssWriter_ObjInfoToHdr. */ 206 RTZIPTARHDR aHdrs[3]; 209 /** Size of a single header returned by rtZipTarFssWriter_ObjInfoToHdr. */ 210 uint32_t cbHdr; 211 /** Format dependent header data. */ 212 union 213 { 214 /** Byte view of the different headers. */ 215 uint8_t abHdrs[512]; 216 /** Header buffers returned by rtZipTarFssWriter_ObjInfoToHdrTar. */ 217 RTZIPTARHDR aHdrsTar[3]; 218 /** CPIO stuff. */ 219 struct 220 { 221 /** CPIO header. */ 222 CPIOHDR Hdr; 223 /** The filepath which comes directly after the header - embedded here 224 * to make the code more uniform with the tar code later on. */ 225 char achFilePath[_1K]; 226 /** Maximum padding if the file path is completely used. */ 227 char abPad[3]; 228 } Cpio; 229 }; 230 /** The fallback I/O buffer if memory allocation fails. */ 231 uint8_t abIoBuf[512]; 207 232 } RTZIPTARFSSTREAMWRITER; 208 233 … … 288 313 289 314 /** 315 * Returns a flag whether the writer is writing a tar archive, false if CPIO. 316 * 317 * @returns Flag whether the writer is in tar mode, true for tar and false for CPIO. 318 * @param pThis The TAR writer instance. 319 */ 320 DECLINLINE(bool) rtZipTarFssWrite_IsTar(PRTZIPTARFSSTREAMWRITER pThis) 321 { 322 return pThis->enmFormat != RTZIPTARFORMAT_CPIO_ASCII_NEW; 323 } 324 325 326 /** 327 * Returns the block size of the given archive format. 328 * 329 * @returns Block size in bytes. 330 * @param pThis The TAR writer instance. 331 */ 332 DECLINLINE(size_t) rtZipTarFssWrite_GetBlockSize(PRTZIPTARFSSTREAMWRITER pThis) 333 { 334 if (!rtZipTarFssWrite_IsTar(pThis)) 335 return sizeof(uint32_t); 336 337 return RTZIPTAR_BLOCKSIZE; 338 } 339 340 341 /** 290 342 * Creates one or more tar headers for the object. 291 343 * 292 * Returns RTZIPTARFSSTREAMWRITER::aHdrs and RTZIPTARFSSTREAMWRITER::cHdrs.344 * Returns RTZIPTARFSSTREAMWRITER::aHdrsTar and RTZIPTARFSSTREAMWRITER::cHdrs. 293 345 * 294 346 * @returns IPRT status code. … … 302 354 * @param chType The tar record type, UINT8_MAX for default. 303 355 */ 304 static int rtZipTarFssWriter_ObjInfoToHdr (PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo,305 const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType)356 static int rtZipTarFssWriter_ObjInfoToHdrTar(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo, 357 const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType) 306 358 { 307 359 pThis->cHdrs = 0; 308 RT_ZERO(pThis->aHdrs [0]);360 RT_ZERO(pThis->aHdrsTar[0]); 309 361 310 362 /* … … 312 364 */ 313 365 size_t cchPath = strlen(pszPath); 314 if (cchPath < sizeof(pThis->aHdrs [0].Common.name))315 { 316 memcpy(pThis->aHdrs [0].Common.name, pszPath, cchPath + 1);366 if (cchPath < sizeof(pThis->aHdrsTar[0].Common.name)) 367 { 368 memcpy(pThis->aHdrsTar[0].Common.name, pszPath, cchPath + 1); 317 369 #if RTPATH_STYLE != RTPATH_STR_F_STYLE_UNIX 318 char *pszDosSlash = strchr(pThis->aHdrs [0].Common.name, '\\');370 char *pszDosSlash = strchr(pThis->aHdrsTar[0].Common.name, '\\'); 319 371 while (pszDosSlash) 320 372 { … … 339 391 else 340 392 uValue = (uValue & pThis->fFileModeAndMask) | pThis->fFileModeOrMask; 341 int rc = RTStrFormatU32(pThis->aHdrs [0].Common.mode, sizeof(pThis->aHdrs[0].Common.mode), uValue, 8 /*uBase*/,342 -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.mode) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);393 int rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.mode, sizeof(pThis->aHdrsTar[0].Common.mode), uValue, 8 /*uBase*/, 394 -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.mode) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 343 395 AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE); 344 396 … … 348 400 uValue = pThis->uidOwner != NIL_RTUID ? pThis->uidOwner 349 401 : pObjInfo->Attr.u.Unix.uid != NIL_RTUID ? pObjInfo->Attr.u.Unix.uid : 0; 350 rc = RTStrFormatU32(pThis->aHdrs [0].Common.uid, sizeof(pThis->aHdrs[0].Common.uid), uValue,351 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.uid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);402 rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.uid, sizeof(pThis->aHdrsTar[0].Common.uid), uValue, 403 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.uid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 352 404 AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE); 353 405 354 406 uValue = pThis->gidGroup != NIL_RTGID ? pThis->gidGroup 355 407 : pObjInfo->Attr.u.Unix.gid != NIL_RTGID ? pObjInfo->Attr.u.Unix.gid : 0; 356 rc = RTStrFormatU32(pThis->aHdrs [0].Common.gid, sizeof(pThis->aHdrs[0].Common.gid), uValue,357 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.gid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);408 rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.gid, sizeof(pThis->aHdrsTar[0].Common.gid), uValue, 409 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.gid) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 358 410 AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE); 359 411 … … 361 413 * The file size. 362 414 */ 363 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs [0].Common.size, pObjInfo->cbObject);415 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pObjInfo->cbObject); 364 416 AssertRCReturn(rc, rc); 365 417 … … 367 419 * Modification time relative to unix epoc. 368 420 */ 369 rc = RTStrFormatU64(pThis->aHdrs [0].Common.mtime, sizeof(pThis->aHdrs[0].Common.mtime),421 rc = RTStrFormatU64(pThis->aHdrsTar[0].Common.mtime, sizeof(pThis->aHdrsTar[0].Common.mtime), 370 422 RTTimeSpecGetSeconds(pThis->pModTime ? pThis->pModTime : &pObjInfo->ModificationTime), 371 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.mtime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);423 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.mtime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 372 424 AssertRCReturn(rc, rc); 373 425 … … 389 441 case RTFS_TYPE_WHITEOUT: AssertFailedReturn(VERR_WRONG_TYPE); 390 442 } 391 pThis->aHdrs [0].Common.typeflag = chType;443 pThis->aHdrsTar[0].Common.typeflag = chType; 392 444 393 445 /* No link name, at least not for now. Caller might set it. */ … … 397 449 */ 398 450 if (pThis->enmFormat == RTZIPTARFORMAT_GNU) 399 memcpy(pThis->aHdrs [0].Gnu.magic, RTZIPTAR_GNU_MAGIC, sizeof(pThis->aHdrs[0].Gnu.magic));451 memcpy(pThis->aHdrsTar[0].Gnu.magic, RTZIPTAR_GNU_MAGIC, sizeof(pThis->aHdrsTar[0].Gnu.magic)); 400 452 else if ( pThis->enmFormat == RTZIPTARFORMAT_USTAR 401 453 || pThis->enmFormat == RTZIPTARFORMAT_PAX) 402 454 { 403 memcpy(pThis->aHdrs [0].Common.magic, RTZIPTAR_USTAR_MAGIC, sizeof(pThis->aHdrs[0].Common.magic));404 memcpy(pThis->aHdrs [0].Common.version, RTZIPTAR_USTAR_VERSION, sizeof(pThis->aHdrs[0].Common.version));455 memcpy(pThis->aHdrsTar[0].Common.magic, RTZIPTAR_USTAR_MAGIC, sizeof(pThis->aHdrsTar[0].Common.magic)); 456 memcpy(pThis->aHdrsTar[0].Common.version, RTZIPTAR_USTAR_VERSION, sizeof(pThis->aHdrsTar[0].Common.version)); 405 457 } 406 458 else … … 410 462 * Owner and group names. Silently truncate them for now. 411 463 */ 412 RTStrCopy(pThis->aHdrs [0].Common.uname, sizeof(pThis->aHdrs[0].Common.uname), pThis->pszOwner ? pThis->pszOwner : pszOwnerNm);413 RTStrCopy(pThis->aHdrs [0].Common.gname, sizeof(pThis->aHdrs[0].Common.uname), pThis->pszGroup ? pThis->pszGroup : pszGroupNm);464 RTStrCopy(pThis->aHdrsTar[0].Common.uname, sizeof(pThis->aHdrsTar[0].Common.uname), pThis->pszOwner ? pThis->pszOwner : pszOwnerNm); 465 RTStrCopy(pThis->aHdrsTar[0].Common.gname, sizeof(pThis->aHdrsTar[0].Common.uname), pThis->pszGroup ? pThis->pszGroup : pszGroupNm); 414 466 415 467 /* … … 419 471 || RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode) ) 420 472 { 421 rc = RTStrFormatU32(pThis->aHdrs [0].Common.devmajor, sizeof(pThis->aHdrs[0].Common.devmajor),473 rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.devmajor, sizeof(pThis->aHdrsTar[0].Common.devmajor), 422 474 RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device), 423 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);475 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 424 476 AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE); 425 477 426 rc = RTStrFormatU32(pThis->aHdrs [0].Common.devminor, sizeof(pThis->aHdrs[0].Common.devmajor),478 rc = RTStrFormatU32(pThis->aHdrsTar[0].Common.devminor, sizeof(pThis->aHdrsTar[0].Common.devmajor), 427 479 RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device), 428 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);480 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Common.devmajor) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 429 481 AssertRCReturn(rc, VERR_TAR_NUM_VALUE_TOO_LARGE); 430 482 } … … 436 488 if (pThis->enmFormat == RTZIPTARFORMAT_GNU) 437 489 { 438 rc = RTStrFormatU64(pThis->aHdrs [0].Gnu.ctime, sizeof(pThis->aHdrs[0].Gnu.ctime),490 rc = RTStrFormatU64(pThis->aHdrsTar[0].Gnu.ctime, sizeof(pThis->aHdrsTar[0].Gnu.ctime), 439 491 RTTimeSpecGetSeconds(&pObjInfo->ChangeTime), 440 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Gnu.ctime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);492 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Gnu.ctime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 441 493 AssertRCReturn(rc, rc); 442 494 443 rc = RTStrFormatU64(pThis->aHdrs [0].Gnu.atime, sizeof(pThis->aHdrs[0].Gnu.atime),495 rc = RTStrFormatU64(pThis->aHdrsTar[0].Gnu.atime, sizeof(pThis->aHdrsTar[0].Gnu.atime), 444 496 RTTimeSpecGetSeconds(&pObjInfo->ChangeTime), 445 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrs [0].Gnu.atime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION);497 8 /*uBase*/, -1 /*cchWidth*/, sizeof(pThis->aHdrsTar[0].Gnu.atime) - 1, RTSTR_F_ZEROPAD | RTSTR_F_PRECISION); 446 498 AssertRCReturn(rc, rc); 447 499 } … … 452 504 */ 453 505 pThis->cHdrs = 1; 454 return rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]); 506 pThis->cbHdr = sizeof(pThis->aHdrsTar[0]); 507 return rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 508 } 509 510 511 /** 512 * Formats a given 32-bit value into a CPIO header field. 513 * 514 * @returns nothing. 515 * @param pach8Field The field to format the value into. 516 * @param u32 The value to format. 517 */ 518 static void rtZipTarFssWriter_CpioFmtU32(char pach8Field[8], uint32_t u32) 519 { 520 static const char s_achHex[] = "0123456789abcdef"; 521 size_t cchField = 7; 522 unsigned char *puchField = (unsigned char *)pach8Field; 523 do 524 { 525 puchField[cchField--] = s_achHex[u32 & 0xf]; 526 u32 >>= 4; 527 } while (cchField); 528 529 /* Last one. */ 530 puchField[0] = s_achHex[u32 & 0xf]; 531 } 532 533 534 /** 535 * Creates one or more CPIO headers for the object. 536 * 537 * Returns RTZIPTARFSSTREAMWRITER::Cpio::Hdr and RTZIPTARFSSTREAMWRITER::cHdrs. 538 * 539 * @returns IPRT status code. 540 * @param pThis The TAR writer instance. 541 * @param pszPath The path to the file. 542 * @param hVfsIos The I/O stream of the file. 543 * @param fFlags The RTVFSFSSTREAMOPS::pfnAdd flags. 544 * @param pObjInfo The object information. 545 * @param pszOwnerNm The owner name. 546 * @param pszGroupNm The group name. 547 */ 548 static int rtZipTarFssWriter_ObjInfoToHdrCpio(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo, 549 const char *pszOwnerNm, const char *pszGroupNm) 550 { 551 RT_NOREF(pszOwnerNm, pszGroupNm); 552 AssertReturn(!rtZipTarFssWrite_IsTar(pThis), VERR_INTERNAL_ERROR_3); 553 554 pThis->cHdrs = 0; 555 RT_ZERO(pThis->Cpio.Hdr); 556 RT_ZERO(pThis->Cpio.achFilePath); 557 558 /* 559 * The path name first. Make sure to flip DOS slashes. 560 */ 561 size_t cchPath = strlen(pszPath) + 1; 562 if (cchPath < sizeof(pThis->Cpio.achFilePath)) 563 { 564 memcpy(&pThis->Cpio.achFilePath[0], pszPath, cchPath); 565 #if RTPATH_STYLE != RTPATH_STR_F_STYLE_UNIX 566 char *pszDosSlash = strchr(&pThis->Cpio.achFilePath[0], '\\'); 567 while (pszDosSlash) 568 { 569 *pszDosSlash = '/'; 570 pszDosSlash = strchr(pszDosSlash + 1, '\\'); 571 } 572 #endif 573 } 574 else 575 return VERR_TAR_NAME_TOO_LONG; 576 577 if (pObjInfo->cbObject != (uint32_t)pObjInfo->cbObject) 578 return VERR_FILE_TOO_BIG; 579 580 /* 581 * Set CPIO record magic and version. 582 */ 583 if (pThis->enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW) 584 memcpy(pThis->Cpio.Hdr.AsciiNew.achMagic, CPIO_HDR_NEW_MAGIC, sizeof(pThis->Cpio.Hdr.AsciiNew.achMagic)); 585 else 586 AssertFailedReturn(VERR_INTERNAL_ERROR_4); 587 588 /* 589 * File mode. ASSUME that the unix part of the IPRT mode mask is 590 * compatible with the TAR/Unix world. 591 */ 592 uint32_t uValue = pObjInfo->Attr.fMode & RTFS_UNIX_MASK; 593 if (pObjInfo->Attr.fMode) /* Don't want to modify the EOS record here. */ 594 { 595 if (RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode)) 596 uValue = (uValue & pThis->fDirModeAndMask) | pThis->fDirModeOrMask; 597 else 598 uValue = (uValue & pThis->fFileModeAndMask) | pThis->fFileModeOrMask; 599 } 600 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achMode, uValue); 601 602 /* 603 * Inode id. 604 */ 605 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achInode, pObjInfo->Attr.u.Unix.INodeId); 606 607 /* 608 * Number of hardlinks. 609 */ 610 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achNLinks, pObjInfo->Attr.u.Unix.cHardlinks ? pObjInfo->Attr.u.Unix.cHardlinks : 1); 611 612 /* 613 * uid & gid. Just guard against NIL values as they won't fit. 614 */ 615 uValue = pThis->uidOwner != NIL_RTUID ? pThis->uidOwner 616 : pObjInfo->Attr.u.Unix.uid != NIL_RTUID ? pObjInfo->Attr.u.Unix.uid : 0; 617 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achUid, uValue); 618 619 uValue = pThis->gidGroup != NIL_RTGID ? pThis->gidGroup 620 : pObjInfo->Attr.u.Unix.gid != NIL_RTGID ? pObjInfo->Attr.u.Unix.gid : 0; 621 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achGid, uValue); 622 623 /* 624 * The file size. 625 */ 626 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pObjInfo->cbObject); 627 628 /* 629 * Modification time relative to unix epoc. 630 */ 631 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achMTime, 632 RTTimeSpecGetSeconds(pThis->pModTime ? pThis->pModTime : &pObjInfo->ModificationTime)); 633 634 /* 635 * Char/block device numbers. 636 */ 637 if ( RTFS_IS_DEV_BLOCK(pObjInfo->Attr.fMode) 638 || RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode) ) 639 { 640 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achDevMajor, RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device)); 641 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achDevMajor, RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)); 642 } 643 644 /* 645 * File path size including the terminator. 646 */ 647 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achNameSize, cchPath); 648 649 pThis->cHdrs = 1; 650 pThis->cbHdr = RT_ALIGN_32(sizeof(pThis->Cpio.Hdr) + cchPath, 4); 651 return VINF_SUCCESS; 652 } 653 654 655 /** 656 * Creates one or more headers for the object. 657 * 658 * Returns RTZIPTARFSSTREAMWRITER::cbHdrs and RTZIPTARFSSTREAMWRITER::cHdrs. 659 * 660 * @returns IPRT status code. 661 * @param pThis The TAR writer instance. 662 * @param pszPath The path to the file. 663 * @param hVfsIos The I/O stream of the file. 664 * @param fFlags The RTVFSFSSTREAMOPS::pfnAdd flags. 665 * @param pObjInfo The object information. 666 * @param pszOwnerNm The owner name. 667 * @param pszGroupNm The group name. 668 * @param chType The tar record type, UINT8_MAX for default. 669 */ 670 static int rtZipTarFssWriter_ObjInfoToHdr(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, PCRTFSOBJINFO pObjInfo, 671 const char *pszOwnerNm, const char *pszGroupNm, uint8_t chType) 672 { 673 if (!rtZipTarFssWrite_IsTar(pThis)) 674 return rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm); 675 676 return rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, chType); 455 677 } 456 678 … … 486 708 *pObjInfo = pPush->ObjInfo; 487 709 pObjInfo->cbObject = pPush->cbCurrent; 488 pObjInfo->cbAllocated = RT_ALIGN_64(pPush->cbCurrent, RTZIPTAR_BLOCKSIZE);710 pObjInfo->cbAllocated = RT_ALIGN_64(pPush->cbCurrent, rtZipTarFssWrite_GetBlockSize(pPush->pParent)); 489 711 490 712 /* Additional info. */ … … 498 720 case RTFSOBJATTRADD_UNIX_OWNER: 499 721 pObjInfo->Attr.u.UnixOwner.uid = pPush->ObjInfo.Attr.u.Unix.uid; 500 if (pPush->pParent) 501 strcpy(pObjInfo->Attr.u.UnixOwner.szName, pPush->pParent->aHdrs[0].Common.uname); 722 if ( pPush->pParent 723 && rtZipTarFssWrite_IsTar(pPush->pParent)) 724 strcpy(pObjInfo->Attr.u.UnixOwner.szName, pPush->pParent->aHdrsTar[0].Common.uname); 502 725 else 503 726 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0'; … … 507 730 case RTFSOBJATTRADD_UNIX_GROUP: 508 731 pObjInfo->Attr.u.UnixGroup.gid = pPush->ObjInfo.Attr.u.Unix.gid; 509 if (pPush->pParent) 510 strcpy(pObjInfo->Attr.u.UnixGroup.szName, pPush->pParent->aHdrs[0].Common.uname); 732 if ( pPush->pParent 733 && rtZipTarFssWrite_IsTar(pPush->pParent)) 734 strcpy(pObjInfo->Attr.u.UnixGroup.szName, pPush->pParent->aHdrsTar[0].Common.uname); 511 735 else 512 736 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0'; … … 882 1106 883 1107 /* 884 * Do we need to update the header. pThis->aHdrs [0] will retain the current1108 * Do we need to update the header. pThis->aHdrsTar[0] will retain the current 885 1109 * content at pPush->offHdr and we only need to update the size. 886 1110 */ 887 1111 if (pPush->fOpenEnded) 888 1112 { 889 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pPush->cbCurrent); 1113 if (rtZipTarFssWrite_IsTar(pThis)) 1114 { 1115 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pPush->cbCurrent); 1116 if (RT_SUCCESS(rc)) 1117 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 1118 } 1119 else 1120 { 1121 if (pPush->cbCurrent == (uint32_t)pPush->cbCurrent) 1122 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pPush->cbCurrent); 1123 else 1124 rc = VERR_FILE_TOO_BIG; 1125 } 1126 890 1127 if (RT_SUCCESS(rc)) 891 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]); 892 if (RT_SUCCESS(rc)) 893 { 894 rc = RTVfsFileWriteAt(pThis->hVfsFile, pPush->offHdr, &pThis->aHdrs[0], sizeof(pThis->aHdrs[0]), NULL); 1128 { 1129 rc = RTVfsFileWriteAt(pThis->hVfsFile, pPush->offHdr, &pThis->abHdrs[0], pThis->cbHdr, NULL); 895 1130 if (RT_SUCCESS(rc)) 896 1131 rc = RTVfsFileSeek(pThis->hVfsFile, pPush->offData + pPush->cbCurrent, RTFILE_SEEK_BEGIN, NULL); … … 910 1145 * Do zero padding if necessary. 911 1146 */ 912 if (pPush->cbCurrent & (RTZIPTAR_BLOCKSIZE - 1)) 913 { 914 size_t cbToZero = RTZIPTAR_BLOCKSIZE - (pPush->cbCurrent & (RTZIPTAR_BLOCKSIZE - 1)); 1147 size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis); 1148 if (pPush->cbCurrent & (cbBlock - 1)) 1149 { 1150 size_t cbToZero = cbBlock - (pPush->cbCurrent & (cbBlock - 1)); 915 1151 rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, cbToZero, true /*fBlocking*/, NULL); 916 1152 if (RT_SUCCESS(rc)) … … 945 1181 */ 946 1182 /** @todo Optimize skipping to end of tar file in update mode. */ 947 while (!pThis->pRead ->fEndOfStream)948 { 949 int rc = rtZipTarFss_Next(pThis->pRead , NULL, NULL, NULL);1183 while (!pThis->pReadTar->fEndOfStream) 1184 { 1185 int rc = rtZipTarFss_Next(pThis->pReadTar, NULL, NULL, NULL); 950 1186 if (rc == VERR_EOF) 951 1187 break; … … 956 1192 * Seek to the desired cut-off point and indicate that we've switched to writing. 957 1193 */ 958 Assert(pThis->pRead ->offNextHdr == pThis->pRead->offCurHdr);959 int rc = RTVfsFileSeek(pThis->hVfsFile, pThis->pRead ->offNextHdr, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);1194 Assert(pThis->pReadTar->offNextHdr == pThis->pReadTar->offCurHdr); 1195 int rc = RTVfsFileSeek(pThis->hVfsFile, pThis->pReadTar->offNextHdr, RTFILE_SEEK_BEGIN, NULL /*poffActual*/); 960 1196 if (RT_SUCCESS(rc)) 961 1197 pThis->fWriting = true; … … 1052 1288 1053 1289 /* 1054 * Final fallback, 512KB buffer using the 3rd header. 1055 */ 1056 AssertCompile(RT_ELEMENTS(pThis->aHdrs) >= 3); 1057 *pcbBuf = sizeof(pThis->aHdrs[2]); 1290 * Final fallback, 512B buffer using the fallback buffer. 1291 */ 1292 *pcbBuf = sizeof(pThis->abIoBuf); 1058 1293 *ppvFree = NULL; 1059 return (uint8_t *)&pThis->aHdrs[2];1294 return &pThis->abIoBuf[0]; 1060 1295 } 1061 1296 … … 1249 1484 * Format the first header. 1250 1485 */ 1251 int rc = rtZipTarFssWriter_ObjInfoToHdr (pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, RTZIPTAR_TF_GNU_SPARSE);1486 int rc = rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, RTZIPTAR_TF_GNU_SPARSE); 1252 1487 AssertRCReturn(rc, rc); 1253 1488 AssertReturn(pThis->cHdrs == 1, VERR_INTERNAL_ERROR_2); 1254 1489 1255 1490 /* data size. */ 1256 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs [0].Common.size, pSparse->cbDataSpans);1491 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, pSparse->cbDataSpans); 1257 1492 AssertRCReturn(rc, rc); 1258 1493 1259 1494 /* realsize. */ 1260 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs [0].Gnu.realsize, pObjInfo->cbObject);1495 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Gnu.realsize, pObjInfo->cbObject); 1261 1496 AssertRCReturn(rc, rc); 1262 1497 1263 Assert(pThis->aHdrs [0].Gnu.isextended == 0);1498 Assert(pThis->aHdrsTar[0].Gnu.isextended == 0); 1264 1499 1265 1500 /* 1266 1501 * Walk the sparse spans, fill and write headers one by one. 1267 1502 */ 1268 PRTZIPTARGNUSPARSE paSparse = &pThis->aHdrs [0].Gnu.sparse[0];1269 uint32_t cSparse = RT_ELEMENTS(pThis->aHdrs [0].Gnu.sparse);1503 PRTZIPTARGNUSPARSE paSparse = &pThis->aHdrsTar[0].Gnu.sparse[0]; 1504 uint32_t cSparse = RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse); 1270 1505 uint32_t iSparse = 0; 1271 1506 … … 1281 1516 if (iSparse >= cSparse) 1282 1517 { 1283 if (cSparse != RT_ELEMENTS(pThis->aHdrs [0].Gnu.sparse))1284 pThis->aHdrs [0].GnuSparse.isextended = 1; /* more headers to come */1518 if (cSparse != RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse)) 1519 pThis->aHdrsTar[0].GnuSparse.isextended = 1; /* more headers to come */ 1285 1520 else 1286 1521 { 1287 pThis->aHdrs [0].Gnu.isextended = 1; /* more headers to come */1288 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs [0]);1522 pThis->aHdrsTar[0].Gnu.isextended = 1; /* more headers to come */ 1523 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 1289 1524 } 1290 1525 if (RT_SUCCESS(rc)) 1291 rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrs [0], sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);1526 rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrsTar[0], sizeof(pThis->aHdrsTar[0]), true /*fBlocking*/, NULL); 1292 1527 if (RT_FAILURE(rc)) 1293 1528 return rc; 1294 RT_ZERO(pThis->aHdrs [0]);1295 cSparse = RT_ELEMENTS(pThis->aHdrs [0].GnuSparse.sp);1529 RT_ZERO(pThis->aHdrsTar[0]); 1530 cSparse = RT_ELEMENTS(pThis->aHdrsTar[0].GnuSparse.sp); 1296 1531 iSparse = 0; 1297 paSparse = &pThis->aHdrs [0].GnuSparse.sp[0];1532 paSparse = &pThis->aHdrsTar[0].GnuSparse.sp[0]; 1298 1533 } 1299 1534 … … 1312 1547 if (iSparse != 0) 1313 1548 { 1314 if (cSparse != RT_ELEMENTS(pThis->aHdrs [0].Gnu.sparse))1315 Assert(pThis->aHdrs [0].GnuSparse.isextended == 0);1549 if (cSparse != RT_ELEMENTS(pThis->aHdrsTar[0].Gnu.sparse)) 1550 Assert(pThis->aHdrsTar[0].GnuSparse.isextended == 0); 1316 1551 else 1317 1552 { 1318 Assert(pThis->aHdrs [0].Gnu.isextended == 0);1319 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs [0]);1553 Assert(pThis->aHdrsTar[0].Gnu.isextended == 0); 1554 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 1320 1555 } 1321 1556 if (RT_SUCCESS(rc)) 1322 rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrs [0], sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);1557 rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->aHdrsTar[0], sizeof(pThis->aHdrsTar[0]), true /*fBlocking*/, NULL); 1323 1558 } 1324 1559 pThis->cHdrs = 0; … … 1343 1578 const char *pszOwnerNm, const char *pszGroupNm) 1344 1579 { 1580 AssertReturn(rtZipTarFssWrite_IsTar(pThis), VERR_INTERNAL_ERROR_2); 1581 1345 1582 /* 1346 1583 * Scan the input file to locate all zero blocks. … … 1463 1700 if (offHdr >= 0) 1464 1701 { 1465 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->a Hdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);1702 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL); 1466 1703 if (RT_SUCCESS(rc)) 1467 1704 { 1468 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);1705 pThis->cbWritten += pThis->cHdrs * pThis->cbHdr; 1469 1706 1470 1707 /* … … 1502 1739 * Do the zero padding. 1503 1740 */ 1504 if ((cbReadTotal & (RTZIPTAR_BLOCKSIZE - 1)) && RT_SUCCESS(rc)) 1741 size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis); 1742 if ((cbReadTotal & (cbBlock - 1)) && RT_SUCCESS(rc)) 1505 1743 { 1506 size_t cbToZero = RTZIPTAR_BLOCKSIZE - (cbReadTotal & (RTZIPTAR_BLOCKSIZE- 1));1744 size_t cbToZero = cbBlock - (cbReadTotal & (cbBlock - 1)); 1507 1745 rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, cbToZero, true /*fBlocking*/, NULL); 1508 1746 if (RT_SUCCESS(rc)) … … 1519 1757 if (offRestore >= 0) 1520 1758 { 1521 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, cbReadTotal); 1522 if (RT_SUCCESS(rc)) 1523 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]); 1759 if (rtZipTarFssWrite_IsTar(pThis)) 1760 { 1761 rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrsTar[0].Common.size, cbReadTotal); 1762 if (RT_SUCCESS(rc)) 1763 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 1764 } 1765 else 1766 { 1767 if (pObjInfo->cbObject == (uint32_t)pObjInfo->cbObject) 1768 rtZipTarFssWriter_CpioFmtU32(pThis->Cpio.Hdr.AsciiNew.achFileSize, (uint32_t)pObjInfo->cbObject); 1769 else 1770 rc = VERR_FILE_TOO_BIG; 1771 } 1772 1524 1773 if (RT_SUCCESS(rc)) 1525 1774 { 1526 rc = RTVfsFileWriteAt(pThis->hVfsFile, offHdr, &pThis->a Hdrs[0], sizeof(pThis->aHdrs[0]), NULL);1775 rc = RTVfsFileWriteAt(pThis->hVfsFile, offHdr, &pThis->abHdrs[0], pThis->cbHdr, NULL); 1527 1776 if (RT_SUCCESS(rc)) 1528 1777 rc = RTVfsFileSeek(pThis->hVfsFile, offRestore, RTFILE_SEEK_BEGIN, NULL); … … 1566 1815 if (RT_SUCCESS(rc)) 1567 1816 { 1568 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->a Hdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);1817 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL); 1569 1818 if (RT_SUCCESS(rc)) 1570 1819 { 1571 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);1820 pThis->cbWritten += pThis->cHdrs * pThis->cbHdr; 1572 1821 1573 1822 /* 1574 * Copy the bytes. Padding the last buffer to a multiple of 512.1823 * Copy the bytes. Padding the last buffer to a multiple of the block size. 1575 1824 */ 1576 1825 void *pvBufFree; … … 1579 1828 1580 1829 uint64_t cbLeft = pObjInfo->cbObject; 1830 size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis); 1581 1831 while (cbLeft > 0) 1582 1832 { … … 1587 1837 1588 1838 size_t cbToWrite = cbRead; 1589 if (cbRead & ( RTZIPTAR_BLOCKSIZE- 1))1839 if (cbRead & (cbBlock - 1)) 1590 1840 { 1591 size_t cbToZero = RTZIPTAR_BLOCKSIZE - (cbRead & (RTZIPTAR_BLOCKSIZE- 1));1841 size_t cbToZero = cbBlock - (cbRead & (cbBlock - 1)); 1592 1842 memset(&pbBuf[cbRead], 0, cbToZero); 1593 1843 cbToWrite += cbToZero; … … 1643 1893 #endif 1644 1894 size_t cchTarget = strlen(szTarget); 1645 if (cchTarget < sizeof(pThis->aHdrs[0].Common.linkname)) 1646 { 1647 /* 1648 * Create a header, add the link target and push it out. 1649 */ 1650 rc = rtZipTarFssWriter_ObjInfoToHdr(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, UINT8_MAX); 1895 if (rtZipTarFssWrite_IsTar(pThis)) 1896 { 1897 if (cchTarget < sizeof(pThis->aHdrsTar[0].Common.linkname)) 1898 { 1899 /* 1900 * Create a header, add the link target and push it out. 1901 */ 1902 rc = rtZipTarFssWriter_ObjInfoToHdrTar(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm, UINT8_MAX); 1903 if (RT_SUCCESS(rc)) 1904 { 1905 memcpy(pThis->aHdrsTar[0].Common.linkname, szTarget, cchTarget + 1); 1906 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrsTar[0]); 1907 if (RT_SUCCESS(rc)) 1908 { 1909 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, 1910 true /*fBlocking*/, NULL); 1911 if (RT_SUCCESS(rc)) 1912 { 1913 pThis->cbWritten += pThis->cHdrs * pThis->cbHdr; 1914 return VINF_SUCCESS; 1915 } 1916 pThis->rcFatal = rc; 1917 } 1918 } 1919 } 1920 else 1921 { 1922 /** @todo implement gnu and pax long name extensions. */ 1923 rc = VERR_TAR_NAME_TOO_LONG; 1924 } 1925 } 1926 else 1927 { 1928 /* CPIO stores the target path as file data after the header, without any zero terminator. */ 1929 rc = rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, pszPath, pObjInfo, pszOwnerNm, pszGroupNm); 1651 1930 if (RT_SUCCESS(rc)) 1652 1931 { 1653 memcpy(pThis->aHdrs[0].Common.linkname, szTarget, cchTarget + 1);1654 rc = rtZipTarFssWriter_ChecksumHdr(&pThis->aHdrs[0]);1932 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, 1933 true /*fBlocking*/, NULL); 1655 1934 if (RT_SUCCESS(rc)) 1656 1935 { 1657 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), 1658 true /*fBlocking*/, NULL); 1936 rc = RTVfsIoStrmWrite(pThis->hVfsIos, szTarget, cchTarget, true /*fBlocking*/, NULL); 1659 1937 if (RT_SUCCESS(rc)) 1660 1938 { 1661 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]); 1662 return VINF_SUCCESS; 1939 /* Need to pad the entry to a 4 byte aligned boundary. */ 1940 size_t cbPad = RT_ALIGN_32(cchTarget, 4) - cchTarget; 1941 if (cbPad) 1942 rc = RTVfsIoStrmWrite(pThis->hVfsIos, &pThis->Cpio.abPad[0], cbPad, true /*fBlocking*/, NULL); 1943 if (RT_SUCCESS(rc)) 1944 { 1945 pThis->cbWritten += pThis->cHdrs * pThis->cbHdr + cbPad; 1946 return VINF_SUCCESS; 1947 } 1663 1948 } 1664 pThis->rcFatal = rc;1665 1949 } 1950 pThis->rcFatal = rc; 1666 1951 } 1667 }1668 else1669 {1670 /** @todo implement gnu and pax long name extensions. */1671 rc = VERR_TAR_NAME_TOO_LONG;1672 1952 } 1673 1953 } … … 1695 1975 if (RT_SUCCESS(rc)) 1696 1976 { 1697 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->a Hdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);1977 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cHdrs * pThis->cbHdr, true /*fBlocking*/, NULL); 1698 1978 if (RT_SUCCESS(rc)) 1699 1979 { 1700 pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);1980 pThis->cbWritten += pThis->cHdrs * pThis->cbHdr; 1701 1981 return VINF_SUCCESS; 1702 1982 } … … 1768 2048 * modifications takes place (truncating the archive or appending files). 1769 2049 */ 1770 AssertReturn(pThis->pRead , VERR_ACCESS_DENIED);2050 AssertReturn(pThis->pReadTar || pThis->pReadCpio, VERR_ACCESS_DENIED); 1771 2051 AssertReturn(pThis->fFlags & RTZIPTAR_C_UPDATE, VERR_ACCESS_DENIED); 1772 2052 1773 2053 AssertReturn(!pThis->fWriting, VERR_WRONG_ORDER); 1774 2054 1775 return rtZipTarFss_Next(pThis->pRead, ppszName, penmType, phVfsObj); 2055 if (rtZipTarFssWrite_IsTar(pThis)) 2056 return rtZipTarFss_Next(pThis->pReadTar, ppszName, penmType, phVfsObj); 2057 else 2058 return rtZipCpioFss_Next(pThis->pReadCpio, ppszName, penmType, phVfsObj); 1776 2059 } 1777 2060 … … 1826 2109 ObjOwnerName.Attr.u.UnixOwner.szName, ObjGrpName.Attr.u.UnixOwner.szName); 1827 2110 else if ( !(pThis->fFlags & RTZIPTAR_C_SPARSE) 1828 || ObjInfo.cbObject < RTZIPTAR_MIN_SPARSE) 2111 || ObjInfo.cbObject < RTZIPTAR_MIN_SPARSE 2112 || !rtZipTarFssWrite_IsTar(pThis)) 1829 2113 rc = rtZipTarFssWriter_AddFile(pThis, pszPath, hVfsIos, &ObjInfo, 1830 2114 ObjOwnerName.Attr.u.UnixOwner.szName, ObjGrpName.Attr.u.UnixOwner.szName); … … 1886 2170 const char *pszOwnerNm = "someone"; 1887 2171 const char *pszGroupNm = "somegroup"; 2172 const size_t cbBlock = rtZipTarFssWrite_GetBlockSize(pThis); 1888 2173 RTFSOBJINFO ObjInfo; 1889 2174 if (cObjInfo == 0) … … 1892 2177 RT_ZERO(ObjInfo); 1893 2178 ObjInfo.cbObject = cbFile != UINT64_MAX ? cbFile : 0; 1894 ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, RTZIPTAR_BLOCKSIZE) : UINT64_MAX;2179 ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, cbBlock) : UINT64_MAX; 1895 2180 RTTimeNow(&ObjInfo.ModificationTime); 1896 2181 ObjInfo.BirthTime = ObjInfo.ModificationTime; … … 1917 2202 { 1918 2203 ObjInfo.cbObject = cbFile != UINT64_MAX ? cbFile : 0; 1919 ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, RTZIPTAR_BLOCKSIZE) : UINT64_MAX;2204 ObjInfo.cbAllocated = cbFile != UINT64_MAX ? RT_ALIGN_64(cbFile, cbBlock) : UINT64_MAX; 1920 2205 } 1921 2206 … … 1976 2261 if (RT_SUCCESS(rc)) 1977 2262 { 1978 size_t cbHdrs = pThis->cHdrs * sizeof(pThis->aHdrs[0]);1979 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->a Hdrs, cbHdrs, true /*fBlocking*/, NULL);2263 size_t cbHdrs = pThis->cHdrs * pThis->cbHdr; 2264 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, cbHdrs, true /*fBlocking*/, NULL); 1980 2265 if (RT_SUCCESS(rc)) 1981 2266 { … … 2015 2300 if (RT_SUCCESS(rc)) 2016 2301 { 2017 /* 2018 * There are supposed to be two zero headers at the end of the archive. 2019 * GNU tar may write more because of the way it does buffering, 2020 * libarchive OTOH writes exactly two. 2021 */ 2022 rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, RTZIPTAR_BLOCKSIZE * 2, true /*fBlocking*/, NULL); 2302 if (rtZipTarFssWrite_IsTar(pThis)) 2303 { 2304 /* 2305 * There are supposed to be two zero headers at the end of the archive. 2306 * GNU tar may write more because of the way it does buffering, 2307 * libarchive OTOH writes exactly two. 2308 */ 2309 rc = RTVfsIoStrmWrite(pThis->hVfsIos, g_abRTZero4K, RTZIPTAR_BLOCKSIZE * 2, true /*fBlocking*/, NULL); 2310 if (RT_SUCCESS(rc)) 2311 pThis->cbWritten += RTZIPTAR_BLOCKSIZE * 2; 2312 } 2313 else 2314 { 2315 /* CPIO has a special trailer marker. */ 2316 RTFSOBJINFO ObjInfoEos; RT_ZERO(ObjInfoEos); 2317 rc = rtZipTarFssWriter_ObjInfoToHdrCpio(pThis, CPIO_EOS_FILE_NAME, &ObjInfoEos, NULL, NULL); 2318 if (RT_SUCCESS(rc)) 2319 rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->abHdrs, pThis->cbHdr, true /*fBlocking*/, NULL); 2320 if (RT_SUCCESS(rc)) 2321 pThis->cbWritten += pThis->cbHdr; 2322 } 2023 2323 if (RT_SUCCESS(rc)) 2024 2324 { 2025 pThis->cbWritten += RTZIPTAR_BLOCKSIZE * 2;2026 2027 2325 /* 2028 2326 * Flush the output. … … 2096 2394 AssertReturn( enmFormat == RTZIPTARFORMAT_GNU 2097 2395 || enmFormat == RTZIPTARFORMAT_USTAR 2396 || enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW 2098 2397 , VERR_NOT_IMPLEMENTED); /* Only implementing GNU and USTAR output at the moment. */ 2099 2398 … … 2153 2452 AssertReturn( enmFormat == RTZIPTARFORMAT_GNU 2154 2453 || enmFormat == RTZIPTARFORMAT_USTAR 2155 , VERR_NOT_IMPLEMENTED); /* Only implementing GNU and USTAR output at the moment. */ 2454 || enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW 2455 , VERR_NOT_IMPLEMENTED); /* Only implementing GNU, USTAR and CPIO output at the moment. */ 2156 2456 2157 2457 RTFOFF const offStart = RTVfsFileTell(hVfsFile); … … 2168 2468 */ 2169 2469 PRTZIPTARFSSTREAMWRITER pThis; 2170 size_t const cbThis = sizeof(*pThis) + (fFlags & RTZIPTAR_C_UPDATE ? sizeof(*pThis->pRead) : 0); 2470 size_t const cbThis = sizeof(*pThis) + ( fFlags & RTZIPTAR_C_UPDATE 2471 ? enmFormat == RTZIPTARFORMAT_CPIO_ASCII_NEW 2472 ? sizeof(*pThis->pReadTar) 2473 : sizeof(*pThis->pReadCpio) 2474 : 0); 2171 2475 RTVFSFSSTREAM hVfsFss; 2172 2476 int rc = RTVfsNewFsStream(&g_rtZipTarFssOps, cbThis, NIL_RTVFS, NIL_RTVFSLOCK, … … 2197 2501 { 2198 2502 pThis->fWriting = false; 2199 pThis->pRead = (PRTZIPTARFSSTREAM)(pThis + 1); 2200 rtZipTarReaderInit(pThis->pRead, hVfsIos, (uint64_t)offStart); 2503 if (rtZipTarFssWrite_IsTar(pThis)) 2504 { 2505 pThis->pReadTar = (PRTZIPTARFSSTREAM)(pThis + 1); 2506 rtZipTarReaderInit(pThis->pReadTar, hVfsIos, (uint64_t)offStart); 2507 } 2508 else 2509 { 2510 pThis->pReadCpio = (PRTZIPCPIOFSSTREAM)(pThis + 1); 2511 rtZipCpioReaderInit(pThis->pReadCpio, hVfsIos, (uint64_t)offStart); 2512 } 2201 2513 } 2202 2514 … … 2343 2655 2344 2656 AssertReturn(hVfsObj != NIL_RTVFSOBJ, VERR_INVALID_HANDLE); 2345 PRTZIPTARBASEOBJ pThisObj = rtZipTarFsStreamBaseObjToPrivate(pThis->pRead, hVfsObj); 2346 AssertReturn(pThis, VERR_NOT_OWNER); 2347 2348 AssertReturn(pThis->pRead, VERR_ACCESS_DENIED); 2657 AssertReturn(pThis->pReadTar || pThis->pReadCpio, VERR_ACCESS_DENIED); 2349 2658 AssertReturn(pThis->fFlags & RTZIPTAR_C_UPDATE, VERR_ACCESS_DENIED); 2350 2659 AssertReturn(!pThis->fWriting, VERR_WRONG_ORDER); 2351 2660 2352 /* 2353 * Seek to the desired cut-off point and indicate that we've switched to writing. 2354 */ 2355 int rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr, 2661 int rc; 2662 if (rtZipTarFssWrite_IsTar(pThis)) 2663 { 2664 PRTZIPTARBASEOBJ pThisObj = rtZipTarFsStreamBaseObjToPrivate(pThis->pReadTar, hVfsObj); 2665 AssertReturn(pThisObj, VERR_NOT_OWNER); 2666 2667 /* 2668 * Seek to the desired cut-off point and indicate that we've switched to writing. 2669 */ 2670 rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr, 2356 2671 RTFILE_SEEK_BEGIN, NULL /*poffActual*/); 2672 } 2673 else 2674 { 2675 PRTZIPCPIOBASEOBJ pThisObj = rtZipCpioFsStreamBaseObjToPrivate(pThis->pReadCpio, hVfsObj); 2676 AssertReturn(pThisObj, VERR_NOT_OWNER); 2677 2678 /* 2679 * Seek to the desired cut-off point and indicate that we've switched to writing. 2680 */ 2681 rc = RTVfsFileSeek(pThis->hVfsFile, fAfter ? pThisObj->offNextHdr : pThisObj->offHdr, 2682 RTFILE_SEEK_BEGIN, NULL /*poffActual*/); 2683 } 2357 2684 if (RT_SUCCESS(rc)) 2358 2685 pThis->fWriting = true;
Note:
See TracChangeset
for help on using the changeset viewer.