2 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
4 * Distributed under the terms of the MIT License.
8 #include <package/hpkg/ReaderImplBase.h>
19 #include <ByteOrder.h>
22 #include <ZlibCompressionAlgorithm.h>
24 #include <package/hpkg/HPKGDefsPrivate.h>
25 #include <package/hpkg/PackageFileHeapReader.h>
28 namespace BPackageKit
{
35 static const size_t kScratchBufferSize
= 64 * 1024;
37 static const uint16 kAttributeTypes
[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT
] = {
38 #define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant) \
39 B_HPKG_ATTRIBUTE_TYPE_##type,
40 #include <package/hpkg/PackageAttributes.h>
41 #undef B_DEFINE_HPKG_ATTRIBUTE
44 // #pragma mark - AttributeHandlerContext
47 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
48 BErrorOutput
* errorOutput
, BPackageContentHandler
* packageContentHandler
,
49 BHPKGPackageSectionID section
, bool ignoreUnknownAttributes
)
51 errorOutput(errorOutput
),
52 packageContentHandler(packageContentHandler
),
53 hasLowLevelHandler(false),
54 ignoreUnknownAttributes(ignoreUnknownAttributes
),
60 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
61 BErrorOutput
* errorOutput
, BLowLevelPackageContentHandler
* lowLevelHandler
,
62 BHPKGPackageSectionID section
, bool ignoreUnknownAttributes
)
64 errorOutput(errorOutput
),
65 lowLevelHandler(lowLevelHandler
),
66 hasLowLevelHandler(true),
67 ignoreUnknownAttributes(ignoreUnknownAttributes
),
74 ReaderImplBase::AttributeHandlerContext::ErrorOccurred()
76 if (hasLowLevelHandler
)
77 lowLevelHandler
->HandleErrorOccurred();
79 packageContentHandler
->HandleErrorOccurred();
83 // #pragma mark - AttributeHandler
86 ReaderImplBase::AttributeHandler::~AttributeHandler()
92 ReaderImplBase::AttributeHandler::SetLevel(int level
)
99 ReaderImplBase::AttributeHandler::HandleAttribute(
100 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
101 AttributeHandler
** _handler
)
108 ReaderImplBase::AttributeHandler::NotifyDone(
109 AttributeHandlerContext
* context
)
116 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext
* context
)
123 // #pragma mark - PackageInfoAttributeHandlerBase
126 ReaderImplBase::PackageInfoAttributeHandlerBase
127 ::PackageInfoAttributeHandlerBase(
128 BPackageInfoAttributeValue
& packageInfoValue
)
130 fPackageInfoValue(packageInfoValue
)
136 ReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone(
137 AttributeHandlerContext
* context
)
139 status_t error
= context
->packageContentHandler
->HandlePackageAttribute(
141 fPackageInfoValue
.Clear();
146 // #pragma mark - PackageVersionAttributeHandler
149 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
150 BPackageInfoAttributeValue
& packageInfoValue
,
151 BPackageVersionData
& versionData
, bool notify
)
153 super(packageInfoValue
),
154 fPackageVersionData(versionData
),
161 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
162 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
163 AttributeHandler
** _handler
)
166 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR
:
167 fPackageVersionData
.minor
= value
.string
;
170 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO
:
171 fPackageVersionData
.micro
= value
.string
;
174 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE
:
175 fPackageVersionData
.preRelease
= value
.string
;
178 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION
:
179 fPackageVersionData
.revision
= value
.unsignedInt
;
183 if (context
->ignoreUnknownAttributes
)
186 context
->errorOutput
->PrintError("Error: Invalid package "
187 "attribute section: unexpected package attribute id %d "
188 "encountered when parsing package version\n", id
);
197 ReaderImplBase::PackageVersionAttributeHandler::NotifyDone(
198 AttributeHandlerContext
* context
)
203 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_VERSION
;
204 return super::NotifyDone(context
);
208 // #pragma mark - PackageResolvableAttributeHandler
211 ReaderImplBase::PackageResolvableAttributeHandler
212 ::PackageResolvableAttributeHandler(
213 BPackageInfoAttributeValue
& packageInfoValue
)
215 super(packageInfoValue
)
221 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
222 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
223 AttributeHandler
** _handler
)
226 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR
:
227 fPackageInfoValue
.resolvable
.haveVersion
= true;
228 fPackageInfoValue
.resolvable
.version
.major
= value
.string
;
229 if (_handler
!= NULL
) {
231 = new(std::nothrow
) PackageVersionAttributeHandler(
233 fPackageInfoValue
.resolvable
.version
, false);
234 if (*_handler
== NULL
)
239 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE
:
240 fPackageInfoValue
.resolvable
.haveCompatibleVersion
= true;
241 fPackageInfoValue
.resolvable
.compatibleVersion
.major
= value
.string
;
242 if (_handler
!= NULL
) {
244 = new(std::nothrow
) PackageVersionAttributeHandler(
246 fPackageInfoValue
.resolvable
.compatibleVersion
, false);
247 if (*_handler
== NULL
)
253 if (context
->ignoreUnknownAttributes
)
256 context
->errorOutput
->PrintError("Error: Invalid package "
257 "attribute section: unexpected package attribute id %d "
258 "encountered when parsing package resolvable\n", id
);
266 // #pragma mark - PackageResolvableExpressionAttributeHandler
269 ReaderImplBase::PackageResolvableExpressionAttributeHandler
270 ::PackageResolvableExpressionAttributeHandler(
271 BPackageInfoAttributeValue
& packageInfoValue
)
273 super(packageInfoValue
)
279 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
280 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
281 AttributeHandler
** _handler
)
284 case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR
:
285 if (value
.unsignedInt
>= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT
) {
286 context
->errorOutput
->PrintError(
287 "Error: Invalid package attribute section: invalid "
288 "package resolvable operator %lld encountered\n",
292 fPackageInfoValue
.resolvableExpression
.op
293 = (BPackageResolvableOperator
)value
.unsignedInt
;
296 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR
:
297 fPackageInfoValue
.resolvableExpression
.haveOpAndVersion
= true;
298 fPackageInfoValue
.resolvableExpression
.version
.major
300 if (_handler
!= NULL
) {
302 = new(std::nothrow
) PackageVersionAttributeHandler(
304 fPackageInfoValue
.resolvableExpression
.version
,
306 if (*_handler
== NULL
)
312 if (context
->ignoreUnknownAttributes
)
315 context
->errorOutput
->PrintError("Error: Invalid package "
316 "attribute section: unexpected package attribute id %d "
317 "encountered when parsing package resolvable-expression\n",
326 // #pragma mark - GlobalWritableFileInfoAttributeHandler
329 ReaderImplBase::GlobalWritableFileInfoAttributeHandler
330 ::GlobalWritableFileInfoAttributeHandler(
331 BPackageInfoAttributeValue
& packageInfoValue
)
333 super(packageInfoValue
)
339 ReaderImplBase::GlobalWritableFileInfoAttributeHandler::HandleAttribute(
340 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
341 AttributeHandler
** _handler
)
344 case B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE
:
345 if (value
.unsignedInt
>= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT
) {
346 context
->errorOutput
->PrintError(
347 "Error: Invalid package attribute section: invalid "
348 "global settings file update type %" B_PRIu64
349 " encountered\n", value
.unsignedInt
);
352 fPackageInfoValue
.globalWritableFileInfo
.updateType
353 = (BWritableFileUpdateType
)value
.unsignedInt
;
356 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY
:
357 fPackageInfoValue
.globalWritableFileInfo
.isDirectory
358 = value
.unsignedInt
!= 0;
362 if (context
->ignoreUnknownAttributes
)
365 context
->errorOutput
->PrintError("Error: Invalid package "
366 "attribute section: unexpected package attribute id %d "
367 "encountered when parsing global settings file info\n",
376 // #pragma mark - UserSettingsFileInfoAttributeHandler
379 ReaderImplBase::UserSettingsFileInfoAttributeHandler
380 ::UserSettingsFileInfoAttributeHandler(
381 BPackageInfoAttributeValue
& packageInfoValue
)
383 super(packageInfoValue
)
389 ReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute(
390 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
391 AttributeHandler
** _handler
)
394 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE
:
395 fPackageInfoValue
.userSettingsFileInfo
.templatePath
= value
.string
;
398 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY
:
399 fPackageInfoValue
.userSettingsFileInfo
.isDirectory
400 = value
.unsignedInt
!= 0;
404 if (context
->ignoreUnknownAttributes
)
407 context
->errorOutput
->PrintError("Error: Invalid package "
408 "attribute section: unexpected package attribute id %d "
409 "encountered when parsing user settings file info\n",
418 // #pragma mark - UserAttributeHandler
421 ReaderImplBase::UserAttributeHandler::UserAttributeHandler(
422 BPackageInfoAttributeValue
& packageInfoValue
)
424 super(packageInfoValue
),
431 ReaderImplBase::UserAttributeHandler::HandleAttribute(
432 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
433 AttributeHandler
** _handler
)
436 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME
:
437 fPackageInfoValue
.user
.realName
= value
.string
;
440 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME
:
441 fPackageInfoValue
.user
.home
= value
.string
;
444 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL
:
445 fPackageInfoValue
.user
.shell
= value
.string
;
448 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP
:
449 if (!fGroups
.Add(value
.string
))
454 if (context
->ignoreUnknownAttributes
)
457 context
->errorOutput
->PrintError("Error: Invalid package "
458 "attribute section: unexpected package attribute id %d "
459 "encountered when parsing user settings file info\n",
469 ReaderImplBase::UserAttributeHandler::NotifyDone(
470 AttributeHandlerContext
* context
)
472 if (!fGroups
.IsEmpty()) {
473 fPackageInfoValue
.user
.groups
= fGroups
.Elements();
474 fPackageInfoValue
.user
.groupCount
= fGroups
.Count();
477 return super::NotifyDone(context
);
481 // #pragma mark - PackageAttributeHandler
485 ReaderImplBase::PackageAttributeHandler::HandleAttribute(
486 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
487 AttributeHandler
** _handler
)
490 case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME
:
491 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_NAME
, value
.string
);
494 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY
:
495 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_SUMMARY
, value
.string
);
498 case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION
:
499 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_DESCRIPTION
,
503 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR
:
504 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_VENDOR
, value
.string
);
507 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER
:
508 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_PACKAGER
, value
.string
);
511 case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE
:
512 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_BASE_PACKAGE
, value
.string
);
515 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS
:
516 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_FLAGS
,
517 (uint32
)value
.unsignedInt
);
520 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE
:
521 if (value
.unsignedInt
522 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT
) {
523 context
->errorOutput
->PrintError(
524 "Error: Invalid package attribute section: "
525 "Invalid package architecture %lld encountered\n",
529 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_ARCHITECTURE
,
530 (uint8
)value
.unsignedInt
);
533 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR
:
534 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_VERSION
;
535 fPackageInfoValue
.version
.major
= value
.string
;
536 if (_handler
!= NULL
) {
538 = new(std::nothrow
) PackageVersionAttributeHandler(
539 fPackageInfoValue
, fPackageInfoValue
.version
, true);
540 if (*_handler
== NULL
)
545 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT
:
546 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_COPYRIGHTS
,
550 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE
:
551 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_LICENSES
,
555 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL
:
556 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_URLS
, value
.string
);
559 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL
:
560 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_SOURCE_URLS
, value
.string
);
563 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES
:
564 fPackageInfoValue
.resolvable
.name
= value
.string
;
565 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_PROVIDES
;
566 if (_handler
!= NULL
) {
568 = new(std::nothrow
) PackageResolvableAttributeHandler(
570 if (*_handler
== NULL
)
575 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES
:
576 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS
:
577 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS
:
578 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS
:
579 fPackageInfoValue
.resolvableExpression
.name
= value
.string
;
581 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES
:
582 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_REQUIRES
;
585 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS
:
586 fPackageInfoValue
.attributeID
587 = B_PACKAGE_INFO_SUPPLEMENTS
;
590 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS
:
591 fPackageInfoValue
.attributeID
592 = B_PACKAGE_INFO_CONFLICTS
;
595 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS
:
596 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_FRESHENS
;
599 if (_handler
!= NULL
) {
600 *_handler
= new(std::nothrow
)
601 PackageResolvableExpressionAttributeHandler(
603 if (*_handler
== NULL
)
608 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES
:
609 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_REPLACES
, value
.string
);
612 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM
:
613 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_CHECKSUM
, value
.string
);
616 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH
:
617 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_INSTALL_PATH
, value
.string
);
620 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE
:
621 fPackageInfoValue
.globalWritableFileInfo
.path
= value
.string
;
622 fPackageInfoValue
.globalWritableFileInfo
.updateType
623 = B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT
;
624 fPackageInfoValue
.attributeID
625 = B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES
;
626 if (_handler
!= NULL
) {
628 = new(std::nothrow
) GlobalWritableFileInfoAttributeHandler(
630 if (*_handler
== NULL
)
635 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE
:
636 fPackageInfoValue
.userSettingsFileInfo
.path
= value
.string
;
637 fPackageInfoValue
.attributeID
638 = B_PACKAGE_INFO_USER_SETTINGS_FILES
;
639 if (_handler
!= NULL
) {
641 = new(std::nothrow
) UserSettingsFileInfoAttributeHandler(
643 if (*_handler
== NULL
)
648 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER
:
649 fPackageInfoValue
.user
.name
= value
.string
;
650 fPackageInfoValue
.attributeID
= B_PACKAGE_INFO_USERS
;
651 if (_handler
!= NULL
) {
652 *_handler
= new(std::nothrow
) UserAttributeHandler(
654 if (*_handler
== NULL
)
659 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP
:
660 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_GROUPS
, value
.string
);
663 case B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT
:
664 fPackageInfoValue
.SetTo(B_PACKAGE_INFO_POST_INSTALL_SCRIPTS
,
669 if (context
->ignoreUnknownAttributes
)
672 context
->errorOutput
->PrintError(
673 "Error: Invalid package attribute section: unexpected "
674 "package attribute id %d encountered\n", id
);
678 // notify unless the current attribute has children, in which case
679 // the child-handler will notify when it's done
680 if (_handler
== NULL
) {
681 status_t error
= context
->packageContentHandler
682 ->HandlePackageAttribute(fPackageInfoValue
);
683 fPackageInfoValue
.Clear();
692 // #pragma mark - LowLevelAttributeHandler
695 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
699 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT
)
704 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id
,
705 const BPackageAttributeValue
& value
, void* parentToken
, void* token
)
716 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
717 AttributeHandlerContext
* context
, uint8 id
, const AttributeValue
& value
,
718 AttributeHandler
** _handler
)
720 // notify the content handler
722 status_t error
= context
->lowLevelHandler
->HandleAttribute(
723 (BHPKGAttributeID
)id
, value
, fToken
, token
);
727 // create a subhandler for the attribute, if it has children
728 if (_handler
!= NULL
) {
729 *_handler
= new(std::nothrow
) LowLevelAttributeHandler(id
, value
,
731 if (*_handler
== NULL
) {
732 context
->lowLevelHandler
->HandleAttributeDone((BHPKGAttributeID
)id
,
733 value
, fToken
, token
);
739 // no children -- just call the done hook
740 return context
->lowLevelHandler
->HandleAttributeDone((BHPKGAttributeID
)id
,
741 value
, fToken
, token
);
746 ReaderImplBase::LowLevelAttributeHandler::NotifyDone(
747 AttributeHandlerContext
* context
)
749 if (fID
!= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT
) {
750 status_t error
= context
->lowLevelHandler
->HandleAttributeDone(
751 (BHPKGAttributeID
)fID
, fValue
, fParentToken
, fToken
);
755 return super::NotifyDone(context
);
759 // #pragma mark - ReaderImplBase
762 ReaderImplBase::ReaderImplBase(const char* fileType
, BErrorOutput
* errorOutput
)
764 fPackageAttributesSection("package attributes"),
766 fErrorOutput(errorOutput
),
769 fRawHeapReader(NULL
),
771 fCurrentSection(NULL
)
776 ReaderImplBase::~ReaderImplBase()
779 if (fRawHeapReader
!= fHeapReader
)
780 delete fRawHeapReader
;
788 ReaderImplBase::UncompressedHeapSize() const
790 return fRawHeapReader
->UncompressedHeapSize();
794 BAbstractBufferedDataReader
*
795 ReaderImplBase::DetachHeapReader(PackageFileHeapReader
*& _rawHeapReader
)
797 BAbstractBufferedDataReader
* heapReader
= fHeapReader
;
798 _rawHeapReader
= fRawHeapReader
;
800 fRawHeapReader
= NULL
;
807 ReaderImplBase::InitHeapReader(uint32 compression
, uint32 chunkSize
,
808 off_t offset
, uint64 compressedSize
, uint64 uncompressedSize
)
810 DecompressionAlgorithmOwner
* decompressionAlgorithm
= NULL
;
811 BReference
<DecompressionAlgorithmOwner
> decompressionAlgorithmReference
;
813 switch (compression
) {
814 case B_HPKG_COMPRESSION_NONE
:
816 case B_HPKG_COMPRESSION_ZLIB
:
817 decompressionAlgorithm
= DecompressionAlgorithmOwner::Create(
818 new(std::nothrow
) BZlibCompressionAlgorithm
,
819 new(std::nothrow
) BZlibDecompressionParameters
);
820 decompressionAlgorithmReference
.SetTo(decompressionAlgorithm
, true);
821 if (decompressionAlgorithm
== NULL
822 || decompressionAlgorithm
->algorithm
== NULL
823 || decompressionAlgorithm
->parameters
== NULL
) {
828 fErrorOutput
->PrintError("Error: Invalid heap compression\n");
832 fRawHeapReader
= new(std::nothrow
) PackageFileHeapReader(fErrorOutput
,
833 fFile
, offset
, compressedSize
, uncompressedSize
,
834 decompressionAlgorithm
);
835 if (fRawHeapReader
== NULL
)
838 status_t error
= fRawHeapReader
->Init();
842 error
= CreateCachedHeapReader(fRawHeapReader
, fHeapReader
);
844 if (error
!= B_NOT_SUPPORTED
)
847 fHeapReader
= fRawHeapReader
;
855 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader
* heapReader
,
856 BAbstractBufferedDataReader
*& _cachedReader
)
858 return B_NOT_SUPPORTED
;
863 ReaderImplBase::InitSection(PackageFileSection
& section
, uint64 endOffset
,
864 uint64 length
, uint64 maxSaneLength
, uint64 stringsLength
,
867 // check length vs. endOffset
868 if (length
> endOffset
) {
869 ErrorOutput()->PrintError("Error: %s file %s section size is %"
870 B_PRIu64
" bytes. This is greater than the available space\n",
871 fFileType
, section
.name
, length
);
875 // check sanity length
876 if (maxSaneLength
> 0 && length
> maxSaneLength
) {
877 ErrorOutput()->PrintError("Error: %s file %s section size is %"
878 B_PRIu64
" bytes. This is beyond the reader's sanity limit\n",
879 fFileType
, section
.name
, length
);
880 return B_NOT_SUPPORTED
;
883 // check strings subsection size/count
884 if ((stringsLength
<= 1) != (stringsCount
== 0) || stringsLength
> length
) {
885 ErrorOutput()->PrintError("Error: strings subsection description of %s "
886 "file %s section is invalid (%" B_PRIu64
" strings, length: %"
887 B_PRIu64
", section length: %" B_PRIu64
")\n",
888 fFileType
, section
.name
, stringsCount
, stringsLength
, length
);
892 section
.uncompressedLength
= length
;
893 section
.offset
= endOffset
- length
;
894 section
.currentOffset
= 0;
895 section
.stringsLength
= stringsLength
;
896 section
.stringsCount
= stringsCount
;
903 ReaderImplBase::PrepareSection(PackageFileSection
& section
)
905 // allocate memory for the section data and read it in
906 section
.data
= new(std::nothrow
) uint8
[section
.uncompressedLength
];
907 if (section
.data
== NULL
) {
908 ErrorOutput()->PrintError("Error: Out of memory!\n");
912 status_t error
= ReadSection(section
);
916 // parse the section strings
917 section
.currentOffset
= 0;
918 SetCurrentSection(§ion
);
920 error
= ParseStrings();
929 ReaderImplBase::ParseStrings()
931 // allocate table, if there are any strings
932 if (fCurrentSection
->stringsCount
== 0) {
933 fCurrentSection
->currentOffset
+= fCurrentSection
->stringsLength
;
937 fCurrentSection
->strings
938 = new(std::nothrow
) char*[fCurrentSection
->stringsCount
];
939 if (fCurrentSection
->strings
== NULL
) {
940 fErrorOutput
->PrintError("Error: Out of memory!\n");
944 // parse the section and fill the table
946 = (char*)fCurrentSection
->data
+ fCurrentSection
->currentOffset
;
947 char* sectionEnd
= position
+ fCurrentSection
->stringsLength
;
950 if (position
>= sectionEnd
) {
951 fErrorOutput
->PrintError("Error: Malformed %s strings section\n",
952 fCurrentSection
->name
);
956 size_t stringLength
= strnlen(position
, (char*)sectionEnd
- position
);
958 if (stringLength
== 0) {
959 if (position
+ 1 != sectionEnd
) {
960 fErrorOutput
->PrintError(
961 "Error: %ld excess bytes in %s strings section\n",
962 sectionEnd
- (position
+ 1), fCurrentSection
->name
);
966 if (index
!= fCurrentSection
->stringsCount
) {
967 fErrorOutput
->PrintError("Error: Invalid %s strings section: "
968 "Less strings (%lld) than specified in the header (%lld)\n",
969 fCurrentSection
->name
, index
,
970 fCurrentSection
->stringsCount
);
974 fCurrentSection
->currentOffset
+= fCurrentSection
->stringsLength
;
979 if (index
>= fCurrentSection
->stringsCount
) {
980 fErrorOutput
->PrintError("Error: Invalid %s strings section: "
981 "More strings (%lld) than specified in the header (%lld)\n",
982 fCurrentSection
->name
, index
, fCurrentSection
->stringsCount
);
986 fCurrentSection
->strings
[index
++] = position
;
987 position
+= stringLength
+ 1;
993 ReaderImplBase::ParsePackageAttributesSection(
994 AttributeHandlerContext
* context
, AttributeHandler
* rootAttributeHandler
)
996 // parse package attributes
997 SetCurrentSection(&fPackageAttributesSection
);
999 // init the attribute handler stack
1000 rootAttributeHandler
->SetLevel(0);
1001 ClearAttributeHandlerStack();
1002 PushAttributeHandler(rootAttributeHandler
);
1004 bool sectionHandled
;
1005 status_t error
= ParseAttributeTree(context
, sectionHandled
);
1006 if (error
== B_OK
&& sectionHandled
) {
1007 if (fPackageAttributesSection
.currentOffset
1008 < fPackageAttributesSection
.uncompressedLength
) {
1009 fErrorOutput
->PrintError("Error: %llu excess byte(s) in package "
1010 "attributes section\n",
1011 fPackageAttributesSection
.uncompressedLength
1012 - fPackageAttributesSection
.currentOffset
);
1017 SetCurrentSection(NULL
);
1019 // clean up on error
1020 if (error
!= B_OK
) {
1021 context
->ErrorOccurred();
1022 while (AttributeHandler
* handler
= PopAttributeHandler()) {
1023 if (handler
!= rootAttributeHandler
)
1024 handler
->Delete(context
);
1034 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext
* context
,
1035 bool& _sectionHandled
)
1037 if (context
->hasLowLevelHandler
) {
1038 bool handleSection
= false;
1039 status_t error
= context
->lowLevelHandler
->HandleSectionStart(
1040 context
->section
, handleSection
);
1044 if (!handleSection
) {
1045 _sectionHandled
= false;
1050 status_t error
= _ParseAttributeTree(context
);
1052 if (context
->hasLowLevelHandler
) {
1053 status_t endError
= context
->lowLevelHandler
->HandleSectionEnd(
1059 _sectionHandled
= true;
1065 ReaderImplBase::_Init(BPositionIO
* file
, bool keepFile
)
1068 fOwnsFile
= keepFile
;
1069 return fFile
!= NULL
? B_OK
: B_BAD_VALUE
;
1074 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext
* context
)
1080 AttributeValue value
;
1084 status_t error
= _ReadAttribute(id
, value
, &hasChildren
, &tag
);
1089 AttributeHandler
* handler
= PopAttributeHandler();
1090 error
= handler
->NotifyDone(context
);
1096 error
= handler
->Delete(context
);
1103 AttributeHandler
* childHandler
= NULL
;
1104 error
= CurrentAttributeHandler()->HandleAttribute(context
, id
, value
,
1105 hasChildren
? &childHandler
: NULL
);
1111 // create an ignore handler, if necessary
1112 if (childHandler
== NULL
) {
1113 childHandler
= new(std::nothrow
) IgnoreAttributeHandler
;
1114 if (childHandler
== NULL
) {
1115 fErrorOutput
->PrintError("Error: Out of memory!\n");
1120 childHandler
->SetLevel(++level
);
1121 PushAttributeHandler(childHandler
);
1128 ReaderImplBase::_ReadAttribute(uint8
& _id
, AttributeValue
& _value
,
1129 bool* _hasChildren
, uint64
* _tag
)
1132 status_t error
= ReadUnsignedLEB128(tag
);
1138 uint16 type
= attribute_tag_type(tag
);
1139 if (type
>= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT
) {
1140 fErrorOutput
->PrintError("Error: Invalid %s section: attribute "
1141 "type %d not supported!\n", fCurrentSection
->name
, type
);
1146 _id
= attribute_tag_id(tag
);
1147 if (_id
< B_HPKG_ATTRIBUTE_ID_ENUM_COUNT
) {
1148 if (type
!= kAttributeTypes
[_id
]) {
1149 fErrorOutput
->PrintError("Error: Invalid %s section: "
1150 "unexpected type %d for attribute id %d (expected %d)!\n",
1151 fCurrentSection
->name
, type
, _id
, kAttributeTypes
[_id
]);
1154 } else if (fMinorFormatVersion
<= fCurrentMinorFormatVersion
) {
1155 fErrorOutput
->PrintError("Error: Invalid %s section: "
1156 "attribute id %d not supported!\n", fCurrentSection
->name
, _id
);
1161 error
= ReadAttributeValue(type
, attribute_tag_encoding(tag
),
1167 if (_hasChildren
!= NULL
)
1168 *_hasChildren
= attribute_tag_has_children(tag
);
1177 ReaderImplBase::ReadAttributeValue(uint8 type
, uint8 encoding
,
1178 AttributeValue
& _value
)
1181 case B_HPKG_ATTRIBUTE_TYPE_INT
:
1182 case B_HPKG_ATTRIBUTE_TYPE_UINT
:
1188 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT
:
1191 error
= _Read(value
);
1195 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT
:
1198 error
= _Read(value
);
1199 intValue
= B_BENDIAN_TO_HOST_INT16(value
);
1202 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT
:
1205 error
= _Read(value
);
1206 intValue
= B_BENDIAN_TO_HOST_INT32(value
);
1209 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT
:
1212 error
= _Read(value
);
1213 intValue
= B_BENDIAN_TO_HOST_INT64(value
);
1218 fErrorOutput
->PrintError("Error: Invalid %s section: "
1219 "invalid encoding %d for int value type %d\n",
1220 fCurrentSection
->name
, encoding
, type
);
1228 if (type
== B_HPKG_ATTRIBUTE_TYPE_INT
)
1229 _value
.SetTo((int64
)intValue
);
1231 _value
.SetTo(intValue
);
1236 case B_HPKG_ATTRIBUTE_TYPE_STRING
:
1238 if (encoding
== B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE
) {
1240 status_t error
= ReadUnsignedLEB128(index
);
1244 if (index
> fCurrentSection
->stringsCount
) {
1245 fErrorOutput
->PrintError("Error: Invalid %s section: "
1246 "string reference (%lld) out of bounds (%lld)\n",
1247 fCurrentSection
->name
, index
,
1248 fCurrentSection
->stringsCount
);
1252 _value
.SetTo(fCurrentSection
->strings
[index
]);
1253 } else if (encoding
== B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE
) {
1255 status_t error
= _ReadString(string
);
1259 _value
.SetTo(string
);
1261 fErrorOutput
->PrintError("Error: Invalid %s section: invalid "
1262 "string encoding (%u)\n", fCurrentSection
->name
, encoding
);
1270 fErrorOutput
->PrintError("Error: Invalid %s section: invalid "
1271 "value type: %d\n", fCurrentSection
->name
, type
);
1278 ReaderImplBase::ReadUnsignedLEB128(uint64
& _value
)
1284 status_t error
= _Read(byte
);
1288 result
|= uint64(byte
& 0x7f) << shift
;
1289 if ((byte
& 0x80) == 0)
1300 ReaderImplBase::_ReadString(const char*& _string
, size_t* _stringLength
)
1303 = (const char*)fCurrentSection
->data
+ fCurrentSection
->currentOffset
;
1304 size_t stringLength
= strnlen(string
,
1305 fCurrentSection
->uncompressedLength
- fCurrentSection
->currentOffset
);
1308 == fCurrentSection
->uncompressedLength
1309 - fCurrentSection
->currentOffset
) {
1310 fErrorOutput
->PrintError(
1311 "_ReadString(): string extends beyond %s end\n",
1312 fCurrentSection
->name
);
1317 if (_stringLength
!= NULL
)
1318 *_stringLength
= stringLength
;
1320 fCurrentSection
->currentOffset
+= stringLength
+ 1;
1326 ReaderImplBase::_ReadSectionBuffer(void* buffer
, size_t size
)
1328 if (size
> fCurrentSection
->uncompressedLength
1329 - fCurrentSection
->currentOffset
) {
1330 fErrorOutput
->PrintError(
1331 "_ReadSectionBuffer(%lu): read beyond %s end\n", size
,
1332 fCurrentSection
->name
);
1336 memcpy(buffer
, fCurrentSection
->data
+ fCurrentSection
->currentOffset
,
1338 fCurrentSection
->currentOffset
+= size
;
1344 ReaderImplBase::ReadBuffer(off_t offset
, void* buffer
, size_t size
)
1346 status_t error
= fFile
->ReadAtExactly(offset
, buffer
, size
);
1347 if (error
!= B_OK
) {
1348 fErrorOutput
->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1349 "%s\n", buffer
, size
, strerror(error
));
1358 ReaderImplBase::ReadSection(const PackageFileSection
& section
)
1360 return fHeapReader
->ReadData(section
.offset
,
1361 section
.data
, section
.uncompressedLength
);
1365 } // namespace BPrivate
1367 } // namespace BHPKG
1369 } // namespace BPackageKit