diff --git a/headers/os/package/PackageInfoAttributes.h b/headers/os/package/PackageInfoAttributes.h index 9ca5120e6a..a6cc093953 100644 --- a/headers/os/package/PackageInfoAttributes.h +++ b/headers/os/package/PackageInfoAttributes.h @@ -9,7 +9,7 @@ namespace BPackageKit { -enum BPackageInfoAttributeIndex { +enum BPackageInfoAttributeID { B_PACKAGE_INFO_NAME = 0, B_PACKAGE_INFO_SUMMARY, // single line B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible diff --git a/headers/os/package/hpkg/HPKGDefs.h b/headers/os/package/hpkg/HPKGDefs.h index 5ae29a0540..c77a1a8ccc 100644 --- a/headers/os/package/hpkg/HPKGDefs.h +++ b/headers/os/package/hpkg/HPKGDefs.h @@ -69,29 +69,49 @@ enum { // package attribute IDs -enum BPackageAttributeID { - B_PACKAGE_ATTRIBUTE_NAME = 0, - B_PACKAGE_ATTRIBUTE_SUMMARY, - B_PACKAGE_ATTRIBUTE_DESCRIPTION, - B_PACKAGE_ATTRIBUTE_VENDOR, - B_PACKAGE_ATTRIBUTE_PACKAGER, - B_PACKAGE_ATTRIBUTE_ARCHITECTURE, - B_PACKAGE_ATTRIBUTE_VERSION_MAJOR, - B_PACKAGE_ATTRIBUTE_VERSION_MINOR, - B_PACKAGE_ATTRIBUTE_VERSION_MICRO, - B_PACKAGE_ATTRIBUTE_VERSION_RELEASE, - B_PACKAGE_ATTRIBUTE_COPYRIGHT, - B_PACKAGE_ATTRIBUTE_LICENSE, - B_PACKAGE_ATTRIBUTE_PROVIDES, - B_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, - B_PACKAGE_ATTRIBUTE_REQUIRES, - B_PACKAGE_ATTRIBUTE_SUPPLEMENTS, - B_PACKAGE_ATTRIBUTE_CONFLICTS, - B_PACKAGE_ATTRIBUTE_FRESHENS, - B_PACKAGE_ATTRIBUTE_REPLACES, - B_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR, +enum BHPKGAttributeID { + B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY = 0, + B_HPKG_ATTRIBUTE_ID_FILE_TYPE = 1, + B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS = 2, + B_HPKG_ATTRIBUTE_ID_FILE_USER = 3, + B_HPKG_ATTRIBUTE_ID_FILE_GROUP = 4, + B_HPKG_ATTRIBUTE_ID_FILE_ATIME = 5, + B_HPKG_ATTRIBUTE_ID_FILE_MTIME = 6, + B_HPKG_ATTRIBUTE_ID_FILE_CRTIME = 7, + B_HPKG_ATTRIBUTE_ID_FILE_ATIME_NANOS = 8, + B_HPKG_ATTRIBUTE_ID_FILE_MTIME_NANOS = 9, + B_HPKG_ATTRIBUTE_ID_FILE_CRTIM_NANOS = 10, + B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE = 11, + B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE = 12, + B_HPKG_ATTRIBUTE_ID_DATA = 13, + B_HPKG_ATTRIBUTE_ID_DATA_SIZE = 14, + B_HPKG_ATTRIBUTE_ID_DATA_COMPRESSION = 15, + B_HPKG_ATTRIBUTE_ID_DATA_CHUNK_SIZE = 16, + B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH = 17, + B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME = 18, + B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY = 19, + B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION = 20, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR = 21, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER = 22, + B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS = 23, + B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE = 24, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR = 25, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR = 26, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO = 27, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_RELEASE = 28, + B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT = 29, + B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE = 30, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES = 31, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE = 32, + B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES = 33, + B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS = 34, + B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS = 35, + B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS = 36, + B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES = 37, + B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR = 38, + B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM = 39, // - B_PACKAGE_ATTRIBUTE_ENUM_COUNT, + B_HPKG_ATTRIBUTE_ID_ENUM_COUNT, }; @@ -102,7 +122,7 @@ enum { }; -// file types (HPKG_ATTRIBUTE_NAME_FILE_TYPE) +// file types (B_HPKG_ATTRIBUTE_ID_FILE_TYPE) enum { B_HPKG_FILE_TYPE_FILE = 0, B_HPKG_FILE_TYPE_DIRECTORY = 1, diff --git a/headers/os/package/hpkg/PackageContentHandler.h b/headers/os/package/hpkg/PackageContentHandler.h index db629c6e34..1314d92785 100644 --- a/headers/os/package/hpkg/PackageContentHandler.h +++ b/headers/os/package/hpkg/PackageContentHandler.h @@ -8,6 +8,8 @@ #include +#include + namespace BPackageKit { @@ -24,14 +26,18 @@ class BLowLevelPackageContentHandler { public: virtual ~BLowLevelPackageContentHandler(); - virtual status_t HandleAttribute(const char* attributeName, + virtual status_t HandleAttribute(BHPKGAttributeID attributeID, const BPackageAttributeValue& value, void* parentToken, void*& _token) = 0; - virtual status_t HandleAttributeDone(const char* attributeName, + virtual status_t HandleAttributeDone( + BHPKGAttributeID attributeID, const BPackageAttributeValue& value, void* token) = 0; virtual void HandleErrorOccurred() = 0; + +protected: + static const char* AttributeNameForID(uint8 id); }; @@ -47,7 +53,6 @@ public: virtual status_t HandlePackageAttribute( const BPackageInfoAttributeValue& value ) = 0; - virtual status_t HandlePackageAttributesDone() = 0; virtual void HandleErrorOccurred() = 0; }; diff --git a/headers/os/package/hpkg/PackageInfoAttributeValue.h b/headers/os/package/hpkg/PackageInfoAttributeValue.h index 604c07dbd3..e2edc95e36 100644 --- a/headers/os/package/hpkg/PackageInfoAttributeValue.h +++ b/headers/os/package/hpkg/PackageInfoAttributeValue.h @@ -51,42 +51,52 @@ struct BPackageInfoAttributeValue { BPackageResolvableData resolvable; BPackageResolvableExpressionData resolvableExpression; }; - uint8 attributeIndex; + BPackageInfoAttributeID attributeID; public: - inline BPackageInfoAttributeValue(); + BPackageInfoAttributeValue(); - inline void SetTo(BPackageInfoAttributeIndex index, + void SetTo(BPackageInfoAttributeID id, uint8 value); - inline void SetTo(BPackageInfoAttributeIndex index, + void SetTo(BPackageInfoAttributeID id, const char* value); + + void Clear(); }; +inline BPackageInfoAttributeValue::BPackageInfoAttributeValue() - : - attributeIndex(B_PACKAGE_INFO_ENUM_COUNT) { + Clear(); } -void -BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index, uint8 value) +inline void +BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeID id, uint8 value) { - attributeIndex = index; + attributeID = id; unsignedInt = value; } -void -BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index, +inline void +BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeID id, const char* value) { - attributeIndex = index; + attributeID = id; string = value; } +inline void +BPackageInfoAttributeValue::Clear() +{ + memset(this, 0, sizeof(BPackageInfoAttributeValue)); + attributeID = B_PACKAGE_INFO_ENUM_COUNT; +} + + } // namespace BHPKG } // namespace BPackageKit diff --git a/headers/os/package/hpkg/PackageWriter.h b/headers/os/package/hpkg/PackageWriter.h index 51eb7d103d..7cc6095f05 100644 --- a/headers/os/package/hpkg/PackageWriter.h +++ b/headers/os/package/hpkg/PackageWriter.h @@ -29,9 +29,7 @@ public: virtual void OnEntryAdded(const char* path) = 0; - virtual void OnTOCSizeInfo( - uint64 uncompressedAttributeTypesSize, - uint64 uncompressedStringsSize, + virtual void OnTOCSizeInfo(uint64 uncompressedStringsSize, uint64 uncompressedMainSize, uint64 uncompressedTOCSize) = 0; virtual void OnPackageAttributesSizeInfo(uint32 stringCount, diff --git a/headers/os/package/hpkg/RepositoryContentHandler.h b/headers/os/package/hpkg/RepositoryContentHandler.h new file mode 100644 index 0000000000..cb2c5f7b32 --- /dev/null +++ b/headers/os/package/hpkg/RepositoryContentHandler.h @@ -0,0 +1,40 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__REPOSITORY_CONTENT_HANDLER_H_ +#define _PACKAGE__HPKG__REPOSITORY_CONTENT_HANDLER_H_ + + +#include + + +namespace BPackageKit { + + +class BPackageInfo; +class BRepositoryInfo; + + +namespace BHPKG { + + +class BRepositoryContentHandler { +public: + virtual ~BRepositoryContentHandler(); + + virtual status_t HandleRepositoryInfo( + const BRepositoryInfo& info) = 0; + virtual status_t HandlePackage(const BPackageInfo& info) = 0; + virtual status_t HandlePackagesDone() = 0; + + virtual void HandleErrorOccurred() = 0; +}; + + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__REPOSITORY_CONTENT_HANDLER_H_ diff --git a/headers/os/package/hpkg/RepositoryReader.h b/headers/os/package/hpkg/RepositoryReader.h new file mode 100644 index 0000000000..86b654a4e2 --- /dev/null +++ b/headers/os/package/hpkg/RepositoryReader.h @@ -0,0 +1,45 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__REPOSITORY_READER_H_ +#define _PACKAGE__HPKG__REPOSITORY_READER_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +namespace BPrivate { + class RepositoryReaderImpl; +} +using BPrivate::RepositoryReaderImpl; + +class BErrorOutput; +class BRepositoryContentHandler; + + +class BRepositoryReader { +public: + BRepositoryReader(BErrorOutput* errorOutput); + ~BRepositoryReader(); + + status_t Init(const char* fileName); + status_t ParseContent( + BPackageContentHandler* contentHandler); + +private: + RepositoryReaderImpl* fImpl; +}; + + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__REPOSITORY_READER_H_ diff --git a/headers/private/package/hpkg/HPKGDefsPrivate.h b/headers/private/package/hpkg/HPKGDefsPrivate.h new file mode 100644 index 0000000000..dc0dedbbe7 --- /dev/null +++ b/headers/private/package/hpkg/HPKGDefsPrivate.h @@ -0,0 +1,87 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ +#define _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ + + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace BPrivate { + + +// header +struct hpkg_header { + uint32 magic; // "hpkg" + uint16 header_size; + uint16 version; + uint64 total_size; + + // package attributes section + uint32 attributes_compression; + uint32 attributes_length_compressed; + uint32 attributes_length_uncompressed; + uint32 attributes_strings_length; + uint32 attributes_strings_count; + + // TOC section + uint32 toc_compression; + uint64 toc_length_compressed; + uint64 toc_length_uncompressed; + uint64 toc_strings_length; + uint64 toc_strings_count; +}; + + +// header +struct hpkg_repo_header { + uint32 magic; // "hpkr" + uint16 header_size; + uint16 version; + uint32 total_size; + + // repository info section + uint32 info_compression; + uint32 info_length_compressed; + uint32 info_length_uncompressed; + + // package attributes section + uint32 packages_compression; + uint32 packages_length_compressed; + uint32 packages_length_uncompressed; + uint32 packages_strings_length; + uint32 packages_strings_count; +}; + + +// attribute tag arithmetics +// (using 6 bits for id, 3 for type, 1 for hasChildren and 2 for encoding) +#define HPKG_ATTRIBUTE_TAG_COMPOSE(id, type, encoding, hasChildren) \ + (((uint16(encoding) << 10) | (uint16((hasChildren) ? 1 : 0) << 9) \ + | (uint16(type) << 6) | (uint16(id))) + 1) +#define HPKG_ATTRIBUTE_TAG_ENCODING(tag) \ + ((uint16((tag) - 1) >> 10) & 0x3) +#define HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag) \ + (((uint16((tag) - 1) >> 9) & 0x1) != 0) +#define HPKG_ATTRIBUTE_TAG_TYPE(tag) \ + ((uint16((tag) - 1) >> 6) & 0x7) +#define HPKG_ATTRIBUTE_TAG_ID(tag) \ + (uint16((tag) - 1) & 0x3f) + + +} // namespace BPrivate + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ diff --git a/headers/private/package/hpkg/PackageReaderImpl.h b/headers/private/package/hpkg/PackageReaderImpl.h index 7ba2518e3b..86d46c8722 100644 --- a/headers/private/package/hpkg/PackageReaderImpl.h +++ b/headers/private/package/hpkg/PackageReaderImpl.h @@ -46,16 +46,18 @@ public: int PackageFileFD() { return fFD; } private: - struct AttributeType; - struct AttributeTypeReference; struct AttributeHandlerContext; struct AttributeHandler; struct IgnoreAttributeHandler; struct DataAttributeHandler; struct AttributeAttributeHandler; struct EntryAttributeHandler; - struct RootAttributeHandler; struct PackageAttributeHandler; + struct PackageVersionAttributeHandler; + struct PackageResolvableAttributeHandler; + struct PackageResolvableExpressionAttributeHandler; + struct RootAttributeHandler; + struct LowLevelAttributeHandler; struct PackageContentListHandler; struct SectionInfo { @@ -94,8 +96,6 @@ private: const char* _CheckCompression( const SectionInfo& section) const; - status_t _ParseTOCAttributeTypes(); - status_t _ParseStrings(); status_t _ParseContent(AttributeHandlerContext* context, @@ -117,7 +117,7 @@ private: const char* resolvableName, bool hasChildren); - status_t _ReadPackageAttribute(uint8& _id, + status_t _ReadAttribute(uint8& _id, AttributeValue& _value, bool* _hasChildren = NULL, uint64* _tag = NULL); @@ -141,8 +141,6 @@ private: status_t _ReadCompressedBuffer( const SectionInfo& section); - static int8 _GetStandardIndex(const AttributeType* type); - inline AttributeHandler* _CurrentAttributeHandler() const; inline void _PushAttributeHandler( AttributeHandler* handler); @@ -157,15 +155,10 @@ private: uint64 fHeapOffset; uint64 fHeapSize; - uint64 fTOCAttributeTypesLength; - uint64 fTOCAttributeTypesCount; - SectionInfo fTOCSection; SectionInfo fPackageAttributesSection; SectionInfo* fCurrentSection; - AttributeTypeReference* fAttributeTypes; - AttributeHandlerList* fAttributeHandlerStack; uint8* fScratchBuffer; diff --git a/headers/private/package/hpkg/PackageWriterImpl.h b/headers/private/package/hpkg/PackageWriterImpl.h index 5a3eaed0fe..ec28e1d77f 100644 --- a/headers/private/package/hpkg/PackageWriterImpl.h +++ b/headers/private/package/hpkg/PackageWriterImpl.h @@ -42,16 +42,10 @@ public: status_t Finish(); private: - struct AttributeTypeKey; - struct AttributeType; - struct AttributeTypeHashDefinition; struct Attribute; - struct AttributeTypeUsageGreater; struct Entry; struct SubPathAdder; - typedef BOpenHashTable - AttributeTypeTable; typedef DoublyLinkedList EntryList; private: @@ -66,9 +60,8 @@ private: status_t _CheckLicenses(); void _WriteTOC(hpkg_header& header); - int32 _WriteTOCSections(uint64& _attributeTypesSize, - uint64& _stringsSize, uint64& _mainSize); - void _WriteAttributeTypes(); + int32 _WriteTOCSections(uint64& _stringsSize, + uint64& _mainSize); void _WriteAttributeChildren(Attribute* attribute); void _WritePackageAttributes(hpkg_header& header); @@ -76,23 +69,21 @@ private: void _AddEntry(int dirFD, Entry* entry, const char* fileName, char* pathBuffer); - Attribute* _AddAttribute(const char* attributeName, + Attribute* _AddAttribute(BHPKGAttributeID attributeID, const AttributeValue& value); template - inline Attribute* _AddAttribute(const char* attributeName, + inline Attribute* _AddAttribute(BHPKGAttributeID attributeID, Type value); - Attribute* _AddStringAttribute(const char* attributeName, + Attribute* _AddStringAttribute( + BHPKGAttributeID attributeID, const char* value); - Attribute* _AddDataAttribute(const char* attributeName, + Attribute* _AddDataAttribute(BHPKGAttributeID attributeID, uint64 dataSize, uint64 dataOffset); - Attribute* _AddDataAttribute(const char* attributeName, + Attribute* _AddDataAttribute(BHPKGAttributeID attributeID, uint64 dataSize, const uint8* data); - AttributeType* _GetAttributeType(const char* attributeName, - uint8 type); - status_t _AddData(BDataReader& dataReader, off_t size); status_t _WriteUncompressedData(BDataReader& dataReader, @@ -117,7 +108,6 @@ private: Attribute* fTopAttribute; StringCache fStringCache; - AttributeTypeTable* fAttributeTypes; BPackageInfo fPackageInfo; }; diff --git a/headers/private/package/hpkg/RepositoryReaderImpl.h b/headers/private/package/hpkg/RepositoryReaderImpl.h new file mode 100644 index 0000000000..ce928528c5 --- /dev/null +++ b/headers/private/package/hpkg/RepositoryReaderImpl.h @@ -0,0 +1,190 @@ +/* + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__PRIVATE__REPOSITORY_READER_IMPL_H_ +#define _PACKAGE__HPKG__PRIVATE__REPOSITORY_READER_IMPL_H_ + + +#include + +#include + +#include +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +class BPackageEntry; +class BPackageEntryAttribute; +class BErrorOutput; + + +namespace BPrivate { + + +class PackageReaderImpl { +public: + PackageReaderImpl( + BErrorOutput* errorOutput); + ~PackageReaderImpl(); + + status_t Init(const char* fileName); + status_t Init(int fd, bool keepFD); + status_t ParseContent( + BPackageContentHandler* contentHandler); + status_t ParseContent(BLowLevelPackageContentHandler* + contentHandler); + + int PackageFileFD() { return fFD; } + +private: + struct AttributeType; + struct AttributeTypeReference; + struct AttributeHandlerContext; + struct AttributeHandler; + struct IgnoreAttributeHandler; + struct DataAttributeHandler; + struct AttributeAttributeHandler; + struct EntryAttributeHandler; + struct RootAttributeHandler; + struct PackageAttributeHandler; + struct PackageContentListHandler; + + struct SectionInfo { + uint32 compression; + uint32 compressedLength; + uint32 uncompressedLength; + uint8* data; + uint64 offset; + uint64 currentOffset; + uint64 stringsLength; + uint64 stringsCount; + char** strings; + const char* name; + + SectionInfo(const char* _name) + : + data(NULL), + strings(NULL), + name(_name) + { + } + + ~SectionInfo() + { + delete[] strings; + delete[] data; + } + }; + + typedef BPackageAttributeValue AttributeValue; + typedef SinglyLinkedList AttributeHandlerList; + +private: + status_t _Init(const char* fileName); + + const char* _CheckCompression( + const SectionInfo& section) const; + + status_t _ParseTOCAttributeTypes(); + + status_t _ParseStrings(); + + status_t _ParseContent(AttributeHandlerContext* context, + AttributeHandler* rootAttributeHandler); + status_t _ParseAttributeTree( + AttributeHandlerContext* context); + + status_t _ParsePackageAttributes( + AttributeHandlerContext* context); + status_t _ParsePackageVersion( + BPackageVersionData& _version, + const char* major = NULL); + status_t _ParsePackageProvides( + BPackageResolvableData& _resolvable, + BPackageResolvableType providesType); + status_t _ParsePackageResolvableExpression( + BPackageResolvableExpressionData& + _resolvableExpression, + const char* resolvableName, + bool hasChildren); + + status_t _ReadPackageAttribute(uint8& _id, + AttributeValue& _value, + bool* _hasChildren = NULL, + uint64* _tag = NULL); + + status_t _ReadAttributeValue(uint8 type, uint8 encoding, + AttributeValue& _value); + + status_t _ReadUnsignedLEB128(uint64& _value); + status_t _ReadString(const char*& _string, + size_t* _stringLength = NULL); + + template + inline status_t _Read(Type& _value); + + status_t _GetTOCBuffer(size_t size, + const void*& _buffer); + status_t _ReadSectionBuffer(void* buffer, size_t size); + + status_t _ReadBuffer(off_t offset, void* buffer, + size_t size); + status_t _ReadCompressedBuffer( + const SectionInfo& section); + + static int8 _GetStandardIndex(const AttributeType* type); + + inline AttributeHandler* _CurrentAttributeHandler() const; + inline void _PushAttributeHandler( + AttributeHandler* handler); + inline AttributeHandler* _PopAttributeHandler(); + +private: + BErrorOutput* fErrorOutput; + int fFD; + bool fOwnsFD; + + uint64 fTotalSize; + uint64 fHeapOffset; + uint64 fHeapSize; + + uint64 fTOCAttributeTypesLength; + uint64 fTOCAttributeTypesCount; + + SectionInfo fTOCSection; + SectionInfo fPackageAttributesSection; + SectionInfo* fCurrentSection; + + AttributeTypeReference* fAttributeTypes; + + AttributeHandlerList* fAttributeHandlerStack; + + uint8* fScratchBuffer; + size_t fScratchBufferSize; +}; + + +template +status_t +PackageReaderImpl::_Read(Type& _value) +{ + return _ReadSectionBuffer(&_value, sizeof(Type)); +} + + +} // namespace BPrivate + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__PRIVATE__REPOSITORY_READER_IMPL_H_ diff --git a/headers/private/package/hpkg/WriterImplBase.h b/headers/private/package/hpkg/WriterImplBase.h index 6ee1d3eb2f..a6b7c47519 100644 --- a/headers/private/package/hpkg/WriterImplBase.h +++ b/headers/private/package/hpkg/WriterImplBase.h @@ -8,7 +8,7 @@ #include -#include +#include #include #include @@ -79,10 +79,10 @@ protected: struct PackageAttribute : public DoublyLinkedListLinkImpl, public AttributeValue { - HPKGPackageAttributeID id; + BHPKGAttributeID id; DoublyLinkedList children; - PackageAttribute(HPKGPackageAttributeID id_, uint8 type, + PackageAttribute(BHPKGAttributeID id_, uint8 type, uint8 encoding); ~PackageAttribute(); diff --git a/headers/private/package/hpkg/haiku_package.h b/headers/private/package/hpkg/haiku_package.h deleted file mode 100644 index 364a4c8ef8..0000000000 --- a/headers/private/package/hpkg/haiku_package.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ -#ifndef _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ -#define _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ - - -#include - -#include - - -namespace BPackageKit { - -namespace BHPKG { - -namespace BPrivate { - - -// header -struct hpkg_header { - uint32 magic; // "hpkg" - uint16 header_size; - uint16 version; - uint64 total_size; - - // package attributes section - uint32 attributes_compression; - uint32 attributes_length_compressed; - uint32 attributes_length_uncompressed; - uint32 attributes_strings_length; - uint32 attributes_strings_count; - - // TOC section - uint32 toc_compression; - uint64 toc_length_compressed; - uint64 toc_length_uncompressed; - - uint64 toc_attribute_types_length; - uint64 toc_attribute_types_count; - uint64 toc_strings_length; - uint64 toc_strings_count; -}; - - -// header -struct hpkg_repo_header { - uint32 magic; // "hpkr" - uint16 header_size; - uint16 version; - uint32 total_size; - - // repository info section - uint32 info_compression; - uint32 info_length_compressed; - uint32 info_length_uncompressed; - - // package attributes section - uint32 packages_compression; - uint32 packages_length_compressed; - uint32 packages_length_uncompressed; - uint32 packages_strings_length; - uint32 packages_strings_count; -}; - - -// attribute tag arithmetics -#define HPKG_ATTRIBUTE_TAG_COMPOSE(index, encoding, hasChildren) \ - (((uint64(index) << 3) | uint64(encoding) << 1 \ - | ((hasChildren) ? 1 : 0)) + 1) -#define HPKG_ATTRIBUTE_TAG_INDEX(tag) (uint64((tag) - 1) >> 3) -#define HPKG_ATTRIBUTE_TAG_ENCODING(tag) ((uint64((tag) - 1) >> 1) & 0x3) -#define HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag) ((uint64((tag) - 1) & 0x1) != 0) - -// package attribute tag arithmetics -#define HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(id, type, encoding, hasChildren) \ - (((uint16(encoding) << 9) | (((hasChildren) ? 1 : 0) << 8) \ - | (uint16(type) << 5) | (uint16(id))) + 1) -#define HPKG_PACKAGE_ATTRIBUTE_TAG_ENCODING(tag) \ - ((uint16((tag) - 1) >> 9) & 0x3) -#define HPKG_PACKAGE_ATTRIBUTE_TAG_HAS_CHILDREN(tag) \ - (((uint16((tag) - 1) >> 8) & 0x1) != 0) -#define HPKG_PACKAGE_ATTRIBUTE_TAG_TYPE(tag) \ - ((uint16((tag) - 1) >> 5) & 0x7) -#define HPKG_PACKAGE_ATTRIBUTE_TAG_ID(tag) \ - (uint16((tag) - 1) & 0x1f) - - -// standard attribute names -#define HPKG_ATTRIBUTE_NAME_DIRECTORY_ENTRY "dir:entry" - // path/entry name (string) -#define HPKG_ATTRIBUTE_NAME_FILE_TYPE "file:type" - // file type (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_PERMISSIONS "file:permissions" - // file permissions (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_USER "file:user" - // file user (string) -#define HPKG_ATTRIBUTE_NAME_FILE_GROUP "file:group" - // file group (string) -#define HPKG_ATTRIBUTE_NAME_FILE_ATIME "file:atime" - // file access time in seconds (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_MTIME "file:mtime" - // file modification time in seconds (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_CRTIME "file:crtime" - // file creation time in seconds (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_ATIME_NANOS "file:atime:nanos" - // file access time nanoseconds fraction (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_MTIME_NANOS "file:mtime:nanos" - // file modification time nanoseconds fraction (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_CRTIM_NANOS "file:crtime:nanos" - // file creation time nanoseconds fraction (uint) -#define HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE "file:attribute" - // file attribute (string) -#define HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE_TYPE "file:attribute:type" - // file attribute type (uint) -#define HPKG_ATTRIBUTE_NAME_DATA "data" - // (file/attribute) data (raw) -#define HPKG_ATTRIBUTE_NAME_DATA_COMPRESSION "data:compression" - // (file/attribute) data compression (uint, default: none) -#define HPKG_ATTRIBUTE_NAME_DATA_SIZE "data:size" - // (file/attribute) uncompressed data size (uint) -#define HPKG_ATTRIBUTE_NAME_DATA_CHUNK_SIZE "data:chunk_size" - // the size of compressed (file/attribute) data chunks (uint) -#define HPKG_ATTRIBUTE_NAME_SYMLINK_PATH "symlink:path" - // symlink path (string) - - -// package attribute IDs -enum HPKGPackageAttributeID { - HPKG_PACKAGE_ATTRIBUTE_NAME = 0, - HPKG_PACKAGE_ATTRIBUTE_SUMMARY, - HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION, - HPKG_PACKAGE_ATTRIBUTE_VENDOR, - HPKG_PACKAGE_ATTRIBUTE_PACKAGER, - HPKG_PACKAGE_ATTRIBUTE_FLAGS, - HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE, - HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR, - HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR, - HPKG_PACKAGE_ATTRIBUTE_VERSION_MICRO, - HPKG_PACKAGE_ATTRIBUTE_VERSION_RELEASE, - HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT, - HPKG_PACKAGE_ATTRIBUTE_LICENSE, - HPKG_PACKAGE_ATTRIBUTE_PROVIDES, - HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, - HPKG_PACKAGE_ATTRIBUTE_REQUIRES, - HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS, - HPKG_PACKAGE_ATTRIBUTE_CONFLICTS, - HPKG_PACKAGE_ATTRIBUTE_FRESHENS, - HPKG_PACKAGE_ATTRIBUTE_REPLACES, - HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR, - HPKG_PACKAGE_ATTRIBUTE_CHECKSUM, - // - HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT, -}; - - -} // namespace BPrivate - -} // namespace BHPKG - -} // namespace BPackageKit - - -#endif // _PACKAGE__HPKG__PRIVATE__HAIKU_PACKAGE_H_ diff --git a/src/add-ons/kernel/file_systems/packagefs/GlobalFactory.cpp b/src/add-ons/kernel/file_systems/packagefs/GlobalFactory.cpp index c501079d70..751874cad7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/GlobalFactory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/GlobalFactory.cpp @@ -8,7 +8,7 @@ #include -#include +#include static const uint32 kMaxCachedBuffers = 32; diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 44ed72e46b..c6b1fe01eb 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -264,12 +264,6 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler { return B_OK; } - virtual status_t HandlePackageAttributesDone() - { - // TODO! - return B_OK; - } - virtual void HandleErrorOccurred() { fErrorOccurred = true; diff --git a/src/bin/package/command_create.cpp b/src/bin/package/command_create.cpp index 8932902a89..5e901e99b9 100644 --- a/src/bin/package/command_create.cpp +++ b/src/bin/package/command_create.cpp @@ -46,16 +46,13 @@ public: printf("\t%s\n", path); } - virtual void OnTOCSizeInfo(uint64 uncompressedAttributeTypesSize, - uint64 uncompressedStringsSize, uint64 uncompressedMainSize, - uint64 uncompressedTOCSize) + virtual void OnTOCSizeInfo(uint64 uncompressedStringsSize, + uint64 uncompressedMainSize, uint64 uncompressedTOCSize) { if (fQuiet || !fVerbose) return; printf("----- TOC Info -----------------------------------\n"); - printf("attribute types size: %10llu (uncompressed)\n", - uncompressedAttributeTypesSize); printf("cached strings size: %10llu (uncompressed)\n", uncompressedStringsSize); printf("TOC main size: %10llu (uncompressed)\n", diff --git a/src/bin/package/command_dump.cpp b/src/bin/package/command_dump.cpp index 02f4abe7cc..8b625d3b6a 100644 --- a/src/bin/package/command_dump.cpp +++ b/src/bin/package/command_dump.cpp @@ -34,13 +34,13 @@ struct PackageContentDumpHandler : BLowLevelPackageContentHandler { { } - virtual status_t HandleAttribute(const char* attributeName, + virtual status_t HandleAttribute(BHPKGAttributeID attributeID, const BPackageAttributeValue& value, void* parentToken, void*& _token) { if (fErrorOccurred) return B_OK; - printf("%*s>%s: ", fLevel * 2, "", attributeName); + printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID)); _PrintValue(value); printf("\n"); @@ -49,7 +49,7 @@ struct PackageContentDumpHandler : BLowLevelPackageContentHandler { return B_OK; } - virtual status_t HandleAttributeDone(const char* attributeName, + virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID, const BPackageAttributeValue& value, void* token) { if (fErrorOccurred) @@ -58,7 +58,7 @@ struct PackageContentDumpHandler : BLowLevelPackageContentHandler { fLevel--; if (fHasChildren) - printf("%*s<%s\n", fLevel * 2, "", attributeName); + printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID)); fHasChildren = true; return B_OK; @@ -144,14 +144,12 @@ command_dump(int argc, const char* const* argv) StandardErrorOutput errorOutput; BPackageReader packageReader(&errorOutput); status_t error = packageReader.Init(packageFileName); -printf("Init(): %s\n", strerror(error)); if (error != B_OK) return 1; // list PackageContentDumpHandler handler; error = packageReader.ParseContent(&handler); -printf("ParseContent(): %s\n", strerror(error)); if (error != B_OK) return 1; diff --git a/src/bin/package/command_extract.cpp b/src/bin/package/command_extract.cpp index df6f38ab9b..d3b3a86a45 100644 --- a/src/bin/package/command_extract.cpp +++ b/src/bin/package/command_extract.cpp @@ -229,11 +229,6 @@ struct PackageContentExtractHandler : BPackageContentHandler { return B_OK; } - virtual status_t HandlePackageAttributesDone() - { - return B_OK; - } - virtual void HandleErrorOccurred() { fErrorOccurred = true; diff --git a/src/bin/package/command_list.cpp b/src/bin/package/command_list.cpp index 31b5023dc9..ba84332c08 100644 --- a/src/bin/package/command_list.cpp +++ b/src/bin/package/command_list.cpp @@ -111,7 +111,7 @@ struct PackageContentListHandler : BPackageContentHandler { virtual status_t HandlePackageAttribute( const BPackageInfoAttributeValue& value) { - switch (value.attributeIndex) { + switch (value.attributeID) { case B_PACKAGE_INFO_NAME: printf("package-attributes:\n"); printf("\tname: %s\n", value.string); @@ -218,19 +218,13 @@ struct PackageContentListHandler : BPackageContentHandler { default: printf( "*** Invalid package attribute section: unexpected " - "package attribute index %d encountered\n", - value.attributeIndex); + "package attribute id %d encountered\n", value.attributeID); return B_BAD_DATA; } return B_OK; } - virtual status_t HandlePackageAttributesDone() - { - return B_OK; - } - virtual void HandleErrorOccurred() { } @@ -308,14 +302,12 @@ command_list(int argc, const char* const* argv) StandardErrorOutput errorOutput; BPackageReader packageReader(&errorOutput); status_t error = packageReader.Init(packageFileName); -printf("Init(): %s\n", strerror(error)); if (error != B_OK) return 1; // list PackageContentListHandler handler(listAttributes); error = packageReader.ParseContent(&handler); -printf("ParseContent(): %s\n", strerror(error)); if (error != B_OK) return 1; diff --git a/src/bin/package_repo/command_list.cpp b/src/bin/package_repo/command_list.cpp index 31b5023dc9..18b2a8ea94 100644 --- a/src/bin/package_repo/command_list.cpp +++ b/src/bin/package_repo/command_list.cpp @@ -26,7 +26,7 @@ using namespace BPackageKit::BHPKG; using namespace BPackageKit; - +/* struct PackageContentListHandler : BPackageContentHandler { PackageContentListHandler(bool listAttributes) : @@ -265,7 +265,7 @@ private: int fLevel; bool fListAttribute; }; - +*/ int command_list(int argc, const char* const* argv) @@ -305,19 +305,17 @@ command_list(int argc, const char* const* argv) const char* packageFileName = argv[optind++]; // open package - StandardErrorOutput errorOutput; - BPackageReader packageReader(&errorOutput); - status_t error = packageReader.Init(packageFileName); -printf("Init(): %s\n", strerror(error)); - if (error != B_OK) - return 1; +// StandardErrorOutput errorOutput; +// BPackageReader packageReader(&errorOutput); +// status_t error = packageReader.Init(packageFileName); +// if (error != B_OK) +// return 1; // list - PackageContentListHandler handler(listAttributes); - error = packageReader.ParseContent(&handler); -printf("ParseContent(): %s\n", strerror(error)); - if (error != B_OK) - return 1; +// PackageContentListHandler handler(listAttributes); +// error = packageReader.ParseContent(&handler); +// if (error != B_OK) +// return 1; return 0; } diff --git a/src/kits/package/PackageVersion.cpp b/src/kits/package/PackageVersion.cpp index 611f715f7e..73e3c03ce3 100644 --- a/src/kits/package/PackageVersion.cpp +++ b/src/kits/package/PackageVersion.cpp @@ -18,6 +18,8 @@ namespace BPackageKit { BPackageVersion::BPackageVersion() + : + fRelease(0) { } diff --git a/src/kits/package/hpkg/PackageContentHandler.cpp b/src/kits/package/hpkg/PackageContentHandler.cpp index 9ce9ea8dce..c981f59d4c 100644 --- a/src/kits/package/hpkg/PackageContentHandler.cpp +++ b/src/kits/package/hpkg/PackageContentHandler.cpp @@ -15,11 +15,66 @@ namespace BHPKG { // #pragma mark - BLowLevelPackageContentHandler +static const char* kAttributeNames[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT + 1] = { + "dir:entry", + "file:type", + "file:permissions", + "file:user", + "file:group", + "file:atime", + "file:mtime", + "file:crtime", + "file:atime:nanos", + "file:mtime:nanos", + "file:crtime:nanos", + "file:attribute", + "file:attribute:type", + "data", + "data:compression", + "data:size", + "data:chunk_size", + "symlink:path", + "package:name", + "package:summary", + "package:description", + "package:vendor", + "package:packager", + "package:flags", + "package:architecture", + "package:version.major", + "package:version.minor", + "package:version.micro", + "package:version.release", + "package:copyright", + "package:license", + "package:provides", + "package:provides.type", + "package:requires", + "package:supplements", + "package:conflicts", + "package:freshens", + "package:replaces", + "package:resolvable.operator", + "package:checksum", + NULL +}; + + BLowLevelPackageContentHandler::~BLowLevelPackageContentHandler() { } +/*static*/ const char* +BLowLevelPackageContentHandler::AttributeNameForID(uint8 id) +{ + if (id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) + return NULL; + + return kAttributeNames[id]; +} + + // #pragma mark - BPackageContentHandler diff --git a/src/kits/package/hpkg/PackageData.cpp b/src/kits/package/hpkg/PackageData.cpp index f2aed96052..31b288f3b0 100644 --- a/src/kits/package/hpkg/PackageData.cpp +++ b/src/kits/package/hpkg/PackageData.cpp @@ -8,7 +8,7 @@ #include -#include +#include namespace BPackageKit { diff --git a/src/kits/package/hpkg/PackageDataReader.cpp b/src/kits/package/hpkg/PackageDataReader.cpp index ac4495cf08..55fd31a828 100644 --- a/src/kits/package/hpkg/PackageDataReader.cpp +++ b/src/kits/package/hpkg/PackageDataReader.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/kits/package/hpkg/PackageReaderImpl.cpp b/src/kits/package/hpkg/PackageReaderImpl.cpp index 7b65655faf..c786900e41 100644 --- a/src/kits/package/hpkg/PackageReaderImpl.cpp +++ b/src/kits/package/hpkg/PackageReaderImpl.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include #include @@ -50,80 +50,6 @@ static const size_t kMaxPackageAttributesSize = 1 * 1024 * 1024; static const size_t kScratchBufferSize = 64 * 1024; -enum { - ATTRIBUTE_INDEX_DIRECTORY_ENTRY = 0, - ATTRIBUTE_INDEX_FILE_TYPE, - ATTRIBUTE_INDEX_FILE_PERMISSIONS, - ATTRIBUTE_INDEX_FILE_USER, - ATTRIBUTE_INDEX_FILE_GROUP, - ATTRIBUTE_INDEX_FILE_ATIME, - ATTRIBUTE_INDEX_FILE_MTIME, - ATTRIBUTE_INDEX_FILE_CRTIME, - ATTRIBUTE_INDEX_FILE_ATIME_NANOS, - ATTRIBUTE_INDEX_FILE_MTIME_NANOS, - ATTRIBUTE_INDEX_FILE_CRTIM_NANOS, - ATTRIBUTE_INDEX_FILE_ATTRIBUTE, - ATTRIBUTE_INDEX_FILE_ATTRIBUTE_TYPE, - ATTRIBUTE_INDEX_DATA, - ATTRIBUTE_INDEX_DATA_SIZE, - ATTRIBUTE_INDEX_DATA_COMPRESSION, - ATTRIBUTE_INDEX_DATA_CHUNK_SIZE, - ATTRIBUTE_INDEX_SYMLINK_PATH -}; - - -struct standard_attribute_index_entry { - const char* name; - uint8 type; - int8 index; -}; - -#undef MAKE_ATTRIBUTE_INDEX_ENTRY -#define MAKE_ATTRIBUTE_INDEX_ENTRY(name, type) \ - { HPKG_ATTRIBUTE_NAME_##name, B_HPKG_ATTRIBUTE_TYPE_##type, \ - ATTRIBUTE_INDEX_##name } - -static const standard_attribute_index_entry kStandardAttributeIndices[] = { - MAKE_ATTRIBUTE_INDEX_ENTRY(DIRECTORY_ENTRY, STRING), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_TYPE, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_PERMISSIONS, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_USER, STRING), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_GROUP, STRING), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATIME, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_MTIME, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_CRTIME, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATIME_NANOS, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_MTIME_NANOS, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_CRTIM_NANOS, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATTRIBUTE, STRING), - MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATTRIBUTE_TYPE, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(DATA, RAW), - MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_SIZE, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_COMPRESSION, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_CHUNK_SIZE, UINT), - MAKE_ATTRIBUTE_INDEX_ENTRY(SYMLINK_PATH, STRING), - {} -}; - - -// #pragma mark - AttributeType - - -struct PackageReaderImpl::AttributeType { - uint8 type; - char name[0]; -}; - - -// #pragma mark - AttributeType - - -struct PackageReaderImpl::AttributeTypeReference { - AttributeType* type; - int32 standardIndex; -}; - - // #pragma mark - AttributeHandler @@ -133,10 +59,10 @@ struct PackageReaderImpl::AttributeHandlerContext { BPackageContentHandler* packageContentHandler; BLowLevelPackageContentHandler* lowLevelPackageContentHandler; }; - bool hasLowLevelHandler; + bool hasLowLevelHandler; - uint64 heapOffset; - uint64 heapSize; + uint64 heapOffset; + uint64 heapSize; AttributeHandlerContext(BErrorOutput* errorOutput, @@ -179,11 +105,9 @@ struct PackageReaderImpl::AttributeHandler fLevel = level; } - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) { -TRACE("%*signored attribute \"%s\" (%u)\n", fLevel * 2, "", type->name, type->type); return B_OK; } @@ -237,16 +161,15 @@ struct PackageReaderImpl::DataAttributeHandler : AttributeHandler { return B_OK; } - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) { - switch (typeIndex) { - case ATTRIBUTE_INDEX_DATA_SIZE: + switch (id) { + case B_HPKG_ATTRIBUTE_ID_DATA_SIZE: fData->SetUncompressedSize(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_DATA_COMPRESSION: + case B_HPKG_ATTRIBUTE_ID_DATA_COMPRESSION: { switch (value.unsignedInt) { case B_HPKG_COMPRESSION_NONE: @@ -263,13 +186,12 @@ struct PackageReaderImpl::DataAttributeHandler : AttributeHandler { return B_OK; } - case ATTRIBUTE_INDEX_DATA_CHUNK_SIZE: + case B_HPKG_ATTRIBUTE_ID_DATA_CHUNK_SIZE: fData->SetChunkSize(value.unsignedInt); return B_OK; } - return AttributeHandler::HandleChildAttribute(context, type, typeIndex, - value, _handler); + return AttributeHandler::HandleAttribute(context, id, value, _handler); } private: @@ -285,28 +207,24 @@ struct PackageReaderImpl::AttributeAttributeHandler : AttributeHandler { { } - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) { - switch (typeIndex) { - case ATTRIBUTE_INDEX_DATA: - { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_DATA: if (_handler != NULL) { return DataAttributeHandler::Create(context, &fAttribute.Data(), value, *_handler); } - return DataAttributeHandler::InitData(context, &fAttribute.Data(), - value); - } + return DataAttributeHandler::InitData(context, + &fAttribute.Data(), value); - case ATTRIBUTE_INDEX_FILE_ATTRIBUTE_TYPE: + case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE: fAttribute.SetType(value.unsignedInt); return B_OK; } - return AttributeHandler::HandleChildAttribute(context, type, typeIndex, - value, _handler); + return AttributeHandler::HandleAttribute(context, id, value, _handler); } virtual status_t Delete(AttributeHandlerContext* context) @@ -356,12 +274,11 @@ struct PackageReaderImpl::EntryAttributeHandler : AttributeHandler { return B_OK; } - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) { - switch (typeIndex) { - case ATTRIBUTE_INDEX_DIRECTORY_ENTRY: + switch (id) { + case B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY: { status_t error = _Notify(context); if (error != B_OK) @@ -375,43 +292,43 @@ struct PackageReaderImpl::EntryAttributeHandler : AttributeHandler { return B_OK; } - case ATTRIBUTE_INDEX_FILE_TYPE: + case B_HPKG_ATTRIBUTE_ID_FILE_TYPE: return _SetFileType(context, value.unsignedInt); - case ATTRIBUTE_INDEX_FILE_PERMISSIONS: + case B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS: fEntry.SetPermissions(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_USER: - case ATTRIBUTE_INDEX_FILE_GROUP: + case B_HPKG_ATTRIBUTE_ID_FILE_USER: + case B_HPKG_ATTRIBUTE_ID_FILE_GROUP: // TODO:... break; - case ATTRIBUTE_INDEX_FILE_ATIME: + case B_HPKG_ATTRIBUTE_ID_FILE_ATIME: fEntry.SetAccessTime(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_MTIME: + case B_HPKG_ATTRIBUTE_ID_FILE_MTIME: fEntry.SetModifiedTime(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_CRTIME: + case B_HPKG_ATTRIBUTE_ID_FILE_CRTIME: fEntry.SetCreationTime(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_ATIME_NANOS: + case B_HPKG_ATTRIBUTE_ID_FILE_ATIME_NANOS: fEntry.SetAccessTimeNanos(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_MTIME_NANOS: + case B_HPKG_ATTRIBUTE_ID_FILE_MTIME_NANOS: fEntry.SetModifiedTimeNanos(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_CRTIM_NANOS: + case B_HPKG_ATTRIBUTE_ID_FILE_CRTIM_NANOS: fEntry.SetCreationTimeNanos(value.unsignedInt); return B_OK; - case ATTRIBUTE_INDEX_FILE_ATTRIBUTE: + case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE: { status_t error = _Notify(context); if (error != B_OK) @@ -430,25 +347,20 @@ struct PackageReaderImpl::EntryAttributeHandler : AttributeHandler { } } - case ATTRIBUTE_INDEX_DATA: - { + case B_HPKG_ATTRIBUTE_ID_DATA: if (_handler != NULL) { return DataAttributeHandler::Create(context, &fEntry.Data(), value, *_handler); } return DataAttributeHandler::InitData(context, &fEntry.Data(), value); - } - case ATTRIBUTE_INDEX_SYMLINK_PATH: - { + case B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH: fEntry.SetSymlinkPath(value.string); return B_OK; - } } - return AttributeHandler::HandleChildAttribute(context, type, typeIndex, - value, _handler); + return AttributeHandler::HandleAttribute(context, id, value, _handler); } virtual status_t Delete(AttributeHandlerContext* context) @@ -483,14 +395,17 @@ private: fEntry.SetType(S_IFREG); fEntry.SetPermissions(B_HPKG_DEFAULT_FILE_PERMISSIONS); break; + case B_HPKG_FILE_TYPE_DIRECTORY: fEntry.SetType(S_IFDIR); fEntry.SetPermissions(B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS); break; + case B_HPKG_FILE_TYPE_SYMLINK: fEntry.SetType(S_IFLNK); fEntry.SetPermissions(B_HPKG_DEFAULT_SYMLINK_PERMISSIONS); break; + default: context->errorOutput->PrintError("Error: Invalid file type for " "package entry (%llu)\n", fileType); @@ -500,18 +415,336 @@ private: } private: - BPackageEntry fEntry; - bool fNotified; + BPackageEntry fEntry; + bool fNotified; }; -struct PackageReaderImpl::RootAttributeHandler : AttributeHandler { - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) +struct PackageReaderImpl::PackageVersionAttributeHandler : AttributeHandler { + PackageVersionAttributeHandler(BPackageInfoAttributeValue& packageInfoValue, + BPackageVersionData& versionData, bool notify) + : + fPackageInfoValue(packageInfoValue), + fPackageVersionData(versionData), + fNotify(notify) { - if (typeIndex == ATTRIBUTE_INDEX_DIRECTORY_ENTRY) { -//TRACE("%*sentry \"%s\"\n", fLevel * 2, "", value.string); + } + + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR: + fPackageVersionData.minor = value.string; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO: + fPackageVersionData.micro = value.string; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_RELEASE: + fPackageVersionData.release = value.unsignedInt; + break; + + default: + context->errorOutput->PrintError("Error: Invalid package " + "attribute section: unexpected package attribute id %d " + "encountered when parsing package version\n", id); + return B_BAD_DATA; + } + + return B_OK; + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + status_t error = B_OK; + if (fNotify) { + fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; + error = context->packageContentHandler->HandlePackageAttribute( + fPackageInfoValue); + fPackageInfoValue.Clear(); + } + + delete this; + return error; + } + +private: + BPackageInfoAttributeValue& fPackageInfoValue; + BPackageVersionData& fPackageVersionData; + bool fNotify; +}; + + +struct PackageReaderImpl::PackageResolvableAttributeHandler : AttributeHandler { + PackageResolvableAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue) + : + fPackageInfoValue(packageInfoValue) + { + } + + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE: + fPackageInfoValue.resolvable.type + = (BPackageResolvableType)value.unsignedInt; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: + fPackageInfoValue.resolvable.haveVersion = true; + fPackageInfoValue.resolvable.version.major = value.string; + if (_handler != NULL) { + *_handler + = new(std::nothrow) PackageVersionAttributeHandler( + fPackageInfoValue, + fPackageInfoValue.resolvable.version, false); + if (*_handler == NULL) + return B_NO_MEMORY; + } + break; + + default: + context->errorOutput->PrintError("Error: Invalid package " + "attribute section: unexpected package attribute id %d " + "encountered when parsing package resolvable\n", id); + return B_BAD_DATA; + } + + return B_OK; + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + status_t error = context->packageContentHandler->HandlePackageAttribute( + fPackageInfoValue); + fPackageInfoValue.Clear(); + + delete this; + return error; + } + +private: + BPackageInfoAttributeValue& fPackageInfoValue; +}; + + +struct PackageReaderImpl::PackageResolvableExpressionAttributeHandler + : AttributeHandler { + PackageResolvableExpressionAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue) + : + fPackageInfoValue(packageInfoValue) + { + } + + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR: + if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { + context->errorOutput->PrintError( + "Error: Invalid package attribute section: invalid " + "package resolvable operator %lld encountered\n", + value.unsignedInt); + return B_BAD_DATA; + } + fPackageInfoValue.resolvableExpression.op + = (BPackageResolvableOperator)value.unsignedInt; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: + fPackageInfoValue.resolvableExpression.haveOpAndVersion = true; + fPackageInfoValue.resolvableExpression.version.major + = value.string; + if (_handler != NULL) { + *_handler + = new(std::nothrow) PackageVersionAttributeHandler( + fPackageInfoValue, + fPackageInfoValue.resolvableExpression.version, + false); + if (*_handler == NULL) + return B_NO_MEMORY; + } + return B_OK; + + default: + context->errorOutput->PrintError("Error: Invalid package " + "attribute section: unexpected package attribute id %d " + "encountered when parsing package resolvable-expression\n", + id); + return B_BAD_DATA; + } + + return B_OK; + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + status_t error = context->packageContentHandler->HandlePackageAttribute( + fPackageInfoValue); + fPackageInfoValue.Clear(); + + delete this; + return error; + } + +private: + BPackageInfoAttributeValue& fPackageInfoValue; +}; + + +struct PackageReaderImpl::PackageAttributeHandler : AttributeHandler { + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, + value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS, + (uint32)value.unsignedInt); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: + if (value.unsignedInt + >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { + context->errorOutput->PrintError( + "Error: Invalid package attribute section: " + "Invalid package architecture %lld encountered\n", + value.unsignedInt); + return B_BAD_DATA; + } + fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, + (uint8)value.unsignedInt); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: + fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; + fPackageInfoValue.version.major = value.string; + if (_handler != NULL) { + *_handler + = new(std::nothrow) PackageVersionAttributeHandler( + fPackageInfoValue, fPackageInfoValue.version, true); + if (*_handler == NULL) + return B_NO_MEMORY; + } + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, + value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES, + value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES: + fPackageInfoValue.resolvable.name = value.string; + fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; + if (_handler != NULL) { + *_handler + = new(std::nothrow) PackageResolvableAttributeHandler( + fPackageInfoValue); + if (*_handler == NULL) + return B_NO_MEMORY; + } + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: + case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: + case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: + case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: + fPackageInfoValue.resolvableExpression.name = value.string; + switch (id) { + case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: + fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: + fPackageInfoValue.attributeID + = B_PACKAGE_INFO_SUPPLEMENTS; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: + fPackageInfoValue.attributeID + = B_PACKAGE_INFO_CONFLICTS; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: + fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; + break; + } + if (_handler != NULL) { + *_handler = new(std::nothrow) + PackageResolvableExpressionAttributeHandler( + fPackageInfoValue); + if (*_handler == NULL) + return B_NO_MEMORY; + } + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); + break; + + default: + context->errorOutput->PrintError( + "Error: Invalid package attribute section: unexpected " + "package attribute id %d encountered\n", id); + return B_BAD_DATA; + } + + // notify unless the current attribute has children, in which case + // the child-handler will notify when it's done + if (_handler == NULL) { + status_t error = context->packageContentHandler + ->HandlePackageAttribute(fPackageInfoValue); + fPackageInfoValue.Clear(); + if (error != B_OK) + return error; + } + + return B_OK; + } + +private: + BPackageInfoAttributeValue fPackageInfoValue; +}; + + +struct PackageReaderImpl::RootAttributeHandler : PackageAttributeHandler { + typedef PackageAttributeHandler inherited; + + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + if (id == B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY) { if (_handler != NULL) { return EntryAttributeHandler::Create(context, NULL, value.string, *_handler); @@ -519,47 +752,45 @@ struct PackageReaderImpl::RootAttributeHandler : AttributeHandler { return B_OK; } - return AttributeHandler::HandleChildAttribute(context, type, typeIndex, - value, _handler); + return inherited::HandleAttribute(context, id, value, _handler); } }; -struct PackageReaderImpl::PackageAttributeHandler : AttributeHandler { - PackageAttributeHandler() +struct PackageReaderImpl::LowLevelAttributeHandler : AttributeHandler { + LowLevelAttributeHandler() : fToken(NULL), - fAttributeName(NULL) + fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { } - PackageAttributeHandler(const char* attributeName, - const BPackageAttributeValue& value, void* token) + LowLevelAttributeHandler(uint8 id, const BPackageAttributeValue& value, + void* token) : fToken(token), - fAttributeName(attributeName), + fID(id), fValue(value) { } - virtual status_t HandleChildAttribute(AttributeHandlerContext* context, - AttributeType* type, int8 typeIndex, const AttributeValue& value, - AttributeHandler** _handler) + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) { // notify the content handler void* token; status_t error = context->lowLevelPackageContentHandler - ->HandleAttribute(type->name, value, fToken, token); + ->HandleAttribute((BHPKGAttributeID)id, value, fToken, token); if (error != B_OK) return error; // create a subhandler for the attribute, if it has children if (_handler != NULL) { - *_handler = new(std::nothrow) PackageAttributeHandler(type->name, - value, token); + *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, + token); if (*_handler == NULL) { context->lowLevelPackageContentHandler->HandleAttributeDone( - type->name, value, token); + (BHPKGAttributeID)id, value, token); return B_NO_MEMORY; } return B_OK; @@ -567,22 +798,25 @@ struct PackageReaderImpl::PackageAttributeHandler : AttributeHandler { // no children -- just call the done hook return context->lowLevelPackageContentHandler->HandleAttributeDone( - type->name, value, token); + (BHPKGAttributeID)id, value, token); } virtual status_t Delete(AttributeHandlerContext* context) { - if (fAttributeName != NULL) { - return context->lowLevelPackageContentHandler->HandleAttributeDone( - fAttributeName, fValue, fToken); + status_t error = B_OK; + if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { + error = context->lowLevelPackageContentHandler->HandleAttributeDone( + (BHPKGAttributeID)fID, fValue, fToken); } - return B_OK; + delete this; + return error; } private: + void* fToken; - const char* fAttributeName; + uint8 fID; AttributeValue fValue; }; @@ -619,7 +853,6 @@ PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput) fTOCSection("TOC"), fPackageAttributesSection("package attributes section"), fCurrentSection(NULL), - fAttributeTypes(NULL), fScratchBuffer(NULL), fScratchBufferSize(0) { @@ -632,7 +865,6 @@ PackageReaderImpl::~PackageReaderImpl() close(fFD); delete[] fScratchBuffer; - delete[] fAttributeTypes; } @@ -737,19 +969,12 @@ PackageReaderImpl::Init(int fd, bool keepFD) } // TOC subsections - fTOCAttributeTypesLength - = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_length); - fTOCAttributeTypesCount - = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_count); fTOCSection.stringsLength = B_BENDIAN_TO_HOST_INT64(header.toc_strings_length); fTOCSection.stringsCount = B_BENDIAN_TO_HOST_INT64(header.toc_strings_count); - if (fTOCAttributeTypesLength > fTOCSection.uncompressedLength - || fTOCSection.stringsLength - > fTOCSection.uncompressedLength - fTOCAttributeTypesLength - || fTOCAttributeTypesCount > fTOCAttributeTypesLength + if (fTOCSection.stringsLength > fTOCSection.uncompressedLength || fTOCSection.stringsCount > fTOCSection.stringsLength) { fErrorOutput->PrintError("Error: Invalid package file: Invalid TOC " "subsections description\n"); @@ -826,11 +1051,15 @@ PackageReaderImpl::Init(int fd, bool keepFD) fCurrentSection = &fTOCSection; fCurrentSection->currentOffset = 0; - // attribute types - error = _ParseTOCAttributeTypes(); + // strings + error = _ParseStrings(); if (error != B_OK) return error; - fCurrentSection->currentOffset += fTOCAttributeTypesLength; + fCurrentSection->currentOffset += fCurrentSection->stringsLength; + + // parse strings from package attributes section + fCurrentSection = &fPackageAttributesSection; + fCurrentSection->currentOffset = 0; // strings error = _ParseStrings(); @@ -838,6 +1067,8 @@ PackageReaderImpl::Init(int fd, bool keepFD) return error; fCurrentSection->currentOffset += fCurrentSection->stringsLength; + fCurrentSection = NULL; + return B_OK; } @@ -847,21 +1078,7 @@ PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler) { AttributeHandlerContext context(fErrorOutput, contentHandler); RootAttributeHandler rootAttributeHandler; - - status_t result = _ParseContent(&context, &rootAttributeHandler); - if (result != B_OK) - return result; - - fCurrentSection = &fPackageAttributesSection; - fCurrentSection->currentOffset = 0; - - // strings - status_t error = _ParseStrings(); - if (error != B_OK) - return error; - fCurrentSection->currentOffset += fCurrentSection->stringsLength; - - return _ParsePackageAttributes(&context); + return _ParseContent(&context, &rootAttributeHandler); } @@ -869,7 +1086,7 @@ status_t PackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler) { AttributeHandlerContext context(fErrorOutput, contentHandler); - PackageAttributeHandler rootAttributeHandler; + LowLevelAttributeHandler rootAttributeHandler; return _ParseContent(&context, &rootAttributeHandler); } @@ -898,62 +1115,6 @@ PackageReaderImpl::_CheckCompression(const SectionInfo& section) const } -status_t -PackageReaderImpl::_ParseTOCAttributeTypes() -{ - // allocate table - fAttributeTypes = new(std::nothrow) AttributeTypeReference[ - fTOCAttributeTypesCount]; - if (fAttributeTypes == NULL) { - fErrorOutput->PrintError("Error: Out of memory!\n"); - return B_NO_MEMORY; - } - - // parse the section and fill the table - uint8* position = fTOCSection.data + fTOCSection.currentOffset; - uint8* sectionEnd = position + fTOCAttributeTypesLength; - uint32 index = 0; - while (true) { - if (position >= sectionEnd) { - fErrorOutput->PrintError("Error: Malformed TOC attribute types " - "section\n"); - return B_BAD_DATA; - } - - AttributeType* type = (AttributeType*)position; - - if (type->type == 0) { - if (position + 1 != sectionEnd) { - fErrorOutput->PrintError("Error: Excess bytes in TOC attribute " - "types section\n"); - return B_BAD_DATA; - } - - if (index != fTOCAttributeTypesCount) { - fErrorOutput->PrintError("Error: Invalid TOC attribute types " - "section: Less types than specified in the header\n"); - return B_BAD_DATA; - } - - return B_OK; - } - - if (index >= fTOCAttributeTypesCount) { - fErrorOutput->PrintError("Error: Invalid TOC attribute types " - "section: More types than specified in the header\n"); - return B_BAD_DATA; - } - - size_t nameLength = strnlen(type->name, - (char*)sectionEnd - type->name); - position = (uint8*)type->name + nameLength + 1; - fAttributeTypes[index].type = type; - fAttributeTypes[index].standardIndex = _GetStandardIndex(type); - index++; - } -} - - status_t PackageReaderImpl::_ParseStrings() { @@ -1016,8 +1177,8 @@ PackageReaderImpl::_ParseContent(AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) { // parse the TOC - fTOCSection.currentOffset = fTOCAttributeTypesLength - + fTOCSection.stringsLength; + fCurrentSection = &fTOCSection; + fTOCSection.currentOffset = fTOCSection.stringsLength; // prepare attribute handler context context->heapOffset = fHeapOffset; @@ -1039,6 +1200,25 @@ PackageReaderImpl::_ParseContent(AttributeHandlerContext* context, } } + // parse package attributes + fCurrentSection = &fPackageAttributesSection; + fAttributeHandlerStack->Add(rootAttributeHandler); + // re-init the attribute handler stack + if (error == B_OK) + error = _ParseAttributeTree(context); + if (error == B_OK) { + if (fPackageAttributesSection.currentOffset + < fPackageAttributesSection.uncompressedLength) { + fErrorOutput->PrintError("Error: %llu excess byte(s) in package " + "attributes section\n", + fPackageAttributesSection.uncompressedLength + - fPackageAttributesSection.currentOffset); + error = B_BAD_DATA; + } + } + + fCurrentSection = NULL; + // clean up on error if (error != B_OK) { context->ErrorOccurred(); @@ -1059,8 +1239,12 @@ PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context) int level = 0; while (true) { + uint8 id; + AttributeValue value; + bool hasChildren; uint64 tag; - status_t error = _ReadUnsignedLEB128(tag); + + status_t error = _ReadAttribute(id, value, &hasChildren, &tag); if (error != B_OK) return error; @@ -1076,26 +1260,8 @@ PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context) continue; } - // get the type - uint64 typeIndex = HPKG_ATTRIBUTE_TAG_INDEX(tag); - if (typeIndex >= fTOCAttributeTypesCount) { - fErrorOutput->PrintError("Error: Invalid TOC section: " - "Invalid attribute type index\n"); - return B_BAD_DATA; - } - AttributeTypeReference* type = fAttributeTypes + typeIndex; - - // get the value - AttributeValue value; - error = _ReadAttributeValue(type->type->type, - HPKG_ATTRIBUTE_TAG_ENCODING(tag), value); - if (error != B_OK) - return error; - - bool hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); AttributeHandler* childHandler = NULL; - error = _CurrentAttributeHandler()->HandleChildAttribute(context, - type->type, type->standardIndex, value, + error = _CurrentAttributeHandler()->HandleAttribute(context, id, value, hasChildren ? &childHandler : NULL); if (error != B_OK) return error; @@ -1111,9 +1277,8 @@ PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context) } } - childHandler->SetLevel(level); + childHandler->SetLevel(++level); _PushAttributeHandler(childHandler); - level++; } } } @@ -1122,145 +1287,135 @@ PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context) status_t PackageReaderImpl::_ParsePackageAttributes(AttributeHandlerContext* context) { - while (true) { - uint8 id; - AttributeValue attributeValue; - bool hasChildren; - uint64 tag; - BPackageInfoAttributeValue handlerValue; - - status_t error - = _ReadPackageAttribute(id, attributeValue, &hasChildren, &tag); - if (error != B_OK) - return error; - - if (tag == 0) { - return - context->packageContentHandler->HandlePackageAttributesDone(); - } - - switch (id) { - case HPKG_PACKAGE_ATTRIBUTE_NAME: - handlerValue.SetTo(B_PACKAGE_INFO_NAME, attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_SUMMARY: - handlerValue.SetTo(B_PACKAGE_INFO_SUMMARY, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION: - handlerValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_VENDOR: - handlerValue.SetTo(B_PACKAGE_INFO_VENDOR, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_PACKAGER: - handlerValue.SetTo(B_PACKAGE_INFO_PACKAGER, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_FLAGS: - handlerValue.SetTo(B_PACKAGE_INFO_FLAGS, - (uint32)attributeValue.unsignedInt); - break; - - case HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE: - if (attributeValue.unsignedInt - >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { - fErrorOutput->PrintError( - "Error: Invalid package attribute section: " - "Invalid package architecture %lld encountered\n", - attributeValue.unsignedInt); - return B_BAD_DATA; - } - handlerValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, - (uint8)attributeValue.unsignedInt); - break; - - case HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR: - error = _ParsePackageVersion(handlerValue.version, - attributeValue.string); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_VERSION; - break; - - case HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT: - handlerValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_LICENSE: - handlerValue.SetTo(B_PACKAGE_INFO_LICENSES, - attributeValue.string); - break; - - case HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE: - error = _ParsePackageProvides(handlerValue.resolvable, - (BPackageResolvableType)attributeValue.unsignedInt); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_PROVIDES; - break; - - case HPKG_PACKAGE_ATTRIBUTE_REQUIRES: - error = _ParsePackageResolvableExpression( - handlerValue.resolvableExpression, attributeValue.string, - hasChildren); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_REQUIRES; - break; - - case HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS: - error = _ParsePackageResolvableExpression( - handlerValue.resolvableExpression, attributeValue.string, - hasChildren); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_SUPPLEMENTS; - break; - - case HPKG_PACKAGE_ATTRIBUTE_CONFLICTS: - error = _ParsePackageResolvableExpression( - handlerValue.resolvableExpression, attributeValue.string, - hasChildren); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_CONFLICTS; - break; - - case HPKG_PACKAGE_ATTRIBUTE_FRESHENS: - error = _ParsePackageResolvableExpression( - handlerValue.resolvableExpression, attributeValue.string, - hasChildren); - if (error != B_OK) - return error; - handlerValue.attributeIndex = B_PACKAGE_INFO_FRESHENS; - break; - - case HPKG_PACKAGE_ATTRIBUTE_REPLACES: - handlerValue.SetTo(B_PACKAGE_INFO_REPLACES, - attributeValue.string); - break; - - default: - fErrorOutput->PrintError( - "Error: Invalid package attribute section: unexpected " - "package attribute id %d encountered\n", id); - return B_BAD_DATA; - } - - error = context->packageContentHandler->HandlePackageAttribute( - handlerValue); - if (error != B_OK) - return error; - } +// +// if (tag == 0) { +// return +// context->packageContentHandler->HandlePackageAttributesDone(); +// } +// +// switch (id) { +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME: +// handlerValue.SetTo(B_PACKAGE_INFO_NAME, attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY: +// handlerValue.SetTo(B_PACKAGE_INFO_SUMMARY, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION: +// handlerValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR: +// handlerValue.SetTo(B_PACKAGE_INFO_VENDOR, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER: +// handlerValue.SetTo(B_PACKAGE_INFO_PACKAGER, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: +// handlerValue.SetTo(B_PACKAGE_INFO_FLAGS, +// (uint32)attributeValue.unsignedInt); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: +// if (attributeValue.unsignedInt +// >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { +// fErrorOutput->PrintError( +// "Error: Invalid package attribute section: " +// "Invalid package architecture %lld encountered\n", +// attributeValue.unsignedInt); +// return B_BAD_DATA; +// } +// handlerValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, +// (uint8)attributeValue.unsignedInt); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: +// error = _ParsePackageVersion(handlerValue.version, +// attributeValue.string); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_VERSION; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: +// handlerValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: +// handlerValue.SetTo(B_PACKAGE_INFO_LICENSES, +// attributeValue.string); +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE: +// error = _ParsePackageProvides(handlerValue.resolvable, +// (BPackageResolvableType)attributeValue.unsignedInt); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_PROVIDES; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: +// error = _ParsePackageResolvableExpression( +// handlerValue.resolvableExpression, attributeValue.string, +// hasChildren); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_REQUIRES; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: +// error = _ParsePackageResolvableExpression( +// handlerValue.resolvableExpression, attributeValue.string, +// hasChildren); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_SUPPLEMENTS; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: +// error = _ParsePackageResolvableExpression( +// handlerValue.resolvableExpression, attributeValue.string, +// hasChildren); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_CONFLICTS; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: +// error = _ParsePackageResolvableExpression( +// handlerValue.resolvableExpression, attributeValue.string, +// hasChildren); +// if (error != B_OK) +// return error; +// handlerValue.attributeID = B_PACKAGE_INFO_FRESHENS; +// break; +// +// case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: +// handlerValue.SetTo(B_PACKAGE_INFO_REPLACES, +// attributeValue.string); +// break; +// +// default: +// fErrorOutput->PrintError( +// "Error: Invalid package attribute section: unexpected " +// "package attribute id %d encountered\n", id); +// return B_BAD_DATA; +// } +// +// error = context->packageContentHandler->HandlePackageAttribute( +// handlerValue); +// if (error != B_OK) +// return error; +// } + return B_OK; } @@ -1268,62 +1423,62 @@ status_t PackageReaderImpl::_ParsePackageVersion(BPackageVersionData& _version, const char* major) { - uint8 id; - AttributeValue value; - status_t error; - - _version.major = NULL; - _version.minor = NULL; - _version.micro = NULL; - _version.release = 0; - - // major (may have been read already) - if (major == NULL) { - error = _ReadPackageAttribute(id, value); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package version, expected major\n"); - return B_BAD_DATA; - } - major = value.string; - } - _version.major = major; - - // minor - error = _ReadPackageAttribute(id, value); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package version, expected minor\n"); - return B_BAD_DATA; - } - _version.minor = value.string; - - // micro - error = _ReadPackageAttribute(id, value); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MICRO) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package version, expected micro\n"); - return B_BAD_DATA; - } - _version.micro = value.string; - - // release - error = _ReadPackageAttribute(id, value); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_RELEASE) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package version, expected release\n"); - return B_BAD_DATA; - } - _version.release = (uint8)value.unsignedInt; - +// uint8 id; +// AttributeValue value; +// status_t error; +// +// _version.major = NULL; +// _version.minor = NULL; +// _version.micro = NULL; +// _version.release = 0; +// +// // major (may have been read already) +// if (major == NULL) { +// error = _ReadPackageAttribute(id, value); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package version, expected major\n"); +// return B_BAD_DATA; +// } +// major = value.string; +// } +// _version.major = major; +// +// // minor +// error = _ReadPackageAttribute(id, value); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package version, expected minor\n"); +// return B_BAD_DATA; +// } +// _version.minor = value.string; +// +// // micro +// error = _ReadPackageAttribute(id, value); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package version, expected micro\n"); +// return B_BAD_DATA; +// } +// _version.micro = value.string; +// +// // release +// error = _ReadPackageAttribute(id, value); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_RELEASE) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package version, expected release\n"); +// return B_BAD_DATA; +// } +// _version.release = (uint8)value.unsignedInt; +// return B_OK; } @@ -1332,46 +1487,46 @@ status_t PackageReaderImpl::_ParsePackageProvides(BPackageResolvableData& _resolvable, BPackageResolvableType providesType) { - uint8 id; - AttributeValue value; - bool hasChildren; - - if (providesType >= B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT) { - fErrorOutput->PrintError("Error: Invalid package attribute section: " - "Invalid package provides type %lld encountered\n", providesType); - return B_BAD_DATA; - } - _resolvable.type = providesType; - _resolvable.haveVersion = false; - - // provides name - status_t error = _ReadPackageAttribute(id, value, &hasChildren); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_PROVIDES) { - fErrorOutput->PrintError("Error: Invalid package attribute section: " - "Invalid package provides, expected name of resolvable\n"); - return B_BAD_DATA; - } - _resolvable.name = value.string; - - // there may be a version added as child - if (hasChildren) { - error = _ParsePackageVersion(_resolvable.version); - if (error != B_OK) - return error; - - _resolvable.haveVersion = true; - - uint64 tag; - if ((error = _ReadUnsignedLEB128(tag)) != B_OK) - return error; - if (tag != 0) { - fErrorOutput->PrintError("Error: Invalid package attribute " - "section: Invalid package provides, expected end-tag\n"); - return B_BAD_DATA; - } - } +// uint8 id; +// AttributeValue value; +// bool hasChildren; +// +// if (providesType >= B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT) { +// fErrorOutput->PrintError("Error: Invalid package attribute section: " +// "Invalid package provides type %lld encountered\n", providesType); +// return B_BAD_DATA; +// } +// _resolvable.type = providesType; +// _resolvable.haveVersion = false; +// +// // provides name +// status_t error = _ReadPackageAttribute(id, value, &hasChildren); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES) { +// fErrorOutput->PrintError("Error: Invalid package attribute section: " +// "Invalid package provides, expected name of resolvable\n"); +// return B_BAD_DATA; +// } +// _resolvable.name = value.string; +// +// // there may be a version added as child +// if (hasChildren) { +// error = _ParsePackageVersion(_resolvable.version); +// if (error != B_OK) +// return error; +// +// _resolvable.haveVersion = true; +// +// uint64 tag; +// if ((error = _ReadUnsignedLEB128(tag)) != B_OK) +// return error; +// if (tag != 0) { +// fErrorOutput->PrintError("Error: Invalid package attribute " +// "section: Invalid package provides, expected end-tag\n"); +// return B_BAD_DATA; +// } +// } return B_OK; } @@ -1382,55 +1537,55 @@ PackageReaderImpl::_ParsePackageResolvableExpression( BPackageResolvableExpressionData& _resolvableExpression, const char* resolvableName, bool hasChildren) { - _resolvableExpression.name = resolvableName; - _resolvableExpression.haveOpAndVersion = false; - - // there may be an operator and a version added as child - if (hasChildren) { - // resolvable-expression operator - uint8 id; - AttributeValue value; - status_t error = _ReadPackageAttribute(id, value); - if (error != B_OK) - return error; - if (id != HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package resolvable expression, expected operator\n"); - return B_BAD_DATA; - } - - if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package resolvable operator %lld encountered\n", - value.unsignedInt); - return B_BAD_DATA; - } - - _resolvableExpression.op - = (BPackageResolvableOperator)value.unsignedInt; - - error = _ParsePackageVersion(_resolvableExpression.version); - if (error != B_OK) - return error; - - _resolvableExpression.haveOpAndVersion = true; - - uint64 tag; - if ((error = _ReadUnsignedLEB128(tag)) != B_OK) - return error; - if (tag != 0) { - fErrorOutput->PrintError("Error: Invalid package attribute section:" - " Invalid package resolvable expression, expected end-tag\n"); - return B_BAD_DATA; - } - } +// _resolvableExpression.name = resolvableName; +// _resolvableExpression.haveOpAndVersion = false; +// +// // there may be an operator and a version added as child +// if (hasChildren) { +// // resolvable-expression operator +// uint8 id; +// AttributeValue value; +// status_t error = _ReadPackageAttribute(id, value); +// if (error != B_OK) +// return error; +// if (id != B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package resolvable expression, expected operator\n"); +// return B_BAD_DATA; +// } +// +// if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package resolvable operator %lld encountered\n", +// value.unsignedInt); +// return B_BAD_DATA; +// } +// +// _resolvableExpression.op +// = (BPackageResolvableOperator)value.unsignedInt; +// +// error = _ParsePackageVersion(_resolvableExpression.version); +// if (error != B_OK) +// return error; +// +// _resolvableExpression.haveOpAndVersion = true; +// +// uint64 tag; +// if ((error = _ReadUnsignedLEB128(tag)) != B_OK) +// return error; +// if (tag != 0) { +// fErrorOutput->PrintError("Error: Invalid package attribute section:" +// " Invalid package resolvable expression, expected end-tag\n"); +// return B_BAD_DATA; +// } +// } return B_OK; } status_t -PackageReaderImpl::_ReadPackageAttribute(uint8& _id, AttributeValue& _value, +PackageReaderImpl::_ReadAttribute(uint8& _id, AttributeValue& _value, bool* _hasChildren, uint64* _tag) { uint64 tag; @@ -1440,29 +1595,29 @@ PackageReaderImpl::_ReadPackageAttribute(uint8& _id, AttributeValue& _value, if (tag != 0) { // get the type - uint16 type = HPKG_PACKAGE_ATTRIBUTE_TAG_TYPE(tag); + uint16 type = HPKG_ATTRIBUTE_TAG_TYPE(tag); if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { - fErrorOutput->PrintError("Error: Invalid package attribute " - "section: attribute type %d not supported!\n", type); + fErrorOutput->PrintError("Error: Invalid %s section: attribute " + "type %d not supported!\n", fCurrentSection->name, type); return B_BAD_DATA; } // get the value - error = _ReadAttributeValue(type, - HPKG_PACKAGE_ATTRIBUTE_TAG_ENCODING(tag), _value); + error = _ReadAttributeValue(type, HPKG_ATTRIBUTE_TAG_ENCODING(tag), + _value); if (error != B_OK) return error; - _id = HPKG_PACKAGE_ATTRIBUTE_TAG_ID(tag); - if (_id >= HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT) { - fErrorOutput->PrintError("Error: Invalid package attribute section: " - "attribute id %d not supported!\n", _id); + _id = HPKG_ATTRIBUTE_TAG_ID(tag); + if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { + fErrorOutput->PrintError("Error: Invalid %s section: " + "attribute id %d not supported!\n", fCurrentSection->name, _id); return B_BAD_DATA; } } if (_hasChildren != NULL) - *_hasChildren = HPKG_PACKAGE_ATTRIBUTE_TAG_HAS_CHILDREN(tag); + *_hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); if (_tag != NULL) *_tag = tag; @@ -1767,21 +1922,6 @@ PackageReaderImpl::_ReadCompressedBuffer(const SectionInfo& section) } -/*static*/ int8 -PackageReaderImpl::_GetStandardIndex(const AttributeType* type) -{ - // TODO: Building a hash table once would make the loopup faster. - for (int32 i = 0; kStandardAttributeIndices[i].name != NULL; i++) { - if (type->type == kStandardAttributeIndices[i].type - && strcmp(kStandardAttributeIndices[i].name, type->name) == 0) { - return i; - } - } - - return -1; -} - - } // namespace BPrivate } // namespace BHPKG diff --git a/src/kits/package/hpkg/PackageWriterImpl.cpp b/src/kits/package/hpkg/PackageWriterImpl.cpp index 718d96a87d..f2f277648d 100644 --- a/src/kits/package/hpkg/PackageWriterImpl.cpp +++ b/src/kits/package/hpkg/PackageWriterImpl.cpp @@ -28,7 +28,7 @@ #include -#include +#include #include #include @@ -52,87 +52,15 @@ static const size_t kZlibCompressionSizeThreshold = 64; // #pragma mark - Attributes -struct PackageWriterImpl::AttributeTypeKey { - const char* name; - uint8 type; - - AttributeTypeKey(const char* name, uint8 type) - : - name(name), - type(type) - { - } -}; - - -struct PackageWriterImpl::AttributeType { - char* name; - uint8 type; - int32 index; - uint32 usageCount; - AttributeType* next; // hash table link - - AttributeType() - : - name(NULL), - type(B_HPKG_ATTRIBUTE_TYPE_INVALID), - index(-1), - usageCount(1) - { - } - - ~AttributeType() - { - free(name); - } - - bool Init(const char* name, uint8 type) - { - this->name = strdup(name); - if (this->name == NULL) - return false; - - this->type = type; - return true; - } -}; - - -struct PackageWriterImpl::AttributeTypeHashDefinition { - typedef AttributeTypeKey KeyType; - typedef AttributeType ValueType; - - size_t HashKey(const AttributeTypeKey& key) const - { - return hash_string(key.name) ^ (uint32)key.type; - } - - size_t Hash(const AttributeType* value) const - { - return hash_string(value->name) ^ (uint32)value->type; - } - - bool Compare(const AttributeTypeKey& key, const AttributeType* value) const - { - return strcmp(value->name, key.name) == 0 && value->type == key.type; - } - - AttributeType*& GetLink(AttributeType* value) const - { - return value->next; - } -}; - - struct PackageWriterImpl::Attribute : public DoublyLinkedListLinkImpl { - AttributeType* type; + BHPKGAttributeID id; AttributeValue value; DoublyLinkedList children; - Attribute(AttributeType* type) + Attribute(BHPKGAttributeID id_ = B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) : - type(type) + id(id_) { } @@ -154,14 +82,6 @@ struct PackageWriterImpl::Attribute }; -struct PackageWriterImpl::AttributeTypeUsageGreater { - bool operator()(const AttributeType* a, const AttributeType* b) - { - return a->usageCount > b->usageCount; - } -}; - - // #pragma mark - Entry @@ -279,11 +199,11 @@ private: template inline PackageWriterImpl::Attribute* -PackageWriterImpl::_AddAttribute(const char* attributeName, Type value) +PackageWriterImpl::_AddAttribute(BHPKGAttributeID attributeID, Type value) { AttributeValue attributeValue; attributeValue.SetTo(value); - return _AddAttribute(attributeName, attributeValue); + return _AddAttribute(attributeID, attributeValue); } @@ -298,8 +218,7 @@ PackageWriterImpl::PackageWriterImpl(BPackageWriterListener* listener) fDataBufferSize(2 * B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB), fRootEntry(NULL), fRootAttribute(NULL), - fTopAttribute(NULL), - fAttributeTypes(NULL) + fTopAttribute(NULL) { } @@ -308,15 +227,6 @@ PackageWriterImpl::~PackageWriterImpl() { delete fRootAttribute; - if (fAttributeTypes != NULL) { - AttributeType* attributeType = fAttributeTypes->Clear(true); - while (attributeType != NULL) { - AttributeType* next = attributeType->next; - delete attributeType; - attributeType = next; - } - } - delete fRootEntry; free(fDataBuffer); @@ -409,14 +319,10 @@ PackageWriterImpl::_Init(const char* fileName) if (fStringCache.Init() != B_OK) throw std::bad_alloc(); - fAttributeTypes = new AttributeTypeTable; - if (fAttributeTypes->Init() != B_OK) - throw std::bad_alloc(); - // create entry list fRootEntry = new Entry(NULL, 0, true); - fRootAttribute = new Attribute(NULL); + fRootAttribute = new Attribute(); fHeapOffset = fHeapEnd = sizeof(hpkg_header); fTopAttribute = fRootAttribute; @@ -587,12 +493,10 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header) zlibWriter.Init(); // write the sections - uint64 uncompressedAttributeTypesSize; uint64 uncompressedStringsSize; uint64 uncompressedMainSize; - int32 cachedStringsWritten = _WriteTOCSections( - uncompressedAttributeTypesSize, uncompressedStringsSize, - uncompressedMainSize); + int32 cachedStringsWritten + = _WriteTOCSections(uncompressedStringsSize, uncompressedMainSize); // finish the writer zlibWriter.Finish(); @@ -601,8 +505,7 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header) off_t endOffset = fHeapEnd; - fListener->OnTOCSizeInfo(uncompressedAttributeTypesSize, - uncompressedStringsSize, uncompressedMainSize, + fListener->OnTOCSizeInfo(uncompressedStringsSize, uncompressedMainSize, zlibWriter.BytesWritten()); // update the header @@ -615,10 +518,6 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header) zlibWriter.BytesWritten()); // TOC subsections - header.toc_attribute_types_length = B_HOST_TO_BENDIAN_INT64( - uncompressedAttributeTypesSize); - header.toc_attribute_types_count = B_HOST_TO_BENDIAN_INT64( - fAttributeTypes->CountElements()); header.toc_strings_length = B_HOST_TO_BENDIAN_INT64( uncompressedStringsSize); header.toc_strings_count = B_HOST_TO_BENDIAN_INT64(cachedStringsWritten); @@ -626,13 +525,8 @@ PackageWriterImpl::_WriteTOC(hpkg_header& header) int32 -PackageWriterImpl::_WriteTOCSections(uint64& _attributeTypesSize, - uint64& _stringsSize, uint64& _mainSize) +PackageWriterImpl::_WriteTOCSections(uint64& _stringsSize, uint64& _mainSize) { - // write the attribute type abbreviations - uint64 attributeTypesOffset = DataWriter()->BytesWritten(); - _WriteAttributeTypes(); - // write the cached strings uint64 cachedStringsOffset = DataWriter()->BytesWritten(); int32 cachedStringsWritten = WriteCachedStrings(fStringCache, 2); @@ -641,7 +535,6 @@ PackageWriterImpl::_WriteTOCSections(uint64& _attributeTypesSize, uint64 mainOffset = DataWriter()->BytesWritten(); _WriteAttributeChildren(fRootAttribute); - _attributeTypesSize = cachedStringsOffset - attributeTypesOffset; _stringsSize = mainOffset - cachedStringsOffset; _mainSize = DataWriter()->BytesWritten() - mainOffset; @@ -649,50 +542,16 @@ PackageWriterImpl::_WriteTOCSections(uint64& _attributeTypesSize, } -void -PackageWriterImpl::_WriteAttributeTypes() -{ - // create an array of the attribute types - int32 attributeTypeCount = fAttributeTypes->CountElements(); - AttributeType** attributeTypes = new AttributeType*[attributeTypeCount]; - ArrayDeleter attributeTypesDeleter(attributeTypes); - - int32 index = 0; - for (AttributeTypeTable::Iterator it = fAttributeTypes->GetIterator(); - AttributeType* type = it.Next();) { - attributeTypes[index++] = type; - } - - // sort it by descending usage count - std::sort(attributeTypes, attributeTypes + attributeTypeCount, - AttributeTypeUsageGreater()); - - // assign the indices and write entries to disk - for (int32 i = 0; i < attributeTypeCount; i++) { - AttributeType* attributeType = attributeTypes[i]; - attributeType->index = i; - - Write(attributeType->type); - WriteString(attributeType->name); - } - - // write a terminating 0 byte - Write(0); -} - - void PackageWriterImpl::_WriteAttributeChildren(Attribute* attribute) { DoublyLinkedList::Iterator it = attribute->children.GetIterator(); while (Attribute* child = it.Next()) { - AttributeType* type = child->type; - // write tag uint8 encoding = child->value.ApplicableEncoding(); - WriteUnsignedLEB128(HPKG_ATTRIBUTE_TAG_COMPOSE(type->index, - encoding, !child->children.IsEmpty())); + WriteUnsignedLEB128(HPKG_ATTRIBUTE_TAG_COMPOSE(child->id, + child->value.type, encoding, !child->children.IsEmpty())); // write value WriteAttributeValue(child->value, encoding); @@ -800,19 +659,19 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName, // add attribute entry Attribute* entryAttribute = _AddStringAttribute( - HPKG_ATTRIBUTE_NAME_DIRECTORY_ENTRY, fileName); + B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY, fileName); Stacker entryAttributeStacker(fTopAttribute, entryAttribute); // add stat data if (fileType != B_HPKG_DEFAULT_FILE_TYPE) - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_TYPE, fileType); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_TYPE, fileType); if (defaultPermissions != uint32(st.st_mode & ALLPERMS)) { - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_PERMISSIONS, + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS, uint32(st.st_mode & ALLPERMS)); } - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_ATIME, uint32(st.st_atime)); - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_MTIME, uint32(st.st_mtime)); - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_CRTIME, uint32(st.st_crtime)); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_ATIME, uint32(st.st_atime)); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_MTIME, uint32(st.st_mtime)); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_CRTIME, uint32(st.st_crtime)); // TODO: File user/group! // add file data/symlink path @@ -836,7 +695,7 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName, } path[bytesRead] = '\0'; - _AddStringAttribute(HPKG_ATTRIBUTE_NAME_SYMLINK_PATH, path); + _AddStringAttribute(B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH, path); } // add attributes @@ -854,12 +713,12 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName, // create attribute entry Attribute* attributeAttribute = _AddStringAttribute( - HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE, entry->d_name); + B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE, entry->d_name); Stacker attributeAttributeStacker(fTopAttribute, attributeAttribute); // add type - _AddAttribute(HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE_TYPE, + _AddAttribute(B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE, (uint32)attrInfo.type); // add data @@ -912,11 +771,10 @@ PackageWriterImpl::_AddEntry(int dirFD, Entry* entry, const char* fileName, PackageWriterImpl::Attribute* -PackageWriterImpl::_AddAttribute(const char* attributeName, +PackageWriterImpl::_AddAttribute(BHPKGAttributeID id, const AttributeValue& value) { - Attribute* attribute = new Attribute( - _GetAttributeType(attributeName, value.type)); + Attribute* attribute = new Attribute(id); attribute->value = value; fTopAttribute->AddChild(attribute); @@ -926,53 +784,32 @@ PackageWriterImpl::_AddAttribute(const char* attributeName, PackageWriterImpl::Attribute* -PackageWriterImpl::_AddStringAttribute(const char* attributeName, +PackageWriterImpl::_AddStringAttribute(BHPKGAttributeID attributeID, const char* value) { AttributeValue attributeValue; attributeValue.SetTo(fStringCache.Get(value)); - return _AddAttribute(attributeName, attributeValue); + return _AddAttribute(attributeID, attributeValue); } PackageWriterImpl::Attribute* -PackageWriterImpl::_AddDataAttribute(const char* attributeName, uint64 dataSize, - uint64 dataOffset) +PackageWriterImpl::_AddDataAttribute(BHPKGAttributeID attributeID, + uint64 dataSize, uint64 dataOffset) { AttributeValue attributeValue; attributeValue.SetToData(dataSize, dataOffset); - return _AddAttribute(attributeName, attributeValue); + return _AddAttribute(attributeID, attributeValue); } PackageWriterImpl::Attribute* -PackageWriterImpl::_AddDataAttribute(const char* attributeName, uint64 dataSize, - const uint8* data) +PackageWriterImpl::_AddDataAttribute(BHPKGAttributeID attributeID, + uint64 dataSize, const uint8* data) { AttributeValue attributeValue; attributeValue.SetToData(dataSize, data); - return _AddAttribute(attributeName, attributeValue); -} - - -PackageWriterImpl::AttributeType* -PackageWriterImpl::_GetAttributeType(const char* attributeName, uint8 type) -{ - AttributeType* attributeType = fAttributeTypes->Lookup( - AttributeTypeKey(attributeName, type)); - if (attributeType != NULL) { - attributeType->usageCount++; - return attributeType; - } - - attributeType = new AttributeType; - if (!attributeType->Init(attributeName, type)) { - delete attributeType; - throw std::bad_alloc(); - } - - fAttributeTypes->Insert(attributeType); - return attributeType; + return _AddAttribute(attributeID, attributeValue); } @@ -988,7 +825,7 @@ PackageWriterImpl::_AddData(BDataReader& dataReader, off_t size) return error; } - _AddDataAttribute(HPKG_ATTRIBUTE_NAME_DATA, size, buffer); + _AddDataAttribute(B_HPKG_ATTRIBUTE_ID_DATA, size, buffer); return B_OK; } @@ -1012,14 +849,14 @@ PackageWriterImpl::_AddData(BDataReader& dataReader, off_t size) fHeapEnd = dataOffset + compressedSize; // add data attribute - Attribute* dataAttribute = _AddDataAttribute(HPKG_ATTRIBUTE_NAME_DATA, + Attribute* dataAttribute = _AddDataAttribute(B_HPKG_ATTRIBUTE_ID_DATA, compressedSize, dataOffset - fHeapOffset); Stacker attributeAttributeStacker(fTopAttribute, dataAttribute); // if compressed, add compression attributes if (compression != B_HPKG_COMPRESSION_NONE) { - _AddAttribute(HPKG_ATTRIBUTE_NAME_DATA_COMPRESSION, compression); - _AddAttribute(HPKG_ATTRIBUTE_NAME_DATA_SIZE, (uint64)size); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_DATA_COMPRESSION, compression); + _AddAttribute(B_HPKG_ATTRIBUTE_ID_DATA_SIZE, (uint64)size); // uncompressed size } diff --git a/src/kits/package/hpkg/RepositoryReader.cpp b/src/kits/package/hpkg/RepositoryReader.cpp new file mode 100644 index 0000000000..1e1cc33e3d --- /dev/null +++ b/src/kits/package/hpkg/RepositoryReader.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +BRepositoryReader::BRepositoryReader(BErrorOutput* errorOutput) + : + fImpl(new (std::nothrow) RepositoryReaderImpl(errorOutput)) +{ +} + + +BRepositoryReader::~BRepositoryReader() +{ + delete fImpl; +} + + +status_t +BRepositoryReader::Init(const char* fileName) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->Init(fileName); +} + + +status_t +BRepositoryReader::ParseContent(BRepositoryContentHandler* contentHandler) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->ParseContent(contentHandler); +} + + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/RepositoryReaderImpl.cpp b/src/kits/package/hpkg/RepositoryReaderImpl.cpp new file mode 100644 index 0000000000..211892ea2d --- /dev/null +++ b/src/kits/package/hpkg/RepositoryReaderImpl.cpp @@ -0,0 +1,1804 @@ +/* + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace BPrivate { + + +//#define TRACE(format...) printf(format) +#define TRACE(format...) do {} while (false) + + +// maximum TOC size we support reading +static const size_t kMaxTOCSize = 64 * 1024 * 1024; + +// maximum package attributes size we support reading +static const size_t kMaxPackageAttributesSize = 1 * 1024 * 1024; + +static const size_t kScratchBufferSize = 64 * 1024; + + +enum { + ATTRIBUTE_INDEX_DIRECTORY_ENTRY = 0, + ATTRIBUTE_INDEX_FILE_TYPE, + ATTRIBUTE_INDEX_FILE_PERMISSIONS, + ATTRIBUTE_INDEX_FILE_USER, + ATTRIBUTE_INDEX_FILE_GROUP, + ATTRIBUTE_INDEX_FILE_ATIME, + ATTRIBUTE_INDEX_FILE_MTIME, + ATTRIBUTE_INDEX_FILE_CRTIME, + ATTRIBUTE_INDEX_FILE_ATIME_NANOS, + ATTRIBUTE_INDEX_FILE_MTIME_NANOS, + ATTRIBUTE_INDEX_FILE_CRTIM_NANOS, + ATTRIBUTE_INDEX_FILE_ATTRIBUTE, + ATTRIBUTE_INDEX_FILE_ATTRIBUTE_TYPE, + ATTRIBUTE_INDEX_DATA, + ATTRIBUTE_INDEX_DATA_SIZE, + ATTRIBUTE_INDEX_DATA_COMPRESSION, + ATTRIBUTE_INDEX_DATA_CHUNK_SIZE, + ATTRIBUTE_INDEX_SYMLINK_PATH +}; + + +struct standard_attribute_index_entry { + const char* name; + uint8 type; + int8 index; +}; + +#undef MAKE_ATTRIBUTE_INDEX_ENTRY +#define MAKE_ATTRIBUTE_INDEX_ENTRY(name, type) \ + { B_HPKG_ATTRIBUTE_ID_##name, B_HPKG_ATTRIBUTE_TYPE_##type, \ + ATTRIBUTE_INDEX_##name } + +static const standard_attribute_index_entry kStandardAttributeIndices[] = { + MAKE_ATTRIBUTE_INDEX_ENTRY(DIRECTORY_ENTRY, STRING), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_TYPE, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_PERMISSIONS, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_USER, STRING), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_GROUP, STRING), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATIME, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_MTIME, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_CRTIME, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATIME_NANOS, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_MTIME_NANOS, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_CRTIM_NANOS, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATTRIBUTE, STRING), + MAKE_ATTRIBUTE_INDEX_ENTRY(FILE_ATTRIBUTE_TYPE, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(DATA, RAW), + MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_SIZE, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_COMPRESSION, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(DATA_CHUNK_SIZE, UINT), + MAKE_ATTRIBUTE_INDEX_ENTRY(SYMLINK_PATH, STRING), + {} +}; + + +// #pragma mark - AttributeType + + +struct PackageReaderImpl::AttributeType { + uint8 type; + char name[0]; +}; + + +// #pragma mark - AttributeType + + +struct PackageReaderImpl::AttributeTypeReference { + AttributeType* type; + int32 standardIndex; +}; + + +// #pragma mark - AttributeHandler + + +struct PackageReaderImpl::AttributeHandlerContext { + BErrorOutput* errorOutput; + union { + BPackageContentHandler* packageContentHandler; + BLowLevelPackageContentHandler* lowLevelPackageContentHandler; + }; + bool hasLowLevelHandler; + + uint64 heapOffset; + uint64 heapSize; + + + AttributeHandlerContext(BErrorOutput* errorOutput, + BPackageContentHandler* packageContentHandler) + : + errorOutput(errorOutput), + packageContentHandler(packageContentHandler), + hasLowLevelHandler(false) + { + } + + AttributeHandlerContext(BErrorOutput* errorOutput, + BLowLevelPackageContentHandler* lowLevelPackageContentHandler) + : + errorOutput(errorOutput), + lowLevelPackageContentHandler(lowLevelPackageContentHandler), + hasLowLevelHandler(true) + { + } + + void ErrorOccurred() + { + if (hasLowLevelHandler) + lowLevelPackageContentHandler->HandleErrorOccurred(); + else + packageContentHandler->HandleErrorOccurred(); + } +}; + + +struct PackageReaderImpl::AttributeHandler + : SinglyLinkedListLinkImpl { + + virtual ~AttributeHandler() + { + } + + void SetLevel(int level) + { + fLevel = level; + } + + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { +TRACE("%*signored attribute \"%s\" (%u)\n", fLevel * 2, "", type->name, type->type); + return B_OK; + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + delete this; + return B_OK; + } + +protected: + int fLevel; +}; + + +struct PackageReaderImpl::IgnoreAttributeHandler : AttributeHandler { +}; + + +struct PackageReaderImpl::DataAttributeHandler : AttributeHandler { + DataAttributeHandler(BPackageData* data) + : + fData(data) + { + } + + static status_t InitData(AttributeHandlerContext* context, + BPackageData* data, const AttributeValue& value) + { + if (value.encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE) + data->SetData(value.data.size, value.data.raw); + else + data->SetData(value.data.size, value.data.offset); + + data->SetUncompressedSize(value.data.size); + + return B_OK; + } + + static status_t Create(AttributeHandlerContext* context, + BPackageData* data, const AttributeValue& value, + AttributeHandler*& _handler) + { + DataAttributeHandler* handler = new(std::nothrow) DataAttributeHandler( + data); + if (handler == NULL) + return B_NO_MEMORY; + + InitData(context, data, value); + + _handler = handler; + return B_OK; + } + + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { + switch (typeIndex) { + case ATTRIBUTE_INDEX_DATA_SIZE: + fData->SetUncompressedSize(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_DATA_COMPRESSION: + { + switch (value.unsignedInt) { + case B_HPKG_COMPRESSION_NONE: + case B_HPKG_COMPRESSION_ZLIB: + break; + default: + context->errorOutput->PrintError("Error: Invalid " + "compression type for data (%llu)\n", + value.unsignedInt); + return B_BAD_DATA; + } + + fData->SetCompression(value.unsignedInt); + return B_OK; + } + + case ATTRIBUTE_INDEX_DATA_CHUNK_SIZE: + fData->SetChunkSize(value.unsignedInt); + return B_OK; + } + + return AttributeHandler::HandleChildAttribute(context, type, typeIndex, + value, _handler); + } + +private: + BPackageData* fData; +}; + + +struct PackageReaderImpl::AttributeAttributeHandler : AttributeHandler { + AttributeAttributeHandler(BPackageEntry* entry, const char* name) + : + fEntry(entry), + fAttribute(name) + { + } + + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { + switch (typeIndex) { + case ATTRIBUTE_INDEX_DATA: + { + if (_handler != NULL) { + return DataAttributeHandler::Create(context, + &fAttribute.Data(), value, *_handler); + } + return DataAttributeHandler::InitData(context, + &fAttribute.Data(), value); + } + + case ATTRIBUTE_INDEX_FILE_ATTRIBUTE_TYPE: + fAttribute.SetType(value.unsignedInt); + return B_OK; + } + + return AttributeHandler::HandleChildAttribute(context, type, typeIndex, + value, _handler); + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + status_t error = context->packageContentHandler->HandleEntryAttribute( + fEntry, &fAttribute); + + delete this; + return error; + } + +private: + BPackageEntry* fEntry; + BPackageEntryAttribute fAttribute; +}; + + +struct PackageReaderImpl::EntryAttributeHandler : AttributeHandler { + EntryAttributeHandler(AttributeHandlerContext* context, + BPackageEntry* parentEntry, const char* name) + : + fEntry(parentEntry, name), + fNotified(false) + { + _SetFileType(context, B_HPKG_DEFAULT_FILE_TYPE); + } + + static status_t Create(AttributeHandlerContext* context, + BPackageEntry* parentEntry, const char* name, + AttributeHandler*& _handler) + { + // check name + if (name[0] == '\0' || strcmp(name, ".") == 0 + || strcmp(name, "..") == 0 || strchr(name, '/') != NULL) { + context->errorOutput->PrintError("Error: Invalid package: Invalid " + "entry name: \"%s\"\n", name); + return B_BAD_DATA; + } + + // create handler + EntryAttributeHandler* handler = new(std::nothrow) + EntryAttributeHandler(context, parentEntry, name); + if (handler == NULL) + return B_NO_MEMORY; + + _handler = handler; + return B_OK; + } + + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { + switch (typeIndex) { + case ATTRIBUTE_INDEX_DIRECTORY_ENTRY: + { + status_t error = _Notify(context); + if (error != B_OK) + return error; + +//TRACE("%*sentry \"%s\"\n", fLevel * 2, "", value.string); + if (_handler != NULL) { + return EntryAttributeHandler::Create(context, &fEntry, + value.string, *_handler); + } + return B_OK; + } + + case ATTRIBUTE_INDEX_FILE_TYPE: + return _SetFileType(context, value.unsignedInt); + + case ATTRIBUTE_INDEX_FILE_PERMISSIONS: + fEntry.SetPermissions(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_USER: + case ATTRIBUTE_INDEX_FILE_GROUP: + // TODO:... + break; + + case ATTRIBUTE_INDEX_FILE_ATIME: + fEntry.SetAccessTime(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_MTIME: + fEntry.SetModifiedTime(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_CRTIME: + fEntry.SetCreationTime(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_ATIME_NANOS: + fEntry.SetAccessTimeNanos(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_MTIME_NANOS: + fEntry.SetModifiedTimeNanos(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_CRTIM_NANOS: + fEntry.SetCreationTimeNanos(value.unsignedInt); + return B_OK; + + case ATTRIBUTE_INDEX_FILE_ATTRIBUTE: + { + status_t error = _Notify(context); + if (error != B_OK) + return error; + + if (_handler != NULL) { + *_handler = new(std::nothrow) AttributeAttributeHandler( + &fEntry, value.string); + if (*_handler == NULL) + return B_NO_MEMORY; + return B_OK; + } else { + BPackageEntryAttribute attribute(value.string); + return context->packageContentHandler->HandleEntryAttribute( + &fEntry, &attribute); + } + } + + case ATTRIBUTE_INDEX_DATA: + { + if (_handler != NULL) { + return DataAttributeHandler::Create(context, &fEntry.Data(), + value, *_handler); + } + return DataAttributeHandler::InitData(context, &fEntry.Data(), + value); + } + + case ATTRIBUTE_INDEX_SYMLINK_PATH: + { + fEntry.SetSymlinkPath(value.string); + return B_OK; + } + } + + return AttributeHandler::HandleChildAttribute(context, type, typeIndex, + value, _handler); + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + // notify if not done yet + status_t error = _Notify(context); + + // notify done + if (error == B_OK) + error = context->packageContentHandler->HandleEntryDone(&fEntry); + else + context->packageContentHandler->HandleEntryDone(&fEntry); + + delete this; + return error; + } + +private: + status_t _Notify(AttributeHandlerContext* context) + { + if (fNotified) + return B_OK; + + fNotified = true; + return context->packageContentHandler->HandleEntry(&fEntry); + } + + status_t _SetFileType(AttributeHandlerContext* context, uint64 fileType) + { + switch (fileType) { + case B_HPKG_FILE_TYPE_FILE: + fEntry.SetType(S_IFREG); + fEntry.SetPermissions(B_HPKG_DEFAULT_FILE_PERMISSIONS); + break; + case B_HPKG_FILE_TYPE_DIRECTORY: + fEntry.SetType(S_IFDIR); + fEntry.SetPermissions(B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS); + break; + case B_HPKG_FILE_TYPE_SYMLINK: + fEntry.SetType(S_IFLNK); + fEntry.SetPermissions(B_HPKG_DEFAULT_SYMLINK_PERMISSIONS); + break; + default: + context->errorOutput->PrintError("Error: Invalid file type for " + "package entry (%llu)\n", fileType); + return B_BAD_DATA; + } + return B_OK; + } + +private: + BPackageEntry fEntry; + bool fNotified; +}; + + +struct PackageReaderImpl::RootAttributeHandler : AttributeHandler { + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { + if (typeIndex == ATTRIBUTE_INDEX_DIRECTORY_ENTRY) { +//TRACE("%*sentry \"%s\"\n", fLevel * 2, "", value.string); + if (_handler != NULL) { + return EntryAttributeHandler::Create(context, NULL, + value.string, *_handler); + } + return B_OK; + } + + return AttributeHandler::HandleChildAttribute(context, type, typeIndex, + value, _handler); + } +}; + + +struct PackageReaderImpl::LowLevelAttributeHandler : AttributeHandler { + LowLevelAttributeHandler() + : + fToken(NULL), + fAttributeName(NULL) + { + } + + LowLevelAttributeHandler(const char* attributeName, + const BPackageAttributeValue& value, void* token) + : + fToken(token), + fAttributeName(attributeName), + fValue(value) + { + } + + virtual status_t HandleChildAttribute(AttributeHandlerContext* context, + AttributeType* type, int8 typeIndex, const AttributeValue& value, + AttributeHandler** _handler) + { + // notify the content handler + void* token; + status_t error = context->lowLevelPackageContentHandler + ->HandleAttribute(type->name, value, fToken, token); + if (error != B_OK) + return error; + + // create a subhandler for the attribute, if it has children + if (_handler != NULL) { + *_handler = new(std::nothrow) LowLevelAttributeHandler(type->name, + value, token); + if (*_handler == NULL) { + context->lowLevelPackageContentHandler->HandleAttributeDone( + type->name, value, token); + return B_NO_MEMORY; + } + return B_OK; + } + + // no children -- just call the done hook + return context->lowLevelPackageContentHandler->HandleAttributeDone( + type->name, value, token); + } + + virtual status_t Delete(AttributeHandlerContext* context) + { + if (fAttributeName != NULL) { + return context->lowLevelPackageContentHandler->HandleAttributeDone( + fAttributeName, fValue, fToken); + } + + return B_OK; + } + +private: + void* fToken; + const char* fAttributeName; + AttributeValue fValue; +}; + + +// #pragma mark - PackageReaderImpl + + +inline PackageReaderImpl::AttributeHandler* +PackageReaderImpl::_CurrentAttributeHandler() const +{ + return fAttributeHandlerStack->Head(); +} + + +inline void +PackageReaderImpl::_PushAttributeHandler(AttributeHandler* handler) +{ + fAttributeHandlerStack->Add(handler); +} + + +inline PackageReaderImpl::AttributeHandler* +PackageReaderImpl::_PopAttributeHandler() +{ + return fAttributeHandlerStack->RemoveHead(); +} + + +PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput) + : + fErrorOutput(errorOutput), + fFD(-1), + fOwnsFD(false), + fTOCSection("TOC"), + fPackageAttributesSection("package attributes section"), + fCurrentSection(NULL), + fAttributeTypes(NULL), + fScratchBuffer(NULL), + fScratchBufferSize(0) +{ +} + + +PackageReaderImpl::~PackageReaderImpl() +{ + if (fOwnsFD && fFD >= 0) + close(fFD); + + delete[] fScratchBuffer; + delete[] fAttributeTypes; +} + + +status_t +PackageReaderImpl::Init(const char* fileName) +{ + // open file + int fd = open(fileName, O_RDONLY); + if (fd < 0) { + fErrorOutput->PrintError("Error: Failed to open package file \"%s\": " + "%s\n", fileName, strerror(errno)); + return errno; + } + + return Init(fd, true); +} + + +status_t +PackageReaderImpl::Init(int fd, bool keepFD) +{ + fFD = fd; + fOwnsFD = keepFD; + + // stat it + struct stat st; + if (fstat(fFD, &st) < 0) { + fErrorOutput->PrintError("Error: Failed to access package file: %s\n", + strerror(errno)); + return errno; + } + + // read the header + hpkg_header header; + status_t error = _ReadBuffer(0, &header, sizeof(header)); + if (error != B_OK) + return error; + + // check the header + + // magic + if (B_BENDIAN_TO_HOST_INT32(header.magic) != B_HPKG_MAGIC) { + fErrorOutput->PrintError("Error: Invalid package file: Invalid " + "magic\n"); + return B_BAD_DATA; + } + + // header size + fHeapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); + if ((size_t)fHeapOffset < sizeof(hpkg_header)) { + fErrorOutput->PrintError("Error: Invalid package file: Invalid header " + "size (%llu)\n", fHeapOffset); + return B_BAD_DATA; + } + + // version + if (B_BENDIAN_TO_HOST_INT16(header.version) != B_HPKG_VERSION) { + fErrorOutput->PrintError("Error: Invalid/unsupported package file " + "version (%d)\n", B_BENDIAN_TO_HOST_INT16(header.version)); + return B_BAD_DATA; + } + + // total size + fTotalSize = B_BENDIAN_TO_HOST_INT64(header.total_size); + if (fTotalSize != (uint64)st.st_size) { + fErrorOutput->PrintError("Error: Invalid package file: Total size in " + "header (%llu) doesn't agree with total file size (%lld)\n", + fTotalSize, st.st_size); + return B_BAD_DATA; + } + + // package attributes length and compression + fPackageAttributesSection.compression + = B_BENDIAN_TO_HOST_INT32(header.attributes_compression); + fPackageAttributesSection.compressedLength + = B_BENDIAN_TO_HOST_INT32(header.attributes_length_compressed); + fPackageAttributesSection.uncompressedLength + = B_BENDIAN_TO_HOST_INT32(header.attributes_length_uncompressed); + fPackageAttributesSection.stringsLength + = B_BENDIAN_TO_HOST_INT32(header.attributes_strings_length); + fPackageAttributesSection.stringsCount + = B_BENDIAN_TO_HOST_INT32(header.attributes_strings_count); + + if (const char* errorString = _CheckCompression( + fPackageAttributesSection)) { + fErrorOutput->PrintError("Error: Invalid package file: package " + "attributes section: %s\n", errorString); + return B_BAD_DATA; + } + + // TOC length and compression + fTOCSection.compression = B_BENDIAN_TO_HOST_INT32(header.toc_compression); + fTOCSection.compressedLength + = B_BENDIAN_TO_HOST_INT64(header.toc_length_compressed); + fTOCSection.uncompressedLength + = B_BENDIAN_TO_HOST_INT64(header.toc_length_uncompressed); + + if (const char* errorString = _CheckCompression(fTOCSection)) { + fErrorOutput->PrintError("Error: Invalid package file: TOC section: " + "%s\n", errorString); + return B_BAD_DATA; + } + + // TOC subsections + fTOCAttributeTypesLength + = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_length); + fTOCAttributeTypesCount + = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_count); + fTOCSection.stringsLength + = B_BENDIAN_TO_HOST_INT64(header.toc_strings_length); + fTOCSection.stringsCount + = B_BENDIAN_TO_HOST_INT64(header.toc_strings_count); + + if (fTOCAttributeTypesLength > fTOCSection.uncompressedLength + || fTOCSection.stringsLength + > fTOCSection.uncompressedLength - fTOCAttributeTypesLength + || fTOCAttributeTypesCount > fTOCAttributeTypesLength + || fTOCSection.stringsCount > fTOCSection.stringsLength) { + fErrorOutput->PrintError("Error: Invalid package file: Invalid TOC " + "subsections description\n"); + return B_BAD_DATA; + } + + // check whether the sections fit together + if (fPackageAttributesSection.compressedLength > fTotalSize + || fTOCSection.compressedLength + > fTotalSize - fPackageAttributesSection.compressedLength + || fHeapOffset + > fTotalSize - fPackageAttributesSection.compressedLength + - fTOCSection.compressedLength) { + fErrorOutput->PrintError("Error: Invalid package file: The sum of the " + "sections sizes is greater than the package size\n"); + return B_BAD_DATA; + } + + fPackageAttributesSection.offset + = fTotalSize - fPackageAttributesSection.compressedLength; + fTOCSection.offset = fPackageAttributesSection.offset + - fTOCSection.compressedLength; + fHeapSize = fTOCSection.offset - fHeapOffset; + + // TOC size sanity check + if (fTOCSection.uncompressedLength > kMaxTOCSize) { + fErrorOutput->PrintError("Error: Package file TOC section size " + "is %llu bytes. This is beyond the reader's sanity limit\n", + fTOCSection.uncompressedLength); + return B_UNSUPPORTED; + } + + // package attributes size sanity check + if (fPackageAttributesSection.uncompressedLength + > kMaxPackageAttributesSize) { + fErrorOutput->PrintError( + "Error: Package file package attributes section size " + "is %llu bytes. This is beyond the reader's sanity limit\n", + fPackageAttributesSection.uncompressedLength); + return B_UNSUPPORTED; + } + + // allocate a scratch buffer + fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; + if (fScratchBuffer == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + fScratchBufferSize = kScratchBufferSize; + + // read in the complete TOC + fTOCSection.data + = new(std::nothrow) uint8[fTOCSection.uncompressedLength]; + if (fTOCSection.data == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + error = _ReadCompressedBuffer(fTOCSection); + if (error != B_OK) + return error; + + // read in the complete package attributes section + fPackageAttributesSection.data + = new(std::nothrow) uint8[fPackageAttributesSection.uncompressedLength]; + if (fPackageAttributesSection.data == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + error = _ReadCompressedBuffer(fPackageAttributesSection); + if (error != B_OK) + return error; + + // start parsing the TOC + fCurrentSection = &fTOCSection; + fCurrentSection->currentOffset = 0; + + // attribute types + error = _ParseTOCAttributeTypes(); + if (error != B_OK) + return error; + fCurrentSection->currentOffset += fTOCAttributeTypesLength; + + // strings + error = _ParseStrings(); + if (error != B_OK) + return error; + fCurrentSection->currentOffset += fCurrentSection->stringsLength; + + // parse strings from package attributes section + fCurrentSection = &fPackageAttributesSection; + fCurrentSection->currentOffset = 0; + + // strings + error = _ParseStrings(); + if (error != B_OK) + return error; + fCurrentSection->currentOffset += fCurrentSection->stringsLength; + + fCurrentSection = NULL; + + return B_OK; +} + + +status_t +PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler) +{ + AttributeHandlerContext context(fErrorOutput, contentHandler); + RootAttributeHandler rootAttributeHandler; + return _ParseContent(&context, &rootAttributeHandler); +} + + +status_t +PackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler) +{ + AttributeHandlerContext context(fErrorOutput, contentHandler); + LowLevelAttributeHandler rootAttributeHandler; + return _ParseContent(&context, &rootAttributeHandler); +} + + +const char* +PackageReaderImpl::_CheckCompression(const SectionInfo& section) const +{ + switch (section.compression) { + case B_HPKG_COMPRESSION_NONE: + if (section.compressedLength != section.uncompressedLength) { + return "Uncompressed, but compressed and uncompressed length " + "don't match"; + } + return NULL; + + case B_HPKG_COMPRESSION_ZLIB: + if (section.compressedLength >= section.uncompressedLength) { + return "Compressed, but compressed length is not less than " + "uncompressed length"; + } + return NULL; + + default: + return "Invalid compression algorithm ID"; + } +} + + +status_t +PackageReaderImpl::_ParseTOCAttributeTypes() +{ + // allocate table + fAttributeTypes = new(std::nothrow) AttributeTypeReference[ + fTOCAttributeTypesCount]; + if (fAttributeTypes == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + + // parse the section and fill the table + uint8* position = fTOCSection.data + fTOCSection.currentOffset; + uint8* sectionEnd = position + fTOCAttributeTypesLength; + uint32 index = 0; + while (true) { + if (position >= sectionEnd) { + fErrorOutput->PrintError("Error: Malformed TOC attribute types " + "section\n"); + return B_BAD_DATA; + } + + AttributeType* type = (AttributeType*)position; + + if (type->type == 0) { + if (position + 1 != sectionEnd) { + fErrorOutput->PrintError("Error: Excess bytes in TOC attribute " + "types section\n"); + return B_BAD_DATA; + } + + if (index != fTOCAttributeTypesCount) { + fErrorOutput->PrintError("Error: Invalid TOC attribute types " + "section: Less types than specified in the header\n"); + return B_BAD_DATA; + } + + return B_OK; + } + + if (index >= fTOCAttributeTypesCount) { + fErrorOutput->PrintError("Error: Invalid TOC attribute types " + "section: More types than specified in the header\n"); + return B_BAD_DATA; + } + + size_t nameLength = strnlen(type->name, + (char*)sectionEnd - type->name); + position = (uint8*)type->name + nameLength + 1; + fAttributeTypes[index].type = type; + fAttributeTypes[index].standardIndex = _GetStandardIndex(type); + index++; + } +} + + +status_t +PackageReaderImpl::_ParseStrings() +{ + // allocate table + fCurrentSection->strings + = new(std::nothrow) char*[fCurrentSection->stringsCount]; + if (fCurrentSection->strings == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + + // parse the section and fill the table + char* position + = (char*)fCurrentSection->data + fCurrentSection->currentOffset; + char* sectionEnd = position + fCurrentSection->stringsLength; + uint32 index = 0; + while (true) { + if (position >= sectionEnd) { + fErrorOutput->PrintError("Error: Malformed %s strings section\n", + fCurrentSection->name); + return B_BAD_DATA; + } + + size_t stringLength = strnlen(position, (char*)sectionEnd - position); + + if (stringLength == 0) { + if (position + 1 != sectionEnd) { + fErrorOutput->PrintError( + "Error: %ld excess bytes in %s strings section\n", + sectionEnd - (position + 1), fCurrentSection->name); + return B_BAD_DATA; + } + + if (index != fCurrentSection->stringsCount) { + fErrorOutput->PrintError("Error: Invalid %s strings section: " + "Less strings (%lld) than specified in the header (%lld)\n", + fCurrentSection->name, index, + fCurrentSection->stringsCount); + return B_BAD_DATA; + } + + return B_OK; + } + + if (index >= fCurrentSection->stringsCount) { + fErrorOutput->PrintError("Error: Invalid %s strings section: " + "More strings (%lld) than specified in the header (%lld)\n", + fCurrentSection->name, index, fCurrentSection->stringsCount); + return B_BAD_DATA; + } + + fCurrentSection->strings[index++] = position; + position += stringLength + 1; + } +} + + +status_t +PackageReaderImpl::_ParseContent(AttributeHandlerContext* context, + AttributeHandler* rootAttributeHandler) +{ + // parse the TOC + fCurrentSection = &fTOCSection; + fTOCSection.currentOffset = fTOCAttributeTypesLength + + fTOCSection.stringsLength; + + // prepare attribute handler context + context->heapOffset = fHeapOffset; + context->heapSize = fHeapSize; + + // init the attribute handler stack + AttributeHandlerList attributeHandlerStack; + fAttributeHandlerStack = &attributeHandlerStack; + fAttributeHandlerStack->Add(rootAttributeHandler); + rootAttributeHandler->SetLevel(0); + + status_t error = _ParseAttributeTree(context); + if (error == B_OK) { + if (fTOCSection.currentOffset < fTOCSection.uncompressedLength) { + fErrorOutput->PrintError("Error: %llu excess byte(s) in TOC " + "section\n", + fTOCSection.uncompressedLength - fTOCSection.currentOffset); + error = B_BAD_DATA; + } + } + + // parse package attributes + fCurrentSection = &fPackageAttributesSection; + if (error == B_OK) + error = _ParsePackageAttributes(&context); + if (error == B_OK) { + if (fPackageAttributesSection.currentOffset + < fPackageAttributesSection.uncompressedLength) { + fErrorOutput->PrintError("Error: %llu excess byte(s) in package " + "attributes section\n", + fPackageAttributesSection.uncompressedLength + - fPackageAttributesSectionSection.currentOffset); + error = B_BAD_DATA; + } + } + + fCurrentSection = NULL; + + // clean up on error + if (error != B_OK) { + context->ErrorOccurred(); + while (AttributeHandler* handler = _PopAttributeHandler()) { + if (handler != rootAttributeHandler) + handler->Delete(context); + } + return error; + } + + return B_OK; +} + + +status_t +PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context) +{ + int level = 0; + + while (true) { + uint64 tag; + status_t error = _ReadUnsignedLEB128(tag); + if (error != B_OK) + return error; + + if (tag == 0) { + AttributeHandler* handler = _PopAttributeHandler(); + if (level-- == 0) + return B_OK; + + error = handler->Delete(context); + if (error != B_OK) + return error; + + continue; + } + + // get the type + uint64 typeIndex = HPKG_ATTRIBUTE_TAG_INDEX(tag); + if (typeIndex >= fTOCAttributeTypesCount) { + fErrorOutput->PrintError("Error: Invalid TOC section: " + "Invalid attribute type index\n"); + return B_BAD_DATA; + } + AttributeTypeReference* type = fAttributeTypes + typeIndex; + + // get the value + AttributeValue value; + error = _ReadAttributeValue(type->type->type, + HPKG_ATTRIBUTE_TAG_ENCODING(tag), value); + if (error != B_OK) + return error; + + bool hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); + AttributeHandler* childHandler = NULL; + error = _CurrentAttributeHandler()->HandleChildAttribute(context, + type->type, type->standardIndex, value, + hasChildren ? &childHandler : NULL); + if (error != B_OK) + return error; + + // parse children + if (hasChildren) { + // create an ignore handler, if necessary + if (childHandler == NULL) { + childHandler = new(std::nothrow) IgnoreAttributeHandler; + if (childHandler == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + } + + childHandler->SetLevel(level); + _PushAttributeHandler(childHandler); + level++; + } + } +} + + +status_t +PackageReaderImpl::_ParsePackageAttributes(AttributeHandlerContext* context) +{ + while (true) { + uint8 id; + AttributeValue attributeValue; + bool hasChildren; + uint64 tag; + BPackageInfoAttributeValue handlerValue; + + status_t error + = _ReadPackageAttribute(id, attributeValue, &hasChildren, &tag); + if (error != B_OK) + return error; + + if (tag == 0) { + return + context->packageContentHandler->HandlePackageAttributesDone(); + } + + switch (id) { + case HPKG_PACKAGE_ATTRIBUTE_NAME: + handlerValue.SetTo(B_PACKAGE_INFO_NAME, attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_SUMMARY: + handlerValue.SetTo(B_PACKAGE_INFO_SUMMARY, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION: + handlerValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_VENDOR: + handlerValue.SetTo(B_PACKAGE_INFO_VENDOR, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_PACKAGER: + handlerValue.SetTo(B_PACKAGE_INFO_PACKAGER, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_FLAGS: + handlerValue.SetTo(B_PACKAGE_INFO_FLAGS, + (uint32)attributeValue.unsignedInt); + break; + + case HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE: + if (attributeValue.unsignedInt + >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { + fErrorOutput->PrintError( + "Error: Invalid package attribute section: " + "Invalid package architecture %lld encountered\n", + attributeValue.unsignedInt); + return B_BAD_DATA; + } + handlerValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, + (uint8)attributeValue.unsignedInt); + break; + + case HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR: + error = _ParsePackageVersion(handlerValue.version, + attributeValue.string); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_VERSION; + break; + + case HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT: + handlerValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_LICENSE: + handlerValue.SetTo(B_PACKAGE_INFO_LICENSES, + attributeValue.string); + break; + + case HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE: + error = _ParsePackageProvides(handlerValue.resolvable, + (BPackageResolvableType)attributeValue.unsignedInt); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_PROVIDES; + break; + + case HPKG_PACKAGE_ATTRIBUTE_REQUIRES: + error = _ParsePackageResolvableExpression( + handlerValue.resolvableExpression, attributeValue.string, + hasChildren); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_REQUIRES; + break; + + case HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS: + error = _ParsePackageResolvableExpression( + handlerValue.resolvableExpression, attributeValue.string, + hasChildren); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_SUPPLEMENTS; + break; + + case HPKG_PACKAGE_ATTRIBUTE_CONFLICTS: + error = _ParsePackageResolvableExpression( + handlerValue.resolvableExpression, attributeValue.string, + hasChildren); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_CONFLICTS; + break; + + case HPKG_PACKAGE_ATTRIBUTE_FRESHENS: + error = _ParsePackageResolvableExpression( + handlerValue.resolvableExpression, attributeValue.string, + hasChildren); + if (error != B_OK) + return error; + handlerValue.attributeIndex = B_PACKAGE_INFO_FRESHENS; + break; + + case HPKG_PACKAGE_ATTRIBUTE_REPLACES: + handlerValue.SetTo(B_PACKAGE_INFO_REPLACES, + attributeValue.string); + break; + + default: + fErrorOutput->PrintError( + "Error: Invalid package attribute section: unexpected " + "package attribute id %d encountered\n", id); + return B_BAD_DATA; + } + + error = context->packageContentHandler->HandlePackageAttribute( + handlerValue); + if (error != B_OK) + return error; + } +} + + +status_t +PackageReaderImpl::_ParsePackageVersion(BPackageVersionData& _version, + const char* major) +{ + uint8 id; + AttributeValue value; + status_t error; + + _version.major = NULL; + _version.minor = NULL; + _version.micro = NULL; + _version.release = 0; + + // major (may have been read already) + if (major == NULL) { + error = _ReadPackageAttribute(id, value); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package version, expected major\n"); + return B_BAD_DATA; + } + major = value.string; + } + _version.major = major; + + // minor + error = _ReadPackageAttribute(id, value); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package version, expected minor\n"); + return B_BAD_DATA; + } + _version.minor = value.string; + + // micro + error = _ReadPackageAttribute(id, value); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_MICRO) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package version, expected micro\n"); + return B_BAD_DATA; + } + _version.micro = value.string; + + // release + error = _ReadPackageAttribute(id, value); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_VERSION_RELEASE) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package version, expected release\n"); + return B_BAD_DATA; + } + _version.release = (uint8)value.unsignedInt; + + return B_OK; +} + + +status_t +PackageReaderImpl::_ParsePackageProvides(BPackageResolvableData& _resolvable, + BPackageResolvableType providesType) +{ + uint8 id; + AttributeValue value; + bool hasChildren; + + if (providesType >= B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT) { + fErrorOutput->PrintError("Error: Invalid package attribute section: " + "Invalid package provides type %lld encountered\n", providesType); + return B_BAD_DATA; + } + _resolvable.type = providesType; + _resolvable.haveVersion = false; + + // provides name + status_t error = _ReadPackageAttribute(id, value, &hasChildren); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_PROVIDES) { + fErrorOutput->PrintError("Error: Invalid package attribute section: " + "Invalid package provides, expected name of resolvable\n"); + return B_BAD_DATA; + } + _resolvable.name = value.string; + + // there may be a version added as child + if (hasChildren) { + error = _ParsePackageVersion(_resolvable.version); + if (error != B_OK) + return error; + + _resolvable.haveVersion = true; + + uint64 tag; + if ((error = _ReadUnsignedLEB128(tag)) != B_OK) + return error; + if (tag != 0) { + fErrorOutput->PrintError("Error: Invalid package attribute " + "section: Invalid package provides, expected end-tag\n"); + return B_BAD_DATA; + } + } + + return B_OK; +} + + +status_t +PackageReaderImpl::_ParsePackageResolvableExpression( + BPackageResolvableExpressionData& _resolvableExpression, + const char* resolvableName, bool hasChildren) +{ + _resolvableExpression.name = resolvableName; + _resolvableExpression.haveOpAndVersion = false; + + // there may be an operator and a version added as child + if (hasChildren) { + // resolvable-expression operator + uint8 id; + AttributeValue value; + status_t error = _ReadPackageAttribute(id, value); + if (error != B_OK) + return error; + if (id != HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package resolvable expression, expected operator\n"); + return B_BAD_DATA; + } + + if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package resolvable operator %lld encountered\n", + value.unsignedInt); + return B_BAD_DATA; + } + + _resolvableExpression.op + = (BPackageResolvableOperator)value.unsignedInt; + + error = _ParsePackageVersion(_resolvableExpression.version); + if (error != B_OK) + return error; + + _resolvableExpression.haveOpAndVersion = true; + + uint64 tag; + if ((error = _ReadUnsignedLEB128(tag)) != B_OK) + return error; + if (tag != 0) { + fErrorOutput->PrintError("Error: Invalid package attribute section:" + " Invalid package resolvable expression, expected end-tag\n"); + return B_BAD_DATA; + } + } + + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadPackageAttribute(uint8& _id, AttributeValue& _value, + bool* _hasChildren, uint64* _tag) +{ + uint64 tag; + status_t error = _ReadUnsignedLEB128(tag); + if (error != B_OK) + return error; + + if (tag != 0) { + // get the type + uint16 type = HPKG_PACKAGE_ATTRIBUTE_TAG_TYPE(tag); + if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { + fErrorOutput->PrintError("Error: Invalid package attribute " + "section: attribute type %d not supported!\n", type); + return B_BAD_DATA; + } + + // get the value + error = _ReadAttributeValue(type, + HPKG_PACKAGE_ATTRIBUTE_TAG_ENCODING(tag), _value); + if (error != B_OK) + return error; + + _id = HPKG_PACKAGE_ATTRIBUTE_TAG_ID(tag); + if (_id >= HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT) { + fErrorOutput->PrintError("Error: Invalid package attribute section: " + "attribute id %d not supported!\n", _id); + return B_BAD_DATA; + } + } + + if (_hasChildren != NULL) + *_hasChildren = HPKG_PACKAGE_ATTRIBUTE_TAG_HAS_CHILDREN(tag); + if (_tag != NULL) + *_tag = tag; + + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadAttributeValue(uint8 type, uint8 encoding, + AttributeValue& _value) +{ + switch (type) { + case B_HPKG_ATTRIBUTE_TYPE_INT: + case B_HPKG_ATTRIBUTE_TYPE_UINT: + { + uint64 intValue; + status_t error; + + switch (encoding) { + case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: + { + uint8 value; + error = _Read(value); + intValue = value; + break; + } + case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: + { + uint16 value; + error = _Read(value); + intValue = B_BENDIAN_TO_HOST_INT16(value); + break; + } + case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: + { + uint32 value; + error = _Read(value); + intValue = B_BENDIAN_TO_HOST_INT32(value); + break; + } + case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: + { + uint64 value; + error = _Read(value); + intValue = B_BENDIAN_TO_HOST_INT64(value); + break; + } + default: + { + fErrorOutput->PrintError("Error: Invalid %s section: " + "invalid encoding %d for int value type %d\n", + fCurrentSection->name, encoding, type); + return B_BAD_VALUE; + } + } + + if (error != B_OK) + return error; + + if (type == B_HPKG_ATTRIBUTE_TYPE_INT) + _value.SetTo((int64)intValue); + else + _value.SetTo(intValue); + + return B_OK; + } + + case B_HPKG_ATTRIBUTE_TYPE_STRING: + { + if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { + uint64 index; + status_t error = _ReadUnsignedLEB128(index); + if (error != B_OK) + return error; + + if (index > fCurrentSection->stringsCount) { + fErrorOutput->PrintError("Error: Invalid %s section: " + "string reference (%lld) out of bounds (%lld)\n", + fCurrentSection->name, index, + fCurrentSection->stringsCount); + return B_BAD_DATA; + } + + _value.SetTo(fCurrentSection->strings[index]); + } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { + const char* string; + status_t error = _ReadString(string); + if (error != B_OK) + return error; + + _value.SetTo(string); + } else { + fErrorOutput->PrintError("Error: Invalid %s section: invalid " + "string encoding (%u)\n", fCurrentSection->name, encoding); + return B_BAD_DATA; + } + + return B_OK; + } + + case B_HPKG_ATTRIBUTE_TYPE_RAW: + { + uint64 size; + status_t error = _ReadUnsignedLEB128(size); + if (error != B_OK) + return error; + + if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP) { + uint64 offset; + error = _ReadUnsignedLEB128(offset); + if (error != B_OK) + return error; + + if (offset > fHeapSize || size > fHeapSize - offset) { + fErrorOutput->PrintError("Error: Invalid %s section: " + "invalid data reference\n", fCurrentSection->name); + return B_BAD_DATA; + } + + _value.SetToData(size, fHeapOffset + offset); + } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE) { + if (size > B_HPKG_MAX_INLINE_DATA_SIZE) { + fErrorOutput->PrintError("Error: Invalid %s section: " + "inline data too long\n", fCurrentSection->name); + return B_BAD_DATA; + } + + const void* buffer; + error = _GetTOCBuffer(size, buffer); + if (error != B_OK) + return error; + _value.SetToData(size, buffer); + } else { + fErrorOutput->PrintError("Error: Invalid %s section: invalid " + "raw encoding (%u)\n", fCurrentSection->name, encoding); + return B_BAD_DATA; + } + + return B_OK; + } + + default: + fErrorOutput->PrintError("Error: Invalid %s section: invalid " + "value type: %d\n", fCurrentSection->name, type); + return B_BAD_DATA; + } +} + + +status_t +PackageReaderImpl::_ReadUnsignedLEB128(uint64& _value) +{ + uint64 result = 0; + int shift = 0; + while (true) { + uint8 byte; + status_t error = _Read(byte); + if (error != B_OK) + return error; + + result |= uint64(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + + _value = result; + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadString(const char*& _string, size_t* _stringLength) +{ + const char* string + = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; + size_t stringLength = strnlen(string, + fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); + + if (stringLength + == fCurrentSection->uncompressedLength + - fCurrentSection->currentOffset) { + fErrorOutput->PrintError( + "_ReadString(): string extends beyond %s end\n", + fCurrentSection->name); + return B_BAD_DATA; + } + + _string = string; + if (_stringLength != NULL) + *_stringLength = stringLength; + + fCurrentSection->currentOffset += stringLength + 1; + return B_OK; +} + + +status_t +PackageReaderImpl::_GetTOCBuffer(size_t size, const void*& _buffer) +{ + if (size > fTOCSection.uncompressedLength - fTOCSection.currentOffset) { + fErrorOutput->PrintError("_GetTOCBuffer(%lu): read beyond TOC end\n", + size); + return B_BAD_DATA; + } + + _buffer = fTOCSection.data + fTOCSection.currentOffset; + fTOCSection.currentOffset += size; + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadSectionBuffer(void* buffer, size_t size) +{ + if (size > fCurrentSection->uncompressedLength + - fCurrentSection->currentOffset) { + fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n", + size, fCurrentSection->name); + return B_BAD_DATA; + } + + memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, + size); + fCurrentSection->currentOffset += size; + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadBuffer(off_t offset, void* buffer, size_t size) +{ + ssize_t bytesRead = pread(fFD, buffer, size, offset); + if (bytesRead < 0) { + fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " + "%s\n", buffer, size, strerror(errno)); + return errno; + } + if ((size_t)bytesRead != size) { + fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " + "data\n", buffer, size); + return B_ERROR; + } + + return B_OK; +} + + +status_t +PackageReaderImpl::_ReadCompressedBuffer(const SectionInfo& section) +{ + uint32 compressedSize = section.compressedLength; + uint64 offset = section.offset; + + switch (section.compression) { + case B_HPKG_COMPRESSION_NONE: + return _ReadBuffer(offset, section.data, compressedSize); + + case B_HPKG_COMPRESSION_ZLIB: + { + // init the decompressor + BBufferDataOutput bufferOutput(section.data, + section.uncompressedLength); + ZlibDecompressor decompressor(&bufferOutput); + status_t error = decompressor.Init(); + if (error != B_OK) + return error; + + while (compressedSize > 0) { + // read compressed buffer + size_t toRead = std::min(compressedSize, fScratchBufferSize); + error = _ReadBuffer(offset, fScratchBuffer, toRead); + if (error != B_OK) + return error; + + // uncompress + error = decompressor.DecompressNext(fScratchBuffer, toRead); + if (error != B_OK) + return error; + + compressedSize -= toRead; + offset += toRead; + } + + error = decompressor.Finish(); + if (error != B_OK) + return error; + + // verify that all data have been read + if (bufferOutput.BytesWritten() != section.uncompressedLength) { + fErrorOutput->PrintError("Error: Missing bytes in uncompressed " + "buffer!\n"); + return B_BAD_DATA; + } + + return B_OK; + } + + default: + return B_BAD_DATA; + } +} + + +/*static*/ int8 +PackageReaderImpl::_GetStandardIndex(const AttributeType* type) +{ + // TODO: Building a hash table once would make the loopup faster. + for (int32 i = 0; kStandardAttributeIndices[i].name != NULL; i++) { + if (type->type == kStandardAttributeIndices[i].type + && strcmp(kStandardAttributeIndices[i].name, type->name) == 0) { + return i; + } + } + + return -1; +} + + +} // namespace BPrivate + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/RepositoryWriterImpl.cpp b/src/kits/package/hpkg/RepositoryWriterImpl.cpp index 607a9bda9f..b46d1e6d5b 100644 --- a/src/kits/package/hpkg/RepositoryWriterImpl.cpp +++ b/src/kits/package/hpkg/RepositoryWriterImpl.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -122,7 +122,7 @@ status_t RepositoryWriterImpl::HandlePackageAttribute( const BPackageInfoAttributeValue& value) { - switch (value.attributeIndex) { + switch (value.attributeID) { case B_PACKAGE_INFO_NAME: fPackageInfo.SetName(value.string); break; @@ -191,7 +191,7 @@ RepositoryWriterImpl::HandlePackageAttribute( default: fListener->PrintError( "Invalid package attribute section: unexpected package " - "attribute index %d encountered\n", value.attributeIndex); + "attribute id %d encountered\n", value.attributeID); return B_BAD_DATA; } diff --git a/src/kits/package/hpkg/WriterImplBase.cpp b/src/kits/package/hpkg/WriterImplBase.cpp index 7758a031b3..27e47bc608 100644 --- a/src/kits/package/hpkg/WriterImplBase.cpp +++ b/src/kits/package/hpkg/WriterImplBase.cpp @@ -18,7 +18,7 @@ #include -#include +#include #include #include @@ -276,7 +276,7 @@ WriterImplBase::ZlibDataWriter::WriteData(const void* buffer, size_t size) // #pragma mark - PackageAttribute -WriterImplBase::PackageAttribute::PackageAttribute(HPKGPackageAttributeID id_, +WriterImplBase::PackageAttribute::PackageAttribute(BHPKGAttributeID id_, uint8 type_, uint8 encoding_) : id(id_) @@ -357,21 +357,22 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, const BPackageInfo& packageInfo) { // name - PackageAttribute* name = new PackageAttribute(HPKG_PACKAGE_ATTRIBUTE_NAME, - B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); + PackageAttribute* name = new PackageAttribute( + B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); name->string = fPackageStringCache.Get(packageInfo.Name().String()); attributeList.Add(name); // summary PackageAttribute* summary = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_SUMMARY, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); summary->string = fPackageStringCache.Get(packageInfo.Summary().String()); attributeList.Add(summary); // description PackageAttribute* description = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); description->string = fPackageStringCache.Get(packageInfo.Description().String()); @@ -379,28 +380,28 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, // vendor PackageAttribute* vendor = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_VENDOR, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); vendor->string = fPackageStringCache.Get(packageInfo.Vendor().String()); attributeList.Add(vendor); // packager PackageAttribute* packager = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_PACKAGER, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); packager->string = fPackageStringCache.Get(packageInfo.Packager().String()); attributeList.Add(packager); // flags PackageAttribute* flags = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT, + B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT); flags->unsignedInt = packageInfo.Flags(); attributeList.Add(flags); // architecture PackageAttribute* architecture = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT, + B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); architecture->unsignedInt = packageInfo.Architecture(); attributeList.Add(architecture); @@ -412,7 +413,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, const BObjectList& copyrightList = packageInfo.CopyrightList(); for (int i = 0; i < copyrightList.CountItems(); ++i) { PackageAttribute* copyright = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); copyright->string = fPackageStringCache.Get(copyrightList.ItemAt(i)->String()); @@ -423,7 +424,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, const BObjectList& licenseList = packageInfo.LicenseList(); for (int i = 0; i < licenseList.CountItems(); ++i) { PackageAttribute* license = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_LICENSE, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); license->string = fPackageStringCache.Get(licenseList.ItemAt(i)->String()); @@ -437,43 +438,43 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, BPackageResolvable* resolvable = providesList.ItemAt(i); bool hasVersion = resolvable->Version().InitCheck() == B_OK; - PackageAttribute* providesType = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT, - B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); - providesType->unsignedInt = resolvable->Type(); - attributeList.Add(providesType); - PackageAttribute* provides = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); provides->string = fPackageStringCache.Get(resolvable->Name().String()); attributeList.Add(provides); + PackageAttribute* providesType = new PackageAttribute( + B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE, + B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); + providesType->unsignedInt = resolvable->Type(); + provides->children.Add(providesType); + if (hasVersion) RegisterPackageVersion(provides->children, resolvable->Version()); } // requires list RegisterPackageResolvableExpressionList(attributeList, - packageInfo.RequiresList(), HPKG_PACKAGE_ATTRIBUTE_REQUIRES); + packageInfo.RequiresList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES); // supplements list RegisterPackageResolvableExpressionList(attributeList, - packageInfo.SupplementsList(), HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS); + packageInfo.SupplementsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS); // conflicts list RegisterPackageResolvableExpressionList(attributeList, - packageInfo.ConflictsList(), HPKG_PACKAGE_ATTRIBUTE_CONFLICTS); + packageInfo.ConflictsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS); // freshens list RegisterPackageResolvableExpressionList(attributeList, - packageInfo.FreshensList(), HPKG_PACKAGE_ATTRIBUTE_FRESHENS); + packageInfo.FreshensList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS); // replaces list const BObjectList& replacesList = packageInfo.ReplacesList(); for (int i = 0; i < replacesList.CountItems(); ++i) { PackageAttribute* replaces = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_REPLACES, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); replaces->string = fPackageStringCache.Get(replacesList.ItemAt(i)->String()); @@ -483,7 +484,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, // checksum (optional, only exists in repositories) if (packageInfo.Checksum().Length() > 0) { PackageAttribute* checksum = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_CHECKSUM, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); checksum->string = fPackageStringCache.Get(packageInfo.Checksum().String()); @@ -497,28 +498,38 @@ WriterImplBase::RegisterPackageVersion(PackageAttributeList& attributeList, const BPackageVersion& version) { PackageAttribute* versionMajor = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); versionMajor->string = fPackageStringCache.Get(version.Major().String()); attributeList.Add(versionMajor); - PackageAttribute* versionMinor = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR, B_HPKG_ATTRIBUTE_TYPE_STRING, - B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); - versionMinor->string = fPackageStringCache.Get(version.Minor().String()); - attributeList.Add(versionMinor); + if (version.Minor().Length() > 0) { + PackageAttribute* versionMinor = new PackageAttribute( + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR, + B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); + versionMinor->string + = fPackageStringCache.Get(version.Minor().String()); + versionMajor->children.Add(versionMinor); - PackageAttribute* versionMicro = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_VERSION_MICRO, B_HPKG_ATTRIBUTE_TYPE_STRING, - B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); - versionMicro->string = fPackageStringCache.Get(version.Micro().String()); - attributeList.Add(versionMicro); + if (version.Micro().Length() > 0) { + PackageAttribute* versionMicro = new PackageAttribute( + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO, + B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); + versionMicro->string + = fPackageStringCache.Get(version.Micro().String()); + versionMajor->children.Add(versionMicro); + } + } - PackageAttribute* versionRelease = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_VERSION_RELEASE, B_HPKG_ATTRIBUTE_TYPE_UINT, - B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); - versionRelease->unsignedInt = version.Release(); - attributeList.Add(versionRelease); + if (version.Release() != 0) { + PackageAttribute* versionRelease = new PackageAttribute( + B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_RELEASE, + B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); + versionRelease->unsignedInt = version.Release(); + versionMajor->children.Add(versionRelease); + } } @@ -531,15 +542,15 @@ WriterImplBase::RegisterPackageResolvableExpressionList( BPackageResolvableExpression* resolvableExpr = expressionList.ItemAt(i); bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK; - PackageAttribute* name = new PackageAttribute( - (HPKGPackageAttributeID)id, B_HPKG_ATTRIBUTE_TYPE_STRING, + PackageAttribute* name = new PackageAttribute((BHPKGAttributeID)id, + B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); name->string = fPackageStringCache.Get(resolvableExpr->Name().String()); attributeList.Add(name); if (hasVersion) { PackageAttribute* op = new PackageAttribute( - HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR, + B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); op->unsignedInt = resolvableExpr->Operator(); @@ -717,7 +728,7 @@ WriterImplBase::_WritePackageAttributes( uint8 encoding = attribute->ApplicableEncoding(); // write tag - WriteUnsignedLEB128(HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( + WriteUnsignedLEB128(HPKG_ATTRIBUTE_TAG_COMPOSE( attribute->id, attribute->type, encoding, !attribute->children.IsEmpty()));