From 6f0278cdc9a22a1e22c3ac3f480beffd6bb5fcff Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Fri, 4 Feb 2011 17:43:07 +0000 Subject: [PATCH] Implemented reading of package info attributes from hpkg file * added kernel-compatible datatypes for reading package info attribute values (PackageInfoAttributeValue.h) - these will be used at a later stage by the package-fs to transport those attributes to userland when asked to do so (by ioctl) * implemented parsing of package info attributes in PackageReaderImpl * added support for compressed package attribute section to PackageReaderImpl * completed the writing of package info attributes in PackageWriterImpl and fixed a couple of bugs exposed by parsing * adjusted 'package list' to show the package info attributes as they are found git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40354 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/package/PackageArchitecture.h | 24 + headers/os/package/PackageInfo.h | 40 +- headers/os/package/PackageInfoAttributes.h | 44 ++ headers/os/package/PackageResolvable.h | 18 +- .../os/package/PackageResolvableOperator.h | 27 ++ headers/os/package/PackageResolvableType.h | 26 ++ headers/os/package/hpkg/HPKGDefs.h | 32 +- .../os/package/hpkg/PackageContentHandler.h | 5 + .../package/hpkg/PackageInfoAttributeValue.h | 95 ++++ .../private/package/hpkg/PackageReaderImpl.h | 35 +- .../private/package/hpkg/PackageWriterImpl.h | 4 + headers/private/package/hpkg/haiku_package.h | 4 +- .../kernel/file_systems/packagefs/Volume.cpp | 7 + src/bin/package/command_extract.cpp | 6 + src/bin/package/command_list.cpp | 123 +++++ src/kits/package/hpkg/PackageReaderImpl.cpp | 429 +++++++++++++++++- src/kits/package/hpkg/PackageWriterImpl.cpp | 67 ++- 17 files changed, 910 insertions(+), 76 deletions(-) create mode 100644 headers/os/package/PackageArchitecture.h create mode 100644 headers/os/package/PackageInfoAttributes.h create mode 100644 headers/os/package/PackageResolvableOperator.h create mode 100644 headers/os/package/PackageResolvableType.h create mode 100644 headers/os/package/hpkg/PackageInfoAttributeValue.h diff --git a/headers/os/package/PackageArchitecture.h b/headers/os/package/PackageArchitecture.h new file mode 100644 index 0000000000..7c71c6f8b6 --- /dev/null +++ b/headers/os/package/PackageArchitecture.h @@ -0,0 +1,24 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__PACKAGE_ARCHITECTURE_H_ +#define _PACKAGE__PACKAGE_ARCHITECTURE_H_ + + +namespace BPackageKit { + + +enum BPackageArchitecture { + B_PACKAGE_ARCHITECTURE_ANY = 0, + B_PACKAGE_ARCHITECTURE_X86, + B_PACKAGE_ARCHITECTURE_X86_GCC2, + // + B_PACKAGE_ARCHITECTURE_ENUM_COUNT, +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__PACKAGE_ARCHITECTURE_H_ diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h index bfcc3ae6d4..b8be176324 100644 --- a/headers/os/package/PackageInfo.h +++ b/headers/os/package/PackageInfo.h @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #include @@ -20,44 +22,6 @@ class BEntry; namespace BPackageKit { -enum BPackageInfoIndex { - B_PACKAGE_INFO_NAME = 0, - B_PACKAGE_INFO_SUMMARY, // single line - B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible - B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project" - B_PACKAGE_INFO_PACKAGER, // e-mail address preferred - B_PACKAGE_INFO_ARCHITECTURE, - B_PACKAGE_INFO_VERSION, // [.[.]] - B_PACKAGE_INFO_COPYRIGHTS, // list - B_PACKAGE_INFO_LICENSES, // list - B_PACKAGE_INFO_PROVIDES, // list of resolvables this package provides, - // each optionally giving a version - B_PACKAGE_INFO_REQUIRES, // list of resolvables required by this package, - // each optionally specifying a version relation - // (e.g. libssl.so >= 0.9.8) - B_PACKAGE_INFO_SUPPLEMENTS, // list of resolvables that are supplemented - // by this package, i.e. this package marks - // itself as an extension to other packages - B_PACKAGE_INFO_CONFLICTS, // list of resolvables that inhibit installation - // of this package - B_PACKAGE_INFO_REPLACES, // list of resolvables that this package - // will replace (upon update) - B_PACKAGE_INFO_FRESHENS, // list of resolvables that this package - // contains a patch for - // - B_PACKAGE_INFO_ENUM_COUNT, -}; - - -enum BPackageArchitecture { - B_PACKAGE_ARCHITECTURE_ANY = 0, - B_PACKAGE_ARCHITECTURE_X86, - B_PACKAGE_ARCHITECTURE_X86_GCC2, - // - B_PACKAGE_ARCHITECTURE_ENUM_COUNT, -}; - - /* * Keeps a list of package info elements (e.g. name, version, vendor, ...) which * will be converted to package attributes when creating a package. Usually, diff --git a/headers/os/package/PackageInfoAttributes.h b/headers/os/package/PackageInfoAttributes.h new file mode 100644 index 0000000000..7e1818df49 --- /dev/null +++ b/headers/os/package/PackageInfoAttributes.h @@ -0,0 +1,44 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_ +#define _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_ + + +namespace BPackageKit { + + +enum BPackageInfoAttributeIndex { + B_PACKAGE_INFO_NAME = 0, + B_PACKAGE_INFO_SUMMARY, // single line + B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible + B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project" + B_PACKAGE_INFO_PACKAGER, // e-mail address preferred + B_PACKAGE_INFO_ARCHITECTURE, + B_PACKAGE_INFO_VERSION, // [.[.]] + B_PACKAGE_INFO_COPYRIGHTS, // list + B_PACKAGE_INFO_LICENSES, // list + B_PACKAGE_INFO_PROVIDES, // list of resolvables this package provides, + // each optionally giving a version + B_PACKAGE_INFO_REQUIRES, // list of resolvables required by this package, + // each optionally specifying a version relation + // (e.g. libssl.so >= 0.9.8) + B_PACKAGE_INFO_SUPPLEMENTS, // list of resolvables that are supplemented + // by this package, i.e. this package marks + // itself as an extension to other packages + B_PACKAGE_INFO_CONFLICTS, // list of resolvables that inhibit installation + // of this package + B_PACKAGE_INFO_FRESHENS, // list of resolvables that this package + // contains a patch for + B_PACKAGE_INFO_REPLACES, // list of resolvables that this package + // will replace (upon update) + // + B_PACKAGE_INFO_ENUM_COUNT, +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_ diff --git a/headers/os/package/PackageResolvable.h b/headers/os/package/PackageResolvable.h index 7e08596be0..658e142335 100644 --- a/headers/os/package/PackageResolvable.h +++ b/headers/os/package/PackageResolvable.h @@ -2,29 +2,19 @@ * Copyright 2011, Haiku, Inc. * Distributed under the terms of the MIT License. */ -#ifndef _PACKAGE__PACKAGE_RESOLVALBE_H_ -#define _PACKAGE__PACKAGE_RESOLVALBE_H_ +#ifndef _PACKAGE__PACKAGE_RESOLVABLE_H_ +#define _PACKAGE__PACKAGE_RESOLVABLE_H_ #include +#include #include namespace BPackageKit { -enum BPackageResolvableType { - B_PACKAGE_RESOLVABLE_TYPE_DEFAULT = 0, - B_PACKAGE_RESOLVABLE_TYPE_LIBRARY, - B_PACKAGE_RESOLVABLE_TYPE_COMMAND, - B_PACKAGE_RESOLVABLE_TYPE_APPLICATION, - B_PACKAGE_RESOLVABLE_TYPE_ADD_ON, - // - B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT, -}; - - /* * Defines a resolvable (something other packages can depend upon). * Each resolvable is defined as a name (with an optional type prefix) @@ -83,4 +73,4 @@ private: } // namespace BPackageKit -#endif // _PACKAGE__PACKAGE_RESOLVALBE_H_ +#endif // _PACKAGE__PACKAGE_RESOLVABLE_H_ diff --git a/headers/os/package/PackageResolvableOperator.h b/headers/os/package/PackageResolvableOperator.h new file mode 100644 index 0000000000..73d6b65197 --- /dev/null +++ b/headers/os/package/PackageResolvableOperator.h @@ -0,0 +1,27 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_ +#define _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_ + + +namespace BPackageKit { + + +enum BPackageResolvableOperator { + B_PACKAGE_RESOLVABLE_OP_LESS, + B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL, + B_PACKAGE_RESOLVABLE_OP_EQUAL, + B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL, + B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL, + B_PACKAGE_RESOLVABLE_OP_GREATER, + // + B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_ diff --git a/headers/os/package/PackageResolvableType.h b/headers/os/package/PackageResolvableType.h new file mode 100644 index 0000000000..2c81e29786 --- /dev/null +++ b/headers/os/package/PackageResolvableType.h @@ -0,0 +1,26 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_ +#define _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_ + + +namespace BPackageKit { + + +enum BPackageResolvableType { + B_PACKAGE_RESOLVABLE_TYPE_DEFAULT = 0, + B_PACKAGE_RESOLVABLE_TYPE_LIBRARY, + B_PACKAGE_RESOLVABLE_TYPE_COMMAND, + B_PACKAGE_RESOLVABLE_TYPE_APPLICATION, + B_PACKAGE_RESOLVABLE_TYPE_ADD_ON, + // + B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT, +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_ diff --git a/headers/os/package/hpkg/HPKGDefs.h b/headers/os/package/hpkg/HPKGDefs.h index 12b6261e6d..8b7b7ebb67 100644 --- a/headers/os/package/hpkg/HPKGDefs.h +++ b/headers/os/package/hpkg/HPKGDefs.h @@ -28,7 +28,9 @@ enum { B_HPKG_ATTRIBUTE_TYPE_INT = 1, B_HPKG_ATTRIBUTE_TYPE_UINT = 2, B_HPKG_ATTRIBUTE_TYPE_STRING = 3, - B_HPKG_ATTRIBUTE_TYPE_RAW = 4 + B_HPKG_ATTRIBUTE_TYPE_RAW = 4, + // + B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT }; @@ -63,6 +65,34 @@ enum { #define B_HPKG_PACKAGE_INFO_FILE_NAME ".PackageInfo" +// 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, + // + B_PACKAGE_ATTRIBUTE_ENUM_COUNT, +}; + + +// TODO: make this accessible via a function // default values enum { B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB = 64 * 1024 diff --git a/headers/os/package/hpkg/PackageContentHandler.h b/headers/os/package/hpkg/PackageContentHandler.h index 9024467c81..21c64da4f8 100644 --- a/headers/os/package/hpkg/PackageContentHandler.h +++ b/headers/os/package/hpkg/PackageContentHandler.h @@ -17,6 +17,7 @@ namespace BHPKG { class BPackageAttributeValue; class BPackageEntry; class BPackageEntryAttribute; +class BPackageInfoAttributeValue; class BLowLevelPackageContentHandler { @@ -43,6 +44,10 @@ public: BPackageEntryAttribute* attribute) = 0; virtual status_t HandleEntryDone(BPackageEntry* entry) = 0; + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value + ) = 0; + virtual void HandleErrorOccurred() = 0; }; diff --git a/headers/os/package/hpkg/PackageInfoAttributeValue.h b/headers/os/package/hpkg/PackageInfoAttributeValue.h new file mode 100644 index 0000000000..604c07dbd3 --- /dev/null +++ b/headers/os/package/hpkg/PackageInfoAttributeValue.h @@ -0,0 +1,95 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__PACKAGE_INFO_ATTRIBUTE_VALUE_H_ +#define _PACKAGE__HPKG__PACKAGE_INFO_ATTRIBUTE_VALUE_H_ + + +#include + +#include +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +struct BPackageVersionData { + const char* major; + const char* minor; + const char* micro; + uint8 release; +}; + + +struct BPackageResolvableData { + BPackageResolvableType type; + const char* name; + bool haveVersion; + BPackageVersionData version; +}; + + +struct BPackageResolvableExpressionData { + const char* name; + bool haveOpAndVersion; + BPackageResolvableOperator op; + BPackageVersionData version; +}; + + +struct BPackageInfoAttributeValue { + union { + uint64 unsignedInt; + const char* string; + BPackageVersionData version; + BPackageResolvableData resolvable; + BPackageResolvableExpressionData resolvableExpression; + }; + uint8 attributeIndex; + +public: + inline BPackageInfoAttributeValue(); + + inline void SetTo(BPackageInfoAttributeIndex index, + uint8 value); + inline void SetTo(BPackageInfoAttributeIndex index, + const char* value); +}; + + +BPackageInfoAttributeValue::BPackageInfoAttributeValue() + : + attributeIndex(B_PACKAGE_INFO_ENUM_COUNT) +{ +} + + +void +BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index, uint8 value) +{ + attributeIndex = index; + unsignedInt = value; +} + + +void +BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index, + const char* value) +{ + attributeIndex = index; + string = value; +} + + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__PACKAGE_ATTRIBUTE_VALUE_H_ diff --git a/headers/private/package/hpkg/PackageReaderImpl.h b/headers/private/package/hpkg/PackageReaderImpl.h index c8735dbd97..fdb39fda09 100644 --- a/headers/private/package/hpkg/PackageReaderImpl.h +++ b/headers/private/package/hpkg/PackageReaderImpl.h @@ -12,6 +12,7 @@ #include #include +#include #include @@ -74,6 +75,25 @@ private: 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); @@ -88,6 +108,9 @@ private: const void*& _buffer); status_t _ReadTOCBuffer(void* buffer, size_t size); + status_t _ReadPackageAttributesBuffer(void* buffer, + size_t size); + status_t _ReadBuffer(off_t offset, void* buffer, size_t size); status_t _ReadCompressedBuffer(off_t offset, @@ -103,7 +126,7 @@ private: inline AttributeHandler* _PopAttributeHandler(); private: - BErrorOutput* fErrorOutput; + BErrorOutput* fErrorOutput; int fFD; bool fOwnsFD; @@ -120,6 +143,8 @@ private: uint64 fTOCStringsLength; uint64 fTOCStringsCount; + bool fInPackageAttributes; + uint32 fPackageAttributesCompression; uint32 fPackageAttributesCompressedLength; uint32 fPackageAttributesUncompressedLength; @@ -127,6 +152,10 @@ private: uint8* fTOCSection; uint64 fCurrentTOCOffset; + + uint8* fPackageAttributesSection; + uint64 fCurrentPackageAttributesOffset; + AttributeTypeReference* fAttributeTypes; char** fStrings; @@ -141,7 +170,9 @@ template status_t PackageReaderImpl::_Read(Type& _value) { - return _ReadTOCBuffer(&_value, sizeof(Type)); + return fInPackageAttributes + ? _ReadPackageAttributesBuffer(&_value, sizeof(Type)) + : _ReadTOCBuffer(&_value, sizeof(Type)); } diff --git a/headers/private/package/hpkg/PackageWriterImpl.h b/headers/private/package/hpkg/PackageWriterImpl.h index 2331384170..f0fd9721f4 100644 --- a/headers/private/package/hpkg/PackageWriterImpl.h +++ b/headers/private/package/hpkg/PackageWriterImpl.h @@ -82,6 +82,10 @@ private: void _WritePackageVersion( const BPackageVersion& version); + void _WritePackageResolvableExpressionList( + const BObjectList< + BPackageResolvableExpression>& list, + uint8 id); template inline void _Write(const Type& value); diff --git a/headers/private/package/hpkg/haiku_package.h b/headers/private/package/hpkg/haiku_package.h index 00ee7ebe16..45fe221791 100644 --- a/headers/private/package/hpkg/haiku_package.h +++ b/headers/private/package/hpkg/haiku_package.h @@ -129,7 +129,7 @@ enum { // package attribute IDs -enum { +enum BHPKGPackageAttributeID { B_HPKG_PACKAGE_ATTRIBUTE_NAME = 0, B_HPKG_PACKAGE_ATTRIBUTE_SUMMARY, B_HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION, @@ -150,6 +150,8 @@ enum { B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS, B_HPKG_PACKAGE_ATTRIBUTE_REPLACES, B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR, + // + B_HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT, }; diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 154971bb00..c6b1fe01eb 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -257,6 +257,13 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler { return B_OK; } + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value) + { + // TODO! + return B_OK; + } + virtual void HandleErrorOccurred() { fErrorOccurred = true; diff --git a/src/bin/package/command_extract.cpp b/src/bin/package/command_extract.cpp index 28615b0338..d3b3a86a45 100644 --- a/src/bin/package/command_extract.cpp +++ b/src/bin/package/command_extract.cpp @@ -223,6 +223,12 @@ struct PackageContentExtractHandler : BPackageContentHandler { return B_OK; } + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value) + { + 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 9719673971..5e00208564 100644 --- a/src/bin/package/command_list.cpp +++ b/src/bin/package/command_list.cpp @@ -14,13 +14,17 @@ #include #include #include +#include #include +#include + #include "package.h" #include "StandardErrorOutput.h" using namespace BPackageKit::BHPKG; +using namespace BPackageKit; struct PackageContentListHandler : BPackageContentHandler { @@ -104,6 +108,114 @@ struct PackageContentListHandler : BPackageContentHandler { return B_OK; } + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value) + { + switch (value.attributeIndex) { + case B_PACKAGE_INFO_NAME: + printf("package-attributes:\n"); + printf("\tname: %s\n", value.string); + break; + + case B_PACKAGE_INFO_SUMMARY: + printf("\tsummary: %s\n", value.string); + break; + + case B_PACKAGE_INFO_DESCRIPTION: + printf("\tdescription: %s\n", value.string); + break; + + case B_PACKAGE_INFO_VENDOR: + printf("\tvendor: %s\n", value.string); + break; + + case B_PACKAGE_INFO_PACKAGER: + printf("\tpackager: %s\n", value.string); + break; + + case B_PACKAGE_INFO_ARCHITECTURE: + printf("\tarchitecure: %s\n", + BPackageInfo::kArchitectureNames[value.unsignedInt]); + break; + + case B_PACKAGE_INFO_VERSION: + printf("\tversion: %s.%s.%s-%d\n", value.version.major, + value.version.minor, value.version.micro, + value.version.release); + break; + + case B_PACKAGE_INFO_COPYRIGHTS: + printf("\tcopyright: %s\n", value.string); + break; + + case B_PACKAGE_INFO_LICENSES: + printf("\tlicense: %s\n", value.string); + break; + + case B_PACKAGE_INFO_PROVIDES: + printf("\tprovides: %s", value.resolvable.name); + if (value.resolvable.haveVersion) { + printf(" = "); + _PrintPackageVersion(value.resolvable.version); + } + printf("\n"); + break; + + case B_PACKAGE_INFO_REQUIRES: + printf("\trequires: %s", value.resolvableExpression.name); + if (value.resolvableExpression.haveOpAndVersion) { + printf(" %s ", BPackageResolvableExpression::kOperatorNames[ + value.resolvableExpression.op]); + _PrintPackageVersion(value.resolvableExpression.version); + } + printf("\n"); + break; + + case B_PACKAGE_INFO_SUPPLEMENTS: + printf("\tsupplements: %s", value.resolvableExpression.name); + if (value.resolvableExpression.haveOpAndVersion) { + printf(" %s ", BPackageResolvableExpression::kOperatorNames[ + value.resolvableExpression.op]); + _PrintPackageVersion(value.resolvableExpression.version); + } + printf("\n"); + break; + + case B_PACKAGE_INFO_CONFLICTS: + printf("\tconflicts: %s", value.resolvableExpression.name); + if (value.resolvableExpression.haveOpAndVersion) { + printf(" %s ", BPackageResolvableExpression::kOperatorNames[ + value.resolvableExpression.op]); + _PrintPackageVersion(value.resolvableExpression.version); + } + printf("\n"); + break; + + case B_PACKAGE_INFO_FRESHENS: + printf("\tfreshens: %s", value.resolvableExpression.name); + if (value.resolvableExpression.haveOpAndVersion) { + printf(" %s ", BPackageResolvableExpression::kOperatorNames[ + value.resolvableExpression.op]); + _PrintPackageVersion(value.resolvableExpression.version); + } + printf("\n"); + break; + + case B_PACKAGE_INFO_REPLACES: + printf("\treplaces: %s\n", value.string); + break; + + default: + printf( + "*** Invalid package attribute section: unexpected " + "package attribute index %d encountered\n", + value.attributeIndex); + return B_BAD_DATA; + } + + return B_OK; + } + virtual void HandleErrorOccurred() { } @@ -123,6 +235,17 @@ private: return buffer; } + static void _PrintPackageVersion(const BPackageVersionData& version) + { + printf("%s", version.major); + if (version.minor != NULL && version.minor[0] != '\0') + printf(".%s", version.minor); + if (version.micro != NULL && version.micro[0] != '\0') + printf(".%s", version.micro); + if (version.release > 0) + printf("-%d", version.release); + } + private: int fLevel; bool fListAttribute; diff --git a/src/kits/package/hpkg/PackageReaderImpl.cpp b/src/kits/package/hpkg/PackageReaderImpl.cpp index a349882aec..b8560499f1 100644 --- a/src/kits/package/hpkg/PackageReaderImpl.cpp +++ b/src/kits/package/hpkg/PackageReaderImpl.cpp @@ -41,9 +41,12 @@ namespace BPrivate { // maximum TOC size we support reading -static const size_t kMaxTOCSize = 64 * 1024 * 1024; +static const size_t kMaxTOCSize = 64 * 1024 * 1024; -static const size_t kScratchBufferSize = 64 * 1024; +// maximum package attributes size we support reading +static const size_t kMaxPackageAttributesSize = 1 * 1024 * 1024; + +static const size_t kScratchBufferSize = 64 * 1024; enum { @@ -612,7 +615,9 @@ PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput) fErrorOutput(errorOutput), fFD(-1), fOwnsFD(false), + fInPackageAttributes(false), fTOCSection(NULL), + fPackageAttributesSection(NULL), fAttributeTypes(NULL), fStrings(NULL), fScratchBuffer(NULL), @@ -630,6 +635,7 @@ PackageReaderImpl::~PackageReaderImpl() delete[] fStrings; delete[] fAttributeTypes; delete[] fTOCSection; + delete[] fPackageAttributesSection; } @@ -772,6 +778,15 @@ PackageReaderImpl::Init(int fd, bool keepFD) return B_UNSUPPORTED; } + // package attributes size sanity check + if (fPackageAttributesUncompressedLength > kMaxPackageAttributesSize) { + fErrorOutput->PrintError( + "Error: Package file package attributes section size " + "is %llu bytes. This is beyond the reader's sanity limit\n", + fPackageAttributesUncompressedLength); + return B_UNSUPPORTED; + } + // allocate a scratch buffer fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; if (fScratchBuffer == NULL) { @@ -786,13 +801,26 @@ PackageReaderImpl::Init(int fd, bool keepFD) fErrorOutput->PrintError("Error: Out of memory!\n"); return B_NO_MEMORY; } - error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection, fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression); if (error != B_OK) return error; + // read in the complete package attributes section + fPackageAttributesSection + = new(std::nothrow) uint8[fPackageAttributesUncompressedLength]; + if (fPackageAttributesSection == NULL) { + fErrorOutput->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + error = _ReadCompressedBuffer(fPackageAttributesOffset, + fPackageAttributesSection, fPackageAttributesCompressedLength, + fPackageAttributesUncompressedLength, fPackageAttributesCompression); + if (error != B_OK) + return error; + // start parsing the TOC + fInPackageAttributes = false; fCurrentTOCOffset = 0; // attribute types @@ -816,7 +844,15 @@ PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler) { AttributeHandlerContext context(fErrorOutput, contentHandler); RootAttributeHandler rootAttributeHandler; - return _ParseContent(&context, &rootAttributeHandler); + + status_t result = _ParseContent(&context, &rootAttributeHandler); + if (result != B_OK) + return result; + + fInPackageAttributes = true; + fCurrentPackageAttributesOffset = 0; + + return _ParsePackageAttributes(&context); } @@ -1070,6 +1106,350 @@ 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 B_OK; + + switch (id) { + case B_HPKG_PACKAGE_ATTRIBUTE_NAME: + handlerValue.SetTo(B_PACKAGE_INFO_NAME, attributeValue.string); + break; + + case B_HPKG_PACKAGE_ATTRIBUTE_SUMMARY: + handlerValue.SetTo(B_PACKAGE_INFO_SUMMARY, + attributeValue.string); + break; + + case B_HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION: + handlerValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, + attributeValue.string); + break; + + case B_HPKG_PACKAGE_ATTRIBUTE_VENDOR: + handlerValue.SetTo(B_PACKAGE_INFO_VENDOR, + attributeValue.string); + break; + + case B_HPKG_PACKAGE_ATTRIBUTE_PACKAGER: + handlerValue.SetTo(B_PACKAGE_INFO_PACKAGER, + attributeValue.string); + break; + + case B_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 B_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 B_HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT: + handlerValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, + attributeValue.string); + break; + + case B_HPKG_PACKAGE_ATTRIBUTE_LICENSE: + handlerValue.SetTo(B_PACKAGE_INFO_LICENSES, + attributeValue.string); + break; + + case B_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 B_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 B_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 B_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 B_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 B_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 != B_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 != B_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 != B_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 != B_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 != B_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 != B_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 = B_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, + B_HPKG_PACKAGE_ATTRIBUTE_TAG_ENCODING(tag), _value); + if (error != B_OK) + return error; + + _id = B_HPKG_PACKAGE_ATTRIBUTE_TAG_ID(tag); + if (_id >= B_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 = B_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) @@ -1235,6 +1615,29 @@ PackageReaderImpl::_ReadUnsignedLEB128(uint64& _value) status_t PackageReaderImpl::_ReadString(const char*& _string, size_t* _stringLength) { + if (fInPackageAttributes) { + const char* string = (const char*)fPackageAttributesSection + + fCurrentPackageAttributesOffset; + size_t stringLength = strnlen(string, + fPackageAttributesUncompressedLength + - fCurrentPackageAttributesOffset); + + if (stringLength == fPackageAttributesUncompressedLength + - fCurrentPackageAttributesOffset) { + fErrorOutput->PrintError( + "_ReadString(): string extends beyond package attributes " + "section end\n"); + return B_BAD_DATA; + } + + _string = string; + if (_stringLength != NULL) + *_stringLength = stringLength; + + fCurrentPackageAttributesOffset += stringLength + 1; + return B_OK; + } + const char* string = (const char*)fTOCSection + fCurrentTOCOffset; size_t stringLength = strnlen(string, fTOCUncompressedLength - fCurrentTOCOffset); @@ -1284,6 +1687,24 @@ PackageReaderImpl::_ReadTOCBuffer(void* buffer, size_t size) } +status_t +PackageReaderImpl::_ReadPackageAttributesBuffer(void* buffer, size_t size) +{ + if (size > fPackageAttributesUncompressedLength + - fCurrentPackageAttributesOffset) { + fErrorOutput->PrintError( + "_ReadPackageAttributesBuffer(%lu): read beyond section end\n", + size); + return B_BAD_DATA; + } + + memcpy(buffer, fPackageAttributesSection + fCurrentPackageAttributesOffset, + size); + fCurrentPackageAttributesOffset += size; + return B_OK; +} + + status_t PackageReaderImpl::_ReadBuffer(off_t offset, void* buffer, size_t size) { diff --git a/src/kits/package/hpkg/PackageWriterImpl.cpp b/src/kits/package/hpkg/PackageWriterImpl.cpp index a9e0da1d0a..5d9e02d2f8 100644 --- a/src/kits/package/hpkg/PackageWriterImpl.cpp +++ b/src/kits/package/hpkg/PackageWriterImpl.cpp @@ -1068,6 +1068,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header) _WriteString(licenseList.ItemAt(i)->String()); } + // provides list const BObjectList& providesList = fPackageInfo.ProvidesList(); for (int i = 0; i < providesList.CountItems(); ++i) { @@ -1075,31 +1076,41 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header) bool hasVersion = resolvable->Version().InitCheck() == B_OK; _WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT, - B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT, hasVersion ? 1 : 0)); - _Write(fPackageInfo.Architecture()); + B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT, 0)); + _Write((uint8)resolvable->Type()); _WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING, - B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, 1)); - _WriteString(resolvable->AsString().String()); + B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion)); + _WriteString(resolvable->Name().String()); if (hasVersion) { _WritePackageVersion(resolvable->Version()); _Write(0); } } - const BObjectList& requiresList - = fPackageInfo.RequiresList(); - for (int i = 0; i < requiresList.CountItems(); ++i) { - BPackageResolvableExpression* resolvableExpr = requiresList.ItemAt(i); - bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK; + // requires list + _WritePackageResolvableExpressionList(fPackageInfo.RequiresList(), + B_HPKG_PACKAGE_ATTRIBUTE_REQUIRES); + + // supplements list + _WritePackageResolvableExpressionList(fPackageInfo.SupplementsList(), + B_HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS); + + // conflicts list + _WritePackageResolvableExpressionList(fPackageInfo.ConflictsList(), + B_HPKG_PACKAGE_ATTRIBUTE_CONFLICTS); + + // freshens list + _WritePackageResolvableExpressionList(fPackageInfo.FreshensList(), + B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS); + + // replaces list + const BObjectList& replacesList = fPackageInfo.ReplacesList(); + for (int i = 0; i < replacesList.CountItems(); ++i) { _WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( - B_HPKG_PACKAGE_ATTRIBUTE_REQUIRES, B_HPKG_ATTRIBUTE_TYPE_STRING, - B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion)); - _WriteString(resolvableExpr->AsString().String()); - if (hasVersion) { - _WritePackageVersion(resolvableExpr->Version()); - _Write(0); - } + B_HPKG_PACKAGE_ATTRIBUTE_REPLACES, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, 0)); + _WriteString(replacesList.ItemAt(i)->String()); } _Write(0); @@ -1143,6 +1154,30 @@ PackageWriterImpl::_WritePackageVersion(const BPackageVersion& version) } +void +PackageWriterImpl::_WritePackageResolvableExpressionList( + const BObjectList& list, uint8 id) +{ + for (int i = 0; i < list.CountItems(); ++i) { + BPackageResolvableExpression* resolvableExpr = list.ItemAt(i); + bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK; + _WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( + id, B_HPKG_ATTRIBUTE_TYPE_STRING, + B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion)); + _WriteString(resolvableExpr->Name().String()); + if (hasVersion) { + _WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE( + B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR, + B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT, + 0)); + _Write(resolvableExpr->Operator()); + _WritePackageVersion(resolvableExpr->Version()); + _Write(0); + } + } +} + + void PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value, uint8 encoding)