WriterImplBase.cpp revision e527b796
1/* 2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <package/hpkg/WriterImplBase.h> 8 9#include <errno.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <unistd.h> 14 15#include <algorithm> 16#include <new> 17 18#include <ByteOrder.h> 19#include <File.h> 20 21#include <AutoDeleter.h> 22#include <ZlibCompressionAlgorithm.h> 23 24#include <package/hpkg/DataReader.h> 25#include <package/hpkg/ErrorOutput.h> 26 27#include <package/hpkg/HPKGDefsPrivate.h> 28 29 30namespace BPackageKit { 31 32namespace BHPKG { 33 34namespace BPrivate { 35 36 37// #pragma mark - AttributeValue 38 39 40WriterImplBase::AttributeValue::AttributeValue() 41 : 42 type(B_HPKG_ATTRIBUTE_TYPE_INVALID), 43 encoding(-1) 44{ 45} 46 47 48WriterImplBase::AttributeValue::~AttributeValue() 49{ 50} 51 52 53void 54WriterImplBase::AttributeValue::SetTo(int8 value) 55{ 56 signedInt = value; 57 type = B_HPKG_ATTRIBUTE_TYPE_INT; 58} 59 60 61void 62WriterImplBase::AttributeValue::SetTo(uint8 value) 63{ 64 unsignedInt = value; 65 type = B_HPKG_ATTRIBUTE_TYPE_UINT; 66} 67 68 69void 70WriterImplBase::AttributeValue::SetTo(int16 value) 71{ 72 signedInt = value; 73 type = B_HPKG_ATTRIBUTE_TYPE_INT; 74} 75 76 77void 78WriterImplBase::AttributeValue::SetTo(uint16 value) 79{ 80 unsignedInt = value; 81 type = B_HPKG_ATTRIBUTE_TYPE_UINT; 82} 83 84 85void 86WriterImplBase::AttributeValue::SetTo(int32 value) 87{ 88 signedInt = value; 89 type = B_HPKG_ATTRIBUTE_TYPE_INT; 90} 91 92 93void 94WriterImplBase::AttributeValue::SetTo(uint32 value) 95{ 96 unsignedInt = value; 97 type = B_HPKG_ATTRIBUTE_TYPE_UINT; 98} 99 100 101void 102WriterImplBase::AttributeValue::SetTo(int64 value) 103{ 104 signedInt = value; 105 type = B_HPKG_ATTRIBUTE_TYPE_INT; 106} 107 108 109void 110WriterImplBase::AttributeValue::SetTo(uint64 value) 111{ 112 unsignedInt = value; 113 type = B_HPKG_ATTRIBUTE_TYPE_UINT; 114} 115 116 117void 118WriterImplBase::AttributeValue::SetTo(CachedString* value) 119{ 120 string = value; 121 type = B_HPKG_ATTRIBUTE_TYPE_STRING; 122} 123 124 125void 126WriterImplBase::AttributeValue::SetToData(uint64 size, uint64 offset) 127{ 128 data.size = size; 129 data.offset = offset; 130 type = B_HPKG_ATTRIBUTE_TYPE_RAW; 131 encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP; 132} 133 134 135void 136WriterImplBase::AttributeValue::SetToData(uint64 size, const void* rawData) 137{ 138 data.size = size; 139 if (size > 0) 140 memcpy(data.raw, rawData, size); 141 type = B_HPKG_ATTRIBUTE_TYPE_RAW; 142 encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE; 143} 144 145 146uint8 147WriterImplBase::AttributeValue::ApplicableEncoding() const 148{ 149 switch (type) { 150 case B_HPKG_ATTRIBUTE_TYPE_INT: 151 return _ApplicableIntEncoding(signedInt >= 0 152 ? (uint64)signedInt << 1 153 : (uint64)(-(signedInt + 1) << 1)); 154 case B_HPKG_ATTRIBUTE_TYPE_UINT: 155 return _ApplicableIntEncoding(unsignedInt); 156 case B_HPKG_ATTRIBUTE_TYPE_STRING: 157 return string->index >= 0 158 ? B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE 159 : B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE; 160 case B_HPKG_ATTRIBUTE_TYPE_RAW: 161 return encoding; 162 default: 163 return 0; 164 } 165} 166 167 168/*static*/ uint8 169WriterImplBase::AttributeValue::_ApplicableIntEncoding(uint64 value) 170{ 171 if (value <= 0xff) 172 return B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT; 173 if (value <= 0xffff) 174 return B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT; 175 if (value <= 0xffffffff) 176 return B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT; 177 178 return B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT; 179} 180 181 182// #pragma mark - PackageAttribute 183 184 185WriterImplBase::PackageAttribute::PackageAttribute(BHPKGAttributeID id_, 186 uint8 type_, uint8 encoding_) 187 : 188 id(id_) 189{ 190 type = type_; 191 encoding = encoding_; 192} 193 194 195WriterImplBase::PackageAttribute::~PackageAttribute() 196{ 197 _DeleteChildren(); 198} 199 200 201void 202WriterImplBase::PackageAttribute::AddChild(PackageAttribute* child) 203{ 204 children.Add(child); 205} 206 207 208void 209WriterImplBase::PackageAttribute::_DeleteChildren() 210{ 211 while (PackageAttribute* child = children.RemoveHead()) 212 delete child; 213} 214 215 216// #pragma mark - WriterImplBase 217 218 219WriterImplBase::WriterImplBase(const char* fileType, BErrorOutput* errorOutput) 220 : 221 fHeapWriter(NULL), 222 fCompressionAlgorithm(NULL), 223 fCompressionParameters(NULL), 224 fDecompressionAlgorithm(NULL), 225 fDecompressionParameters(NULL), 226 fFileType(fileType), 227 fErrorOutput(errorOutput), 228 fFileName(NULL), 229 fParameters(), 230 fFile(NULL), 231 fFinished(false) 232{ 233} 234 235 236WriterImplBase::~WriterImplBase() 237{ 238 delete fHeapWriter; 239 delete fCompressionAlgorithm; 240 delete fCompressionParameters; 241 delete fDecompressionAlgorithm; 242 delete fDecompressionParameters; 243 244 delete fFile; 245 246 if (!fFinished && fFileName != NULL 247 && (Flags() & B_HPKG_WRITER_UPDATE_PACKAGE) == 0) { 248 unlink(fFileName); 249 } 250} 251 252 253status_t 254WriterImplBase::Init(const char* fileName, size_t headerSize, 255 const BPackageWriterParameters& parameters) 256{ 257 fParameters = parameters; 258 259 if (fPackageStringCache.Init() != B_OK) 260 throw std::bad_alloc(); 261 262 // open file (don't truncate in update mode) 263 int openMode = O_RDWR; 264 if ((Flags() & B_HPKG_WRITER_UPDATE_PACKAGE) == 0) 265 openMode |= O_CREAT | O_TRUNC; 266 267 BFile* file = new BFile; 268 status_t error = file->SetTo(fileName, openMode); 269 if (error != B_OK) { 270 fErrorOutput->PrintError("Failed to open %s file \"%s\": %s\n", 271 fFileType, fileName, strerror(errno)); 272 delete file; 273 return error; 274 } 275 276 fFile = file; 277 fFileName = fileName; 278 279 DecompressionAlgorithmOwner* decompressionAlgorithm 280 = DecompressionAlgorithmOwner::Create( 281 new(std::nothrow) BZlibCompressionAlgorithm, 282 new(std::nothrow) BZlibDecompressionParameters); 283 BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference( 284 decompressionAlgorithm, true); 285 286 if (decompressionAlgorithm == NULL 287 || decompressionAlgorithm->algorithm == NULL 288 || decompressionAlgorithm->parameters == NULL) { 289 throw std::bad_alloc(); 290 } 291 292 CompressionAlgorithmOwner* compressionAlgorithm = NULL; 293 294 if (fParameters.CompressionLevel() != B_HPKG_COMPRESSION_LEVEL_NONE) { 295 compressionAlgorithm = CompressionAlgorithmOwner::Create( 296 new(std::nothrow) BZlibCompressionAlgorithm, 297 new(std::nothrow) BZlibCompressionParameters( 298 fParameters.CompressionLevel())); 299 300 if (compressionAlgorithm == NULL 301 || compressionAlgorithm->algorithm == NULL 302 || compressionAlgorithm->parameters == NULL) { 303 throw std::bad_alloc(); 304 } 305 } 306 307 BReference<CompressionAlgorithmOwner> compressionAlgorithmReference( 308 compressionAlgorithm, true); 309 310 // create heap writer 311 fHeapWriter = new PackageFileHeapWriter(fErrorOutput, fFile, headerSize, 312 compressionAlgorithm, decompressionAlgorithm); 313 fHeapWriter->Init(); 314 315 return B_OK; 316} 317 318 319void 320WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, 321 const BPackageInfo& packageInfo) 322{ 323 // name 324 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, packageInfo.Name(), 325 attributeList); 326 327 // summary 328 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY, 329 packageInfo.Summary(), attributeList); 330 331 // description 332 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION, 333 packageInfo.Description(), attributeList); 334 335 // vendor 336 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR, 337 packageInfo.Vendor(), attributeList); 338 339 // packager 340 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER, 341 packageInfo.Packager(), attributeList); 342 343 // base package (optional) 344 _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE, 345 packageInfo.BasePackage(), attributeList); 346 347 // flags 348 PackageAttribute* flags = new PackageAttribute( 349 B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT, 350 B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT); 351 flags->unsignedInt = packageInfo.Flags(); 352 attributeList.Add(flags); 353 354 // architecture 355 PackageAttribute* architecture = new PackageAttribute( 356 B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT, 357 B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); 358 architecture->unsignedInt = packageInfo.Architecture(); 359 attributeList.Add(architecture); 360 361 // version 362 RegisterPackageVersion(attributeList, packageInfo.Version()); 363 364 // copyright list 365 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT, 366 packageInfo.CopyrightList(), attributeList); 367 368 // license list 369 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE, 370 packageInfo.LicenseList(), attributeList); 371 372 // URL list 373 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_URL, 374 packageInfo.URLList(), attributeList); 375 376 // source URL list 377 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL, 378 packageInfo.SourceURLList(), attributeList); 379 380 // provides list 381 const BObjectList<BPackageResolvable>& providesList 382 = packageInfo.ProvidesList(); 383 for (int i = 0; i < providesList.CountItems(); ++i) { 384 BPackageResolvable* resolvable = providesList.ItemAt(i); 385 bool hasVersion = resolvable->Version().InitCheck() == B_OK; 386 bool hasCompatibleVersion 387 = resolvable->CompatibleVersion().InitCheck() == B_OK; 388 389 PackageAttribute* provides = AddStringAttribute( 390 B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, resolvable->Name(), 391 attributeList); 392 393 if (hasVersion) 394 RegisterPackageVersion(provides->children, resolvable->Version()); 395 396 if (hasCompatibleVersion) { 397 RegisterPackageVersion(provides->children, 398 resolvable->CompatibleVersion(), 399 B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE); 400 } 401 } 402 403 // requires list 404 RegisterPackageResolvableExpressionList(attributeList, 405 packageInfo.RequiresList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES); 406 407 // supplements list 408 RegisterPackageResolvableExpressionList(attributeList, 409 packageInfo.SupplementsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS); 410 411 // conflicts list 412 RegisterPackageResolvableExpressionList(attributeList, 413 packageInfo.ConflictsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS); 414 415 // freshens list 416 RegisterPackageResolvableExpressionList(attributeList, 417 packageInfo.FreshensList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS); 418 419 // replaces list 420 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES, 421 packageInfo.ReplacesList(), attributeList); 422 423 // global writable file info list 424 const BObjectList<BGlobalWritableFileInfo>& globalWritableFileInfos 425 = packageInfo.GlobalWritableFileInfos(); 426 for (int32 i = 0; i < globalWritableFileInfos.CountItems(); ++i) { 427 BGlobalWritableFileInfo* info = globalWritableFileInfos.ItemAt(i); 428 PackageAttribute* attribute = AddStringAttribute( 429 B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE, info->Path(), 430 attributeList); 431 432 if (info->IsDirectory()) { 433 PackageAttribute* isDirectoryAttribute = new PackageAttribute( 434 B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY, 435 B_HPKG_ATTRIBUTE_TYPE_UINT, 436 B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); 437 isDirectoryAttribute->unsignedInt = 1; 438 attribute->children.Add(isDirectoryAttribute); 439 } 440 441 if (info->IsIncluded()) { 442 PackageAttribute* updateTypeAttribute = new PackageAttribute( 443 B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE, 444 B_HPKG_ATTRIBUTE_TYPE_UINT, 445 B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); 446 updateTypeAttribute->unsignedInt = info->UpdateType(); 447 attribute->children.Add(updateTypeAttribute); 448 } 449 } 450 451 // user settings file info list 452 const BObjectList<BUserSettingsFileInfo>& userSettingsFileInfos 453 = packageInfo.UserSettingsFileInfos(); 454 for (int32 i = 0; i < userSettingsFileInfos.CountItems(); ++i) { 455 BUserSettingsFileInfo* info = userSettingsFileInfos.ItemAt(i); 456 PackageAttribute* attribute = AddStringAttribute( 457 B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE, info->Path(), 458 attributeList); 459 460 if (info->IsDirectory()) { 461 PackageAttribute* isDirectoryAttribute = new PackageAttribute( 462 B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY, 463 B_HPKG_ATTRIBUTE_TYPE_UINT, 464 B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); 465 isDirectoryAttribute->unsignedInt = 1; 466 attribute->children.Add(isDirectoryAttribute); 467 } else { 468 _AddStringAttributeIfNotEmpty( 469 B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE, 470 info->TemplatePath(), attribute->children); 471 } 472 } 473 474 // user list 475 const BObjectList<BUser>& users = packageInfo.Users(); 476 for (int32 i = 0; i < users.CountItems(); ++i) { 477 const BUser* user = users.ItemAt(i); 478 PackageAttribute* attribute = AddStringAttribute( 479 B_HPKG_ATTRIBUTE_ID_PACKAGE_USER, user->Name(), attributeList); 480 481 _AddStringAttributeIfNotEmpty( 482 B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME, user->RealName(), 483 attribute->children); 484 _AddStringAttributeIfNotEmpty( 485 B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME, user->Home(), 486 attribute->children); 487 _AddStringAttributeIfNotEmpty( 488 B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL, user->Shell(), 489 attribute->children); 490 491 for (int32 k = 0; k < user->Groups().CountStrings(); k++) { 492 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP, 493 user->Groups().StringAt(k), attribute->children); 494 } 495 } 496 497 // group list 498 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP, 499 packageInfo.Groups(), attributeList); 500 501 // post install script list 502 _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT, 503 packageInfo.PostInstallScripts(), attributeList); 504 505 // checksum (optional, only exists in repositories) 506 _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM, 507 packageInfo.Checksum(), attributeList); 508 509 // install path (optional) 510 _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH, 511 packageInfo.InstallPath(), attributeList); 512} 513 514 515void 516WriterImplBase::RegisterPackageVersion(PackageAttributeList& attributeList, 517 const BPackageVersion& version, BHPKGAttributeID attributeID) 518{ 519 PackageAttribute* versionMajor = AddStringAttribute(attributeID, 520 version.Major(), attributeList); 521 522 if (!version.Minor().IsEmpty()) { 523 AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR, 524 version.Minor(), versionMajor->children); 525 _AddStringAttributeIfNotEmpty( 526 B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO, version.Micro(), 527 versionMajor->children); 528 } 529 530 _AddStringAttributeIfNotEmpty( 531 B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE, 532 version.PreRelease(), versionMajor->children); 533 534 if (version.Revision() != 0) { 535 PackageAttribute* versionRevision = new PackageAttribute( 536 B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION, 537 B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT); 538 versionRevision->unsignedInt = version.Revision(); 539 versionMajor->children.Add(versionRevision); 540 } 541} 542 543 544void 545WriterImplBase::RegisterPackageResolvableExpressionList( 546 PackageAttributeList& attributeList, 547 const BObjectList<BPackageResolvableExpression>& expressionList, uint8 id) 548{ 549 for (int i = 0; i < expressionList.CountItems(); ++i) { 550 BPackageResolvableExpression* resolvableExpr = expressionList.ItemAt(i); 551 PackageAttribute* name = AddStringAttribute((BHPKGAttributeID)id, 552 resolvableExpr->Name(), attributeList); 553 554 if (resolvableExpr->Version().InitCheck() == B_OK) { 555 PackageAttribute* op = new PackageAttribute( 556 B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR, 557 B_HPKG_ATTRIBUTE_TYPE_UINT, 558 B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); 559 op->unsignedInt = resolvableExpr->Operator(); 560 name->children.Add(op); 561 RegisterPackageVersion(name->children, resolvableExpr->Version()); 562 } 563 } 564} 565 566 567WriterImplBase::PackageAttribute* 568WriterImplBase::AddStringAttribute(BHPKGAttributeID id, const BString& value, 569 DoublyLinkedList<PackageAttribute>& list) 570{ 571 PackageAttribute* attribute = new PackageAttribute(id, 572 B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); 573 attribute->string = fPackageStringCache.Get(value); 574 list.Add(attribute); 575 return attribute; 576} 577 578 579int32 580WriterImplBase::WriteCachedStrings(const StringCache& cache, 581 uint32 minUsageCount) 582{ 583 // create an array of the cached strings 584 int32 count = cache.CountElements(); 585 CachedString** cachedStrings = new CachedString*[count]; 586 ArrayDeleter<CachedString*> cachedStringsDeleter(cachedStrings); 587 588 int32 index = 0; 589 for (CachedStringTable::Iterator it = cache.GetIterator(); 590 CachedString* string = it.Next();) { 591 cachedStrings[index++] = string; 592 } 593 594 // sort it by descending usage count 595 std::sort(cachedStrings, cachedStrings + count, CachedStringUsageGreater()); 596 597 // assign the indices and write entries to disk 598 int32 stringsWritten = 0; 599 for (int32 i = 0; i < count; i++) { 600 CachedString* cachedString = cachedStrings[i]; 601 602 // empty strings must be stored inline, as they can't be distinguished 603 // from the end-marker! 604 if (strlen(cachedString->string) == 0) 605 continue; 606 607 // strings that are used only once are better stored inline 608 if (cachedString->usageCount < minUsageCount) 609 break; 610 611 WriteString(cachedString->string); 612 613 cachedString->index = stringsWritten++; 614 } 615 616 // write a terminating 0 byte 617 Write<uint8>(0); 618 619 return stringsWritten; 620} 621 622 623int32 624WriterImplBase::WritePackageAttributes( 625 const PackageAttributeList& packageAttributes, 626 uint32& _stringsLengthUncompressed) 627{ 628 // write the cached strings 629 uint64 startOffset = fHeapWriter->UncompressedHeapSize(); 630 uint32 stringsCount = WriteCachedStrings(fPackageStringCache, 2); 631 _stringsLengthUncompressed 632 = fHeapWriter->UncompressedHeapSize() - startOffset; 633 634 _WritePackageAttributes(packageAttributes); 635 636 return stringsCount; 637} 638 639 640void 641WriterImplBase::WriteAttributeValue(const AttributeValue& value, uint8 encoding) 642{ 643 switch (value.type) { 644 case B_HPKG_ATTRIBUTE_TYPE_INT: 645 case B_HPKG_ATTRIBUTE_TYPE_UINT: 646 { 647 uint64 intValue = value.type == B_HPKG_ATTRIBUTE_TYPE_INT 648 ? (uint64)value.signedInt : value.unsignedInt; 649 650 switch (encoding) { 651 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 652 Write<uint8>((uint8)intValue); 653 break; 654 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 655 Write<uint16>( 656 B_HOST_TO_BENDIAN_INT16((uint16)intValue)); 657 break; 658 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 659 Write<uint32>( 660 B_HOST_TO_BENDIAN_INT32((uint32)intValue)); 661 break; 662 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 663 Write<uint64>( 664 B_HOST_TO_BENDIAN_INT64((uint64)intValue)); 665 break; 666 default: 667 { 668 fErrorOutput->PrintError("WriteAttributeValue(): invalid " 669 "encoding %d for int value type %d\n", encoding, 670 value.type); 671 throw status_t(B_BAD_VALUE); 672 } 673 } 674 675 break; 676 } 677 678 case B_HPKG_ATTRIBUTE_TYPE_STRING: 679 { 680 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) 681 WriteUnsignedLEB128(value.string->index); 682 else 683 WriteString(value.string->string); 684 break; 685 } 686 687 case B_HPKG_ATTRIBUTE_TYPE_RAW: 688 { 689 WriteUnsignedLEB128(value.data.size); 690 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP) 691 WriteUnsignedLEB128(value.data.offset); 692 else 693 fHeapWriter->AddDataThrows(value.data.raw, value.data.size); 694 break; 695 } 696 697 default: 698 fErrorOutput->PrintError( 699 "WriteAttributeValue(): invalid value type: %d\n", value.type); 700 throw status_t(B_BAD_VALUE); 701 } 702} 703 704 705void 706WriterImplBase::WriteUnsignedLEB128(uint64 value) 707{ 708 uint8 bytes[10]; 709 int32 count = 0; 710 do { 711 uint8 byte = value & 0x7f; 712 value >>= 7; 713 bytes[count++] = byte | (value != 0 ? 0x80 : 0); 714 } while (value != 0); 715 716 fHeapWriter->AddDataThrows(bytes, count); 717} 718 719 720void 721WriterImplBase::RawWriteBuffer(const void* buffer, size_t size, off_t offset) 722{ 723 status_t error = fFile->WriteAtExactly(offset, buffer, size); 724 if (error != B_OK) { 725 fErrorOutput->PrintError( 726 "RawWriteBuffer(%p, %lu) failed to write data: %s\n", buffer, size, 727 strerror(error)); 728 throw error; 729 } 730} 731 732 733void 734WriterImplBase::_AddStringAttributeList(BHPKGAttributeID id, 735 const BStringList& value, DoublyLinkedList<PackageAttribute>& list) 736{ 737 for (int32 i = 0; i < value.CountStrings(); i++) 738 AddStringAttribute(id, value.StringAt(i), list); 739} 740 741 742void 743WriterImplBase::_WritePackageAttributes( 744 const PackageAttributeList& packageAttributes) 745{ 746 DoublyLinkedList<PackageAttribute>::ConstIterator it 747 = packageAttributes.GetIterator(); 748 while (PackageAttribute* attribute = it.Next()) { 749 uint8 encoding = attribute->ApplicableEncoding(); 750 751 // write tag 752 WriteUnsignedLEB128(compose_attribute_tag( 753 attribute->id, attribute->type, encoding, 754 !attribute->children.IsEmpty())); 755 756 // write value 757 WriteAttributeValue(*attribute, encoding); 758 759 if (!attribute->children.IsEmpty()) 760 _WritePackageAttributes(attribute->children); 761 } 762 763 WriteUnsignedLEB128(0); 764} 765 766 767} // namespace BPrivate 768 769} // namespace BHPKG 770 771} // namespace BPackageKit 772