diff --git a/headers/build/os/package/hpkg/v1/HPKGDefs.h b/headers/build/os/package/hpkg/v1/HPKGDefs.h new file mode 100644 index 0000000000..902ae73bfa --- /dev/null +++ b/headers/build/os/package/hpkg/v1/HPKGDefs.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/HPKGDefs.h> diff --git a/headers/build/os/package/hpkg/v1/PackageAttributeValue.h b/headers/build/os/package/hpkg/v1/PackageAttributeValue.h new file mode 100644 index 0000000000..3468eb9c46 --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageAttributeValue.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageAttributeValue.h> diff --git a/headers/build/os/package/hpkg/v1/PackageContentHandler.h b/headers/build/os/package/hpkg/v1/PackageContentHandler.h new file mode 100644 index 0000000000..b5cb701d09 --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageContentHandler.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageContentHandler.h> diff --git a/headers/build/os/package/hpkg/v1/PackageData.h b/headers/build/os/package/hpkg/v1/PackageData.h new file mode 100644 index 0000000000..399ae83c26 --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageData.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageData.h> diff --git a/headers/build/os/package/hpkg/v1/PackageDataReader.h b/headers/build/os/package/hpkg/v1/PackageDataReader.h new file mode 100644 index 0000000000..b732a595ec --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageDataReader.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageDataReader.h> diff --git a/headers/build/os/package/hpkg/v1/PackageEntry.h b/headers/build/os/package/hpkg/v1/PackageEntry.h new file mode 100644 index 0000000000..20319e0689 --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageEntry.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageEntry.h> diff --git a/headers/build/os/package/hpkg/v1/PackageEntryAttribute.h b/headers/build/os/package/hpkg/v1/PackageEntryAttribute.h new file mode 100644 index 0000000000..f4cbf51fdd --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageEntryAttribute.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageEntryAttribute.h> diff --git a/headers/build/os/package/hpkg/v1/PackageReader.h b/headers/build/os/package/hpkg/v1/PackageReader.h new file mode 100644 index 0000000000..97a82ccded --- /dev/null +++ b/headers/build/os/package/hpkg/v1/PackageReader.h @@ -0,0 +1 @@ +#include <../os/package/hpkg/v1/PackageReader.h> diff --git a/headers/build/private/package/hpkg/v1/HPKGDefsPrivate.h b/headers/build/private/package/hpkg/v1/HPKGDefsPrivate.h new file mode 100644 index 0000000000..e9b88221cb --- /dev/null +++ b/headers/build/private/package/hpkg/v1/HPKGDefsPrivate.h @@ -0,0 +1 @@ +#include <../private/package/hpkg/v1/HPKGDefsPrivate.h> diff --git a/headers/build/private/package/hpkg/v1/PackageInfoContentHandler.h b/headers/build/private/package/hpkg/v1/PackageInfoContentHandler.h new file mode 100644 index 0000000000..f56434047c --- /dev/null +++ b/headers/build/private/package/hpkg/v1/PackageInfoContentHandler.h @@ -0,0 +1 @@ +#include <../private/package/hpkg/v1/PackageInfoContentHandler.h> diff --git a/headers/build/private/package/hpkg/v1/PackageReaderImpl.h b/headers/build/private/package/hpkg/v1/PackageReaderImpl.h new file mode 100644 index 0000000000..461ad77522 --- /dev/null +++ b/headers/build/private/package/hpkg/v1/PackageReaderImpl.h @@ -0,0 +1 @@ +#include <../private/package/hpkg/v1/PackageReaderImpl.h> diff --git a/headers/build/private/package/hpkg/v1/ReaderImplBase.h b/headers/build/private/package/hpkg/v1/ReaderImplBase.h new file mode 100644 index 0000000000..c06ed7c5c4 --- /dev/null +++ b/headers/build/private/package/hpkg/v1/ReaderImplBase.h @@ -0,0 +1 @@ +#include <../private/package/hpkg/v1/ReaderImplBase.h> diff --git a/headers/os/package/hpkg/v1/HPKGDefs.h b/headers/os/package/hpkg/v1/HPKGDefs.h new file mode 100644 index 0000000000..0c6405772f --- /dev/null +++ b/headers/os/package/hpkg/v1/HPKGDefs.h @@ -0,0 +1,183 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__HPKG_DEFS_H_ +#define _PACKAGE__HPKG__V1__HPKG_DEFS_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +// magic & version of package and repository files +enum { + B_HPKG_MAGIC = 'hpkg', + B_HPKG_VERSION = 1, + // + B_HPKG_REPO_MAGIC = 'hpkr', + B_HPKG_REPO_VERSION = 1 +}; + + +// package attribute IDs +enum BHPKGPackageSectionID { + B_HPKG_SECTION_HEADER = 0, + B_HPKG_SECTION_HEAP = 1, + B_HPKG_SECTION_PACKAGE_TOC = 2, + B_HPKG_SECTION_PACKAGE_ATTRIBUTES = 3, + B_HPKG_SECTION_REPOSITORY_INFO = 4, + // + B_HPKG_SECTION_ENUM_COUNT +}; + + +// attribute types +enum { + // types + B_HPKG_ATTRIBUTE_TYPE_INVALID = 0, + 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_ENUM_COUNT +}; + + +// attribute encodings +enum { + // signed/unsigned int encodings + B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT = 0, + B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT = 1, + B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT = 2, + B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT = 3, + + // string encodings + B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE = 0, + // null-terminated string + B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE = 1, + // unsigned LEB128 index into string table + + // raw data encodings + B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE = 0, + // unsigned LEB128 size, raw bytes + B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP = 1 + // unsigned LEB128 size, unsigned LEB128 offset into the heap +}; + + +// maximum number of bytes of data to be encoded inline; more will be allocated +// on the heap +enum { + B_HPKG_MAX_INLINE_DATA_SIZE = 8 +}; + + +// name of file containing package information (in package's root folder) +extern const char* const B_HPKG_PACKAGE_INFO_FILE_NAME; + + +// package attribute IDs +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_REVISION = 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_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE = 40, + B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE = 41, + B_HPKG_ATTRIBUTE_ID_PACKAGE_URL = 42, + B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL = 43, + B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH = 44, + // + B_HPKG_ATTRIBUTE_ID_ENUM_COUNT, +}; + + +// compression types +enum { + B_HPKG_COMPRESSION_NONE = 0, + B_HPKG_COMPRESSION_ZLIB = 1 +}; + + +// file types (B_HPKG_ATTRIBUTE_ID_FILE_TYPE) +enum { + B_HPKG_FILE_TYPE_FILE = 0, + B_HPKG_FILE_TYPE_DIRECTORY = 1, + B_HPKG_FILE_TYPE_SYMLINK = 2 +}; + + +// default values +enum { + B_HPKG_DEFAULT_FILE_TYPE = B_HPKG_FILE_TYPE_FILE, + B_HPKG_DEFAULT_FILE_PERMISSIONS = 0644, + B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS = 0755, + B_HPKG_DEFAULT_SYMLINK_PERMISSIONS = 0777, + B_HPKG_DEFAULT_DATA_COMPRESSION = B_HPKG_COMPRESSION_NONE, + B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB = 64 * 1024 +}; + + +// Writer Init() flags +enum { + B_HPKG_WRITER_UPDATE_PACKAGE = 0x01, + // update the package (don't truncate) + B_HPKG_WRITER_FORCE_ADD = 0x02, + // when updating a pre-existing entry, don't fail, but replace the + // entry, if possible (directories will be merged, but won't replace a + // non-directory) +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__HPKG_DEFS_H_ diff --git a/headers/os/package/hpkg/v1/PackageAttributeValue.h b/headers/os/package/hpkg/v1/PackageAttributeValue.h new file mode 100644 index 0000000000..ded2e060b5 --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageAttributeValue.h @@ -0,0 +1,161 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_ATTRIBUTE_VALUE_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_ATTRIBUTE_VALUE_H_ + + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +struct BPackageAttributeValue { + union { + int64 signedInt; + uint64 unsignedInt; + const char* string; + struct { + uint64 size; + union { + uint64 offset; + uint8 raw[B_HPKG_MAX_INLINE_DATA_SIZE]; + }; + } data; + }; + uint8 type; + uint8 encoding; + +public: + inline BPackageAttributeValue(); + + inline void SetTo(int8 value); + inline void SetTo(uint8 value); + inline void SetTo(int16 value); + inline void SetTo(uint16 value); + inline void SetTo(int32 value); + inline void SetTo(uint32 value); + inline void SetTo(int64 value); + inline void SetTo(uint64 value); + inline void SetTo(const char* value); + inline void SetToData(uint64 size, uint64 offset); + inline void SetToData(uint64 size, const void* rawData); +}; + + +BPackageAttributeValue::BPackageAttributeValue() + : + type(B_HPKG_ATTRIBUTE_TYPE_INVALID) +{ +} + + +void +BPackageAttributeValue::SetTo(int8 value) +{ + signedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_INT; +} + + +void +BPackageAttributeValue::SetTo(uint8 value) +{ + unsignedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_UINT; +} + + +void +BPackageAttributeValue::SetTo(int16 value) +{ + signedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_INT; +} + + +void +BPackageAttributeValue::SetTo(uint16 value) +{ + unsignedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_UINT; +} + + +void +BPackageAttributeValue::SetTo(int32 value) +{ + signedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_INT; +} + + +void +BPackageAttributeValue::SetTo(uint32 value) +{ + unsignedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_UINT; +} + + +void +BPackageAttributeValue::SetTo(int64 value) +{ + signedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_INT; +} + + +void +BPackageAttributeValue::SetTo(uint64 value) +{ + unsignedInt = value; + type = B_HPKG_ATTRIBUTE_TYPE_UINT; +} + + +void +BPackageAttributeValue::SetTo(const char* value) +{ + string = value; + type = B_HPKG_ATTRIBUTE_TYPE_STRING; +} + + +void +BPackageAttributeValue::SetToData(uint64 size, uint64 offset) +{ + data.size = size; + data.offset = offset; + type = B_HPKG_ATTRIBUTE_TYPE_RAW; + encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP; +} + + +void +BPackageAttributeValue::SetToData(uint64 size, const void* rawData) +{ + data.size = size; + if (size > 0) + memcpy(data.raw, rawData, size); + type = B_HPKG_ATTRIBUTE_TYPE_RAW; + encoding = B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE; +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_ATTRIBUTE_VALUE_H_ diff --git a/headers/os/package/hpkg/v1/PackageContentHandler.h b/headers/os/package/hpkg/v1/PackageContentHandler.h new file mode 100644 index 0000000000..6b46771951 --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageContentHandler.h @@ -0,0 +1,79 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_CONTENT_HANDLER_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_CONTENT_HANDLER_H_ + + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +class BPackageInfoAttributeValue; + + +namespace V1 { + + +class BPackageAttributeValue; +class BPackageEntry; +class BPackageEntryAttribute; + + +class BLowLevelPackageContentHandler { +public: + virtual ~BLowLevelPackageContentHandler(); + + virtual status_t HandleSectionStart( + BHPKGPackageSectionID sectionID, + bool& _handleSection) = 0; + virtual status_t HandleSectionEnd( + BHPKGPackageSectionID sectionID) = 0; + + virtual status_t HandleAttribute(BHPKGAttributeID attributeID, + const BPackageAttributeValue& value, + void* parentToken, void*& _token) = 0; + virtual status_t HandleAttributeDone( + BHPKGAttributeID attributeID, + const BPackageAttributeValue& value, + void* parentToken, void* token) = 0; + + virtual void HandleErrorOccurred() = 0; + +protected: + static const char* AttributeNameForID(uint8 id); +}; + + +class BPackageContentHandler { +public: + virtual ~BPackageContentHandler(); + + virtual status_t HandleEntry(BPackageEntry* entry) = 0; + virtual status_t HandleEntryAttribute(BPackageEntry* entry, + BPackageEntryAttribute* attribute) = 0; + virtual status_t HandleEntryDone(BPackageEntry* entry) = 0; + + virtual status_t HandlePackageAttribute( + const BPackageInfoAttributeValue& value + ) = 0; + + virtual void HandleErrorOccurred() = 0; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_CONTENT_HANDLER_H_ diff --git a/headers/os/package/hpkg/v1/PackageData.h b/headers/os/package/hpkg/v1/PackageData.h new file mode 100644 index 0000000000..816a7e6cc6 --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageData.h @@ -0,0 +1,66 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_DATA_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_DATA_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +class BPackageData { +public: + BPackageData(); + + uint64 CompressedSize() const + { return fCompressedSize; } + uint64 UncompressedSize() const + { return fUncompressedSize; } + uint64 Offset() const + { return fEncodedInline ? 0 : fOffset; } + uint32 Compression() const { return fCompression; } + uint32 ChunkSize() const { return fChunkSize; } + + bool IsEncodedInline() const + { return fEncodedInline; } + const uint8* InlineData() const { return fInlineData; } + + void SetData(uint64 size, uint64 offset); + void SetData(uint8 size, const void* data); + + void SetCompression(uint32 compression) + { fCompression = compression; } + void SetUncompressedSize(uint64 size) + { fUncompressedSize = size; } + void SetChunkSize(uint32 size) + { fChunkSize = size; } + +private: + uint64 fCompressedSize; + uint64 fUncompressedSize; + union { + uint64 fOffset; + uint8 fInlineData[B_HPKG_MAX_INLINE_DATA_SIZE]; + }; + uint32 fChunkSize; + uint32 fCompression; + bool fEncodedInline; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_DATA_H_ diff --git a/headers/os/package/hpkg/v1/PackageDataReader.h b/headers/os/package/hpkg/v1/PackageDataReader.h new file mode 100644 index 0000000000..9af3c02ca6 --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageDataReader.h @@ -0,0 +1,68 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_DATA_READER_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_DATA_READER_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +class BBufferCache; +class BDataOutput; + + +namespace V1 { + + +class BPackageData; + + +class BPackageDataReader : public BDataReader { +public: + BPackageDataReader(BDataReader* dataReader); + virtual ~BPackageDataReader(); + + virtual status_t Init(const BPackageData& data) = 0; + + virtual status_t ReadData(off_t offset, void* buffer, + size_t size); + virtual status_t ReadDataToOutput(off_t offset, size_t size, + BDataOutput* output) = 0; + + virtual uint64 Size() const = 0; + virtual size_t BlockSize() const = 0; + +protected: + BDataReader* fDataReader; +}; + + +class BPackageDataReaderFactory { +public: + BPackageDataReaderFactory( + BBufferCache* bufferCache); + + status_t CreatePackageDataReader(BDataReader* dataReader, + const BPackageData& data, + BPackageDataReader*& _reader); + +private: + BBufferCache* fBufferCache; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_DATA_READER_H_ diff --git a/headers/os/package/hpkg/v1/PackageEntry.h b/headers/os/package/hpkg/v1/PackageEntry.h new file mode 100644 index 0000000000..98621fb1bb --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageEntry.h @@ -0,0 +1,98 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_ENTRY_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_ENTRY_H_ + + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +class BPackageEntry { +public: + BPackageEntry(BPackageEntry* parent, + const char* name); + + const BPackageEntry* Parent() const { return fParent; } + const char* Name() const { return fName; } + void* UserToken() const { return fUserToken; } + + mode_t Mode() const { return fMode; } + + const timespec& AccessTime() const + { return fAccessTime; } + const timespec& ModifiedTime() const + { return fModifiedTime; } + const timespec& CreationTime() const + { return fCreationTime; } + + BPackageData& Data() { return fData; } + + const char* SymlinkPath() const { return fSymlinkPath; } + + void SetUserToken(void* token) + { fUserToken = token; } + + void SetType(uint32 type); + void SetPermissions(uint32 permissions); + + void SetAccessTime(uint32 seconds) + { fAccessTime.tv_sec = seconds; } + void SetAccessTimeNanos(uint32 nanos) + { fAccessTime.tv_nsec = nanos; } + void SetModifiedTime(uint32 seconds) + { fModifiedTime.tv_sec = seconds; } + void SetModifiedTimeNanos(uint32 nanos) + { fModifiedTime.tv_nsec = nanos; } + void SetCreationTime(uint32 seconds) + { fCreationTime.tv_sec = seconds; } + void SetCreationTimeNanos(uint32 nanos) + { fCreationTime.tv_nsec = nanos; } + + void SetSymlinkPath(const char* path) + { fSymlinkPath = path; } +private: + BPackageEntry* fParent; + const char* fName; + void* fUserToken; + mode_t fMode; + timespec fAccessTime; + timespec fModifiedTime; + timespec fCreationTime; + BPackageData fData; + const char* fSymlinkPath; +}; + + +inline void +BPackageEntry::SetType(uint32 type) +{ + fMode = (fMode & ~(uint32)S_IFMT) | (type & S_IFMT); +} + + +inline void +BPackageEntry::SetPermissions(uint32 permissions) +{ + fMode = (fMode & ~(uint32)ALLPERMS) | (permissions & ALLPERMS); +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_ENTRY_H_ diff --git a/headers/os/package/hpkg/v1/PackageEntryAttribute.h b/headers/os/package/hpkg/v1/PackageEntryAttribute.h new file mode 100644 index 0000000000..8fdfc6ea5f --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageEntryAttribute.h @@ -0,0 +1,44 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_ENTRY_ATTRIBUTE_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_ENTRY_ATTRIBUTE_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +class BPackageEntryAttribute { +public: + BPackageEntryAttribute(const char* name); + + const char* Name() const { return fName; } + uint32 Type() const { return fType; } + + BPackageData& Data() { return fData; } + + void SetType(uint32 type) { fType = type; } + +private: + const char* fName; + uint32 fType; + BPackageData fData; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_ENTRY_ATTRIBUTE_H_ diff --git a/headers/os/package/hpkg/v1/PackageReader.h b/headers/os/package/hpkg/v1/PackageReader.h new file mode 100644 index 0000000000..50df38fbb3 --- /dev/null +++ b/headers/os/package/hpkg/v1/PackageReader.h @@ -0,0 +1,58 @@ +/* + * Copyright 2009,2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_READER_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_READER_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +class BErrorOutput; + + +namespace V1 { + + +namespace BPrivate { + class PackageReaderImpl; +} +using BPrivate::PackageReaderImpl; + +class BLowLevelPackageContentHandler; +class BPackageContentHandler; + + +class BPackageReader { +public: + BPackageReader( + BErrorOutput* errorOutput); + ~BPackageReader(); + + 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(); +private: + PackageReaderImpl* fImpl; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_READER_H_ diff --git a/headers/private/package/hpkg/v1/HPKGDefsPrivate.h b/headers/private/package/hpkg/v1/HPKGDefsPrivate.h new file mode 100644 index 0000000000..f5948b09f4 --- /dev/null +++ b/headers/private/package/hpkg/v1/HPKGDefsPrivate.h @@ -0,0 +1,115 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PRIVATE__HAIKU_PACKAGE_H_ +#define _PACKAGE__HPKG__V1__PRIVATE__HAIKU_PACKAGE_H_ + + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + +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; + uint64 total_size; + + // repository info section + uint32 info_compression; + uint32 info_length_compressed; + uint32 info_length_uncompressed; + + // package attributes section + uint32 packages_compression; + uint64 packages_length_compressed; + uint64 packages_length_uncompressed; + uint64 packages_strings_length; + uint64 packages_strings_count; +}; + + +// attribute tag arithmetics +// (using 6 bits for id, 3 for type, 1 for hasChildren and 2 for encoding) +static inline uint16 +compose_attribute_tag(uint16 id, uint16 type, uint16 encoding, bool hasChildren) +{ + return ((encoding << 10) | (uint16(hasChildren ? 1 : 0) << 9) | (type << 6) + | id) + + 1; +} + + +static inline uint16 +attribute_tag_encoding(uint16 tag) +{ + return ((tag - 1) >> 10) & 0x3; +} + + +static inline bool +attribute_tag_has_children(uint16 tag) +{ + return (((tag - 1) >> 9) & 0x1) != 0; +} + + +static inline uint16 +attribute_tag_type(uint16 tag) +{ + return ((tag - 1) >> 6) & 0x7; +} + + +static inline uint16 +attribute_tag_id(uint16 tag) +{ + return (tag - 1) & 0x3f; +} + + +} // namespace BPrivate + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PRIVATE__HAIKU_PACKAGE_H_ diff --git a/headers/private/package/hpkg/v1/PackageInfoContentHandler.h b/headers/private/package/hpkg/v1/PackageInfoContentHandler.h new file mode 100644 index 0000000000..38ff4f1218 --- /dev/null +++ b/headers/private/package/hpkg/v1/PackageInfoContentHandler.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PACKAGE_INFO_CONTENT_HANDLER_H_ +#define _PACKAGE__HPKG__V1__PACKAGE_INFO_CONTENT_HANDLER_H_ + + +#include + + +namespace BPackageKit { + + +class BPackageInfo; + + +namespace BHPKG { + + +class BErrorOutput; + + +namespace V1 { + + +class BPackageInfoContentHandler : public BPackageContentHandler { +public: + BPackageInfoContentHandler( + BPackageInfo& packageInfo, + BHPKG::BErrorOutput* errorOutput = NULL); + virtual ~BPackageInfoContentHandler(); + + virtual status_t HandleEntry(BPackageEntry* entry); + virtual status_t HandleEntryAttribute(BPackageEntry* entry, + BPackageEntryAttribute* attribute); + virtual status_t HandleEntryDone(BPackageEntry* entry); + + virtual status_t HandlePackageAttribute( + const BHPKG::BPackageInfoAttributeValue& + value); + + virtual void HandleErrorOccurred(); + +protected: + BPackageInfo& fPackageInfo; + BHPKG::BErrorOutput* fErrorOutput; +}; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PACKAGE_INFO_CONTENT_HANDLER_H_ diff --git a/headers/private/package/hpkg/v1/PackageReaderImpl.h b/headers/private/package/hpkg/v1/PackageReaderImpl.h new file mode 100644 index 0000000000..3628d88a09 --- /dev/null +++ b/headers/private/package/hpkg/v1/PackageReaderImpl.h @@ -0,0 +1,102 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PRIVATE__PACKAGE_READER_IMPL_H_ +#define _PACKAGE__HPKG__V1__PRIVATE__PACKAGE_READER_IMPL_H_ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +class BPackageEntry; +class BPackageEntryAttribute; + + +namespace BPrivate { + + +class PackageReaderImpl : public ReaderImplBase { + typedef ReaderImplBase inherited; +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() const; + + uint64 HeapOffset() const; + uint64 HeapSize() const; + +protected: + // from ReaderImplBase + virtual status_t ReadAttributeValue(uint8 type, uint8 encoding, + AttributeValue& _value); + +private: + struct DataAttributeHandler; + struct AttributeAttributeHandler; + struct EntryAttributeHandler; + struct RootAttributeHandler; + +private: + status_t _ParseTOC(AttributeHandlerContext* context, + AttributeHandler* rootAttributeHandler); + + status_t _GetTOCBuffer(size_t size, + const void*& _buffer); +private: + uint64 fTotalSize; + uint64 fHeapOffset; + uint64 fHeapSize; + + SectionInfo fTOCSection; +}; + + +inline int +PackageReaderImpl::PackageFileFD() const +{ + return FD(); +} + + +inline uint64 +PackageReaderImpl::HeapOffset() const +{ + return fHeapOffset; +} + + +inline uint64 +PackageReaderImpl::HeapSize() const +{ + return fHeapSize; +} + + +} // namespace BPrivate + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PRIVATE__PACKAGE_READER_IMPL_H_ diff --git a/headers/private/package/hpkg/v1/ReaderImplBase.h b/headers/private/package/hpkg/v1/ReaderImplBase.h new file mode 100644 index 0000000000..4147d422b7 --- /dev/null +++ b/headers/private/package/hpkg/v1/ReaderImplBase.h @@ -0,0 +1,338 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__HPKG__V1__PRIVATE__READER_IMPL_BASE_H_ +#define _PACKAGE__HPKG__V1__PRIVATE__READER_IMPL_BASE_H_ + + +#include + +#include + +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + + +class BErrorOutput; + + +namespace V1 { + +namespace BPrivate { + + +class ReaderImplBase { +protected: + ReaderImplBase( + BErrorOutput* errorOutput); + virtual ~ReaderImplBase(); + + virtual status_t Init(int fd, bool keepFD); + + int FD() const; + + BErrorOutput* ErrorOutput() const; + +protected: + struct AttributeHandlerContext { + BErrorOutput* errorOutput; + union { + BPackageContentHandler* packageContentHandler; + BLowLevelPackageContentHandler* lowLevelHandler; + }; + bool hasLowLevelHandler; + + uint64 heapOffset; + uint64 heapSize; + + BHPKGPackageSectionID section; + + AttributeHandlerContext(BErrorOutput* errorOutput, + BPackageContentHandler* packageContentHandler, + BHPKGPackageSectionID section); + + AttributeHandlerContext(BErrorOutput* errorOutput, + BLowLevelPackageContentHandler* lowLevelHandler, + BHPKGPackageSectionID section); + + void ErrorOccurred(); + }; + + + typedef BPackageAttributeValue AttributeValue; + + struct AttributeHandler + : SinglyLinkedListLinkImpl { + virtual ~AttributeHandler(); + + void SetLevel(int level); + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + + virtual status_t Delete(AttributeHandlerContext* context); + + protected: + int fLevel; + }; + + + struct IgnoreAttributeHandler : AttributeHandler { + }; + + + struct PackageVersionAttributeHandler : AttributeHandler { + PackageVersionAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue, + BPackageVersionData& versionData, bool notify); + + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + + virtual status_t Delete(AttributeHandlerContext* context); + + private: + BPackageInfoAttributeValue& fPackageInfoValue; + BPackageVersionData& fPackageVersionData; + bool fNotify; + }; + + + struct PackageResolvableAttributeHandler : AttributeHandler { + PackageResolvableAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue); + + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + + virtual status_t Delete(AttributeHandlerContext* context); + + private: + BPackageInfoAttributeValue& fPackageInfoValue; + }; + + + struct PackageResolvableExpressionAttributeHandler + : AttributeHandler { + PackageResolvableExpressionAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue); + + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + + virtual status_t Delete(AttributeHandlerContext* context); + + private: + BPackageInfoAttributeValue& fPackageInfoValue; + }; + + + struct PackageAttributeHandler : AttributeHandler { + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + + private: + BPackageInfoAttributeValue fPackageInfoValue; + }; + + + struct LowLevelAttributeHandler : AttributeHandler { + LowLevelAttributeHandler(); + LowLevelAttributeHandler(uint8 id, + const BPackageAttributeValue& value, void* parentToken, + void* token); + + virtual status_t HandleAttribute( + AttributeHandlerContext* context, uint8 id, + const AttributeValue& value, AttributeHandler** _handler); + virtual status_t Delete(AttributeHandlerContext* context); + + private: + void* fParentToken; + void* fToken; + uint8 fID; + AttributeValue fValue; + }; + + + 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 SinglyLinkedList AttributeHandlerList; + +protected: + const char* CheckCompression( + const SectionInfo& section) const; + + status_t ParseStrings(); + + status_t ParsePackageAttributesSection( + AttributeHandlerContext* context, + AttributeHandler* rootAttributeHandler); + status_t ParseAttributeTree( + AttributeHandlerContext* context, + bool& _sectionHandled); + + virtual status_t ReadAttributeValue(uint8 type, uint8 encoding, + AttributeValue& _value); + + status_t ReadUnsignedLEB128(uint64& _value); + + status_t ReadBuffer(off_t offset, void* buffer, + size_t size); + status_t ReadCompressedBuffer( + const SectionInfo& section); + + inline AttributeHandler* CurrentAttributeHandler() const; + inline void PushAttributeHandler( + AttributeHandler* handler); + inline AttributeHandler* PopAttributeHandler(); + inline void ClearAttributeHandlerStack(); + + inline SectionInfo* CurrentSection(); + inline void SetCurrentSection(SectionInfo* section); + +protected: + SectionInfo fPackageAttributesSection; + +private: + status_t _ParseAttributeTree( + AttributeHandlerContext* context); + + template + inline status_t _Read(Type& _value); + + status_t _ReadSectionBuffer(void* buffer, size_t size); + + status_t _ReadAttribute(uint8& _id, + AttributeValue& _value, + bool* _hasChildren = NULL, + uint64* _tag = NULL); + + status_t _ReadString(const char*& _string, + size_t* _stringLength = NULL); + +private: + BErrorOutput* fErrorOutput; + int fFD; + bool fOwnsFD; + + SectionInfo* fCurrentSection; + + AttributeHandlerList fAttributeHandlerStack; + + uint8* fScratchBuffer; + size_t fScratchBufferSize; +}; + + +inline int +ReaderImplBase::FD() const +{ + return fFD; +} + + +inline BErrorOutput* +ReaderImplBase::ErrorOutput() const +{ + return fErrorOutput; +} + + +ReaderImplBase::SectionInfo* +ReaderImplBase::CurrentSection() +{ + return fCurrentSection; +} + + +void +ReaderImplBase::SetCurrentSection(SectionInfo* section) +{ + fCurrentSection = section; +} + + +template +status_t +ReaderImplBase::_Read(Type& _value) +{ + return _ReadSectionBuffer(&_value, sizeof(Type)); +} + + +inline ReaderImplBase::AttributeHandler* +ReaderImplBase::CurrentAttributeHandler() const +{ + return fAttributeHandlerStack.Head(); +} + + +inline void +ReaderImplBase::PushAttributeHandler(AttributeHandler* handler) +{ + fAttributeHandlerStack.Add(handler); +} + + +inline ReaderImplBase::AttributeHandler* +ReaderImplBase::PopAttributeHandler() +{ + return fAttributeHandlerStack.RemoveHead(); +} + + +inline void +ReaderImplBase::ClearAttributeHandlerStack() +{ + fAttributeHandlerStack.MakeEmpty(); +} + + +} // namespace BPrivate + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit + + +#endif // _PACKAGE__HPKG__V1__PRIVATE__READER_IMPL_BASE_H_ diff --git a/src/build/libpackage/Jamfile b/src/build/libpackage/Jamfile index f35bbc2076..ab111713b9 100644 --- a/src/build/libpackage/Jamfile +++ b/src/build/libpackage/Jamfile @@ -4,6 +4,7 @@ UsePrivateBuildHeaders kernel package shared ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ; +SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg v1 ] ; USES_BE_API on libpackage_build.so = true ; @@ -46,6 +47,18 @@ HPKG_SOURCES = Strings.cpp WriterImplBase.cpp + # V1 support + HPKGDefsV1.cpp + PackageContentHandlerV1.cpp + PackageDataReaderV1.cpp + PackageDataV1.cpp + PackageEntryAttributeV1.cpp + PackageEntryV1.cpp + PackageInfoContentHandlerV1.cpp + PackageReaderImplV1.cpp + PackageReaderV1.cpp + ReaderImplBaseV1.cpp + # compression ZlibCompressionBase.cpp ZlibCompressor.cpp diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile index 8a92e8d7ae..0588901d19 100644 --- a/src/kits/package/Jamfile +++ b/src/kits/package/Jamfile @@ -7,6 +7,7 @@ UsePrivateHeaders shared ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ; +SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg v1 ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package solver ] ; HPKG_SOURCES = @@ -37,6 +38,18 @@ HPKG_SOURCES = Strings.cpp WriterImplBase.cpp + # V1 support + HPKGDefsV1.cpp + PackageContentHandlerV1.cpp + PackageDataReaderV1.cpp + PackageDataV1.cpp + PackageEntryAttributeV1.cpp + PackageEntryV1.cpp + PackageInfoContentHandlerV1.cpp + PackageReaderImplV1.cpp + PackageReaderV1.cpp + ReaderImplBaseV1.cpp + # compression ZlibCompressionBase.cpp ZlibCompressor.cpp diff --git a/src/kits/package/hpkg/v1/HPKGDefsV1.cpp b/src/kits/package/hpkg/v1/HPKGDefsV1.cpp new file mode 100644 index 0000000000..a9093217bc --- /dev/null +++ b/src/kits/package/hpkg/v1/HPKGDefsV1.cpp @@ -0,0 +1,24 @@ +/* + * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +const char* const B_HPKG_PACKAGE_INFO_FILE_NAME = ".PackageInfo"; + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageContentHandlerV1.cpp b/src/kits/package/hpkg/v1/PackageContentHandlerV1.cpp new file mode 100644 index 0000000000..4f026ac2f9 --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageContentHandlerV1.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +// #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.revision", + "package:copyright", + "package:license", + "package:provides", + "package:provides.type", + "package:requires", + "package:supplements", + "package:conflicts", + "package:freshens", + "package:replaces", + "package:resolvable.operator", + "package:checksum", + "package:version.prerelease", + "package:provides.compatible", + "package:url", + "package:source-url", + "package:install-path", + 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 + + +BPackageContentHandler::~BPackageContentHandler() +{ +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp b/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp new file mode 100644 index 0000000000..2057767e1d --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageDataReaderV1.cpp @@ -0,0 +1,469 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +using BHPKG::BPrivate::CachedBufferPutter; +using BHPKG::BPrivate::ZlibDecompressor; + + +// minimum/maximum zlib chunk size we consider sane +static const size_t kMinSaneZlibChunkSize = 1024; +static const size_t kMaxSaneZlibChunkSize = 10 * 1024 * 1024; + +// maximum number of entries in the zlib offset table buffer +static const uint32 kMaxZlibOffsetTableBufferSize = 512; + +static const size_t kUncompressedReaderBufferSize + = B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB; + + +// #pragma mark - BPackageDataReader + + +BPackageDataReader::BPackageDataReader(BDataReader* dataReader) + : + fDataReader(dataReader) +{ +} + + +BPackageDataReader::~BPackageDataReader() +{ +} + + +status_t +BPackageDataReader::ReadData(off_t offset, void* buffer, size_t size) +{ + BBufferDataOutput output(buffer, size); + return ReadDataToOutput(offset, size, &output); +} + + +// #pragma mark - UncompressedPackageDataReader + + +class UncompressedPackageDataReader : public BPackageDataReader { +public: + UncompressedPackageDataReader(BDataReader* dataReader, + BBufferCache* bufferCache) + : + BPackageDataReader(dataReader), + fBufferCache(bufferCache) + { + } + + status_t Init(const BPackageData& data) + { + fOffset = data.Offset(); + fSize = data.UncompressedSize(); + return B_OK; + } + + virtual uint64 Size() const + { + return fSize; + } + + virtual size_t BlockSize() const + { + // TODO: Some other value? + return 64 * 1024; + } + + virtual status_t ReadData(off_t offset, void* buffer, size_t size) + { + if (size == 0) + return B_OK; + + if (offset < 0) + return B_BAD_VALUE; + + if ((uint64)offset > fSize || size > fSize - offset) + return B_BAD_VALUE; + + return fDataReader->ReadData(fOffset + offset, buffer, size); + } + + virtual status_t ReadDataToOutput(off_t offset, size_t size, + BDataOutput* output) + { + if (size == 0) + return B_OK; + + if (offset < 0) + return B_BAD_VALUE; + + if ((uint64)offset > fSize || size > fSize - offset) + return B_BAD_VALUE; + + // get a temporary buffer + CachedBuffer* buffer = fBufferCache->GetBuffer( + kUncompressedReaderBufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + CachedBufferPutter bufferPutter(fBufferCache, &buffer); + + while (size > 0) { + // read into the buffer + size_t toRead = std::min(size, buffer->Size()); + status_t error = fDataReader->ReadData(fOffset + offset, + buffer->Buffer(), toRead); + if (error != B_OK) + return error; + + // write to the output + error = output->WriteData(buffer->Buffer(), toRead); + if (error != B_OK) + return error; + + offset += toRead; + size -= toRead; + } + + return B_OK; + } + +private: + BBufferCache* fBufferCache; + uint64 fOffset; + uint64 fSize; +}; + + +// #pragma mark - ZlibPackageDataReader + + +class ZlibPackageDataReader : public BPackageDataReader { +public: + ZlibPackageDataReader(BDataReader* dataReader, BBufferCache* bufferCache) + : + BPackageDataReader(dataReader), + fBufferCache(bufferCache), + fUncompressBuffer(NULL), + fOffsetTable(NULL) + { + } + + ~ZlibPackageDataReader() + { + delete[] fOffsetTable; + + fBufferCache->PutBuffer(&fUncompressBuffer); + } + + status_t Init(const BPackageData& data) + { + fOffset = data.Offset(); + fCompressedSize = data.CompressedSize(); + fUncompressedSize = data.UncompressedSize(); + fChunkSize = data.ChunkSize(); + + // validate chunk size + if (fChunkSize == 0) + fChunkSize = B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB; + if (fChunkSize < kMinSaneZlibChunkSize + || fChunkSize > kMaxSaneZlibChunkSize) { + return B_BAD_DATA; + } + + fChunkCount = (fUncompressedSize + (fChunkSize - 1)) / fChunkSize; + fOffsetTableSize = (fChunkCount - 1) * sizeof(uint64); + if (fOffsetTableSize >= fCompressedSize) + return B_BAD_DATA; + + // allocate a buffer for the offset table + if (fChunkCount > 1) { + fOffsetTableBufferEntryCount = std::min(fChunkCount - 1, + (uint64)kMaxZlibOffsetTableBufferSize); + fOffsetTable = new(std::nothrow) uint64[ + fOffsetTableBufferEntryCount]; + if (fOffsetTable == NULL) + return B_NO_MEMORY; + + fOffsetTableIndex = -1; + // mark the table content invalid + } else + fChunkSize = fUncompressedSize; + + // mark uncompressed content invalid + fUncompressedChunk = -1; + + return B_OK; + } + + virtual uint64 Size() const + { + return fUncompressedSize; + } + + virtual size_t BlockSize() const + { + return fChunkSize; + } + + virtual status_t ReadDataToOutput(off_t offset, size_t size, + BDataOutput* output) + { + // check offset and size + if (size == 0) + return B_OK; + + if (offset < 0) + return B_BAD_VALUE; + + if ((uint64)offset > fUncompressedSize + || size > fUncompressedSize - offset) { + return B_BAD_VALUE; + } + + // get our uncompressed chunk buffer back, if possible + bool newBuffer; + if (fBufferCache->GetBuffer(fChunkSize, &fUncompressBuffer, &newBuffer) + == NULL) { + return B_NO_MEMORY; + } + CachedBufferPutter uncompressBufferPutter(fBufferCache, + &fUncompressBuffer); + + if (newBuffer) + fUncompressedChunk = -1; + + // uncompress + int64 chunkIndex = offset / fChunkSize; + off_t chunkOffset = chunkIndex * fChunkSize; + size_t inChunkOffset = offset - chunkOffset; + + while (size > 0) { + // read and uncompress the chunk + status_t error = _ReadChunk(chunkIndex); + if (error != B_OK) + return error; + + // write data to output + size_t toCopy = std::min(size, (size_t)fChunkSize - inChunkOffset); + error = output->WriteData( + (uint8*)fUncompressBuffer->Buffer() + inChunkOffset, toCopy); + if (error != B_OK) + return error; + + size -= toCopy; + + chunkIndex++; + chunkOffset += fChunkSize; + inChunkOffset = 0; + } + + return B_OK; + } + +private: + status_t _ReadChunk(int64 chunkIndex) + { + if (chunkIndex == fUncompressedChunk) + return B_OK; + + // get the chunk offset and size + uint64 offset; + uint32 compressedSize; + status_t error = _GetCompressedChunkOffsetAndSize(chunkIndex, offset, + compressedSize); + if (error != B_OK) + return error; + + uint32 uncompressedSize = (uint64)chunkIndex + 1 < fChunkCount + ? fChunkSize : fUncompressedSize - chunkIndex * fChunkSize; + + // read the chunk + if (compressedSize == uncompressedSize) { + // the chunk is not compressed -- read it directly into the + // uncompressed buffer + error = fDataReader->ReadData(offset, fUncompressBuffer->Buffer(), + compressedSize); + } else { + // read to a read buffer and uncompress + CachedBuffer* readBuffer = fBufferCache->GetBuffer(fChunkSize); + if (readBuffer == NULL) + return B_NO_MEMORY; + CachedBufferPutter readBufferPutter(fBufferCache, readBuffer); + + error = fDataReader->ReadData(offset, readBuffer->Buffer(), + compressedSize); + if (error != B_OK) + return error; + + size_t actuallyUncompressedSize; + error = ZlibDecompressor::DecompressSingleBuffer( + readBuffer->Buffer(), compressedSize, + fUncompressBuffer->Buffer(), uncompressedSize, + actuallyUncompressedSize); + if (error == B_OK && actuallyUncompressedSize != uncompressedSize) + error = B_BAD_DATA; + } + + if (error != B_OK) { + // error reading/decompressing data -- mark the cached data invalid + fUncompressedChunk = -1; + return error; + } + + fUncompressedChunk = chunkIndex; + return B_OK; + } + + status_t _GetCompressedChunkOffsetAndSize(int64 chunkIndex, uint64& _offset, + uint32& _size) + { + // get the offset + uint64 offset; + if (chunkIndex == 0) { + // first chunk is at 0 + offset = 0; + } else { + status_t error = _GetCompressedChunkRelativeOffset(chunkIndex, + offset); + if (error != B_OK) + return error; + } + + // get the end offset + uint64 endOffset; + if ((uint64)chunkIndex + 1 == fChunkCount) { + // last chunk end with the end of the data + endOffset = fCompressedSize - fOffsetTableSize; + } else { + status_t error = _GetCompressedChunkRelativeOffset(chunkIndex + 1, + endOffset); + if (error != B_OK) + return error; + } + + // sanity check + if (endOffset < offset) + return B_BAD_DATA; + + _offset = fOffset + fOffsetTableSize + offset; + _size = endOffset - offset; + return B_OK; + } + + status_t _GetCompressedChunkRelativeOffset(int64 chunkIndex, + uint64& _offset) + { + if (fOffsetTableIndex < 0 || fOffsetTableIndex > chunkIndex + || fOffsetTableIndex + fOffsetTableBufferEntryCount <= chunkIndex) { + // read the table at the given index, or, if we can, the whole table + int64 readAtIndex = fChunkCount - 1 > fOffsetTableBufferEntryCount + ? chunkIndex : 1; + uint32 entriesToRead = std::min( + (uint64)fOffsetTableBufferEntryCount, + fChunkCount - readAtIndex); + + status_t error = fDataReader->ReadData( + fOffset + (readAtIndex - 1) * sizeof(uint64), + fOffsetTable, entriesToRead * sizeof(uint64)); + if (error != B_OK) { + fOffsetTableIndex = -1; + return error; + } + + fOffsetTableIndex = readAtIndex; + } + + // get and check the offset + _offset = fOffsetTable[chunkIndex - fOffsetTableIndex]; + if (_offset > fCompressedSize - fOffsetTableSize) + return B_BAD_DATA; + + return B_OK; + } + +private: + BBufferCache* fBufferCache; + CachedBuffer* fUncompressBuffer; + int64 fUncompressedChunk; + + uint64 fOffset; + uint64 fUncompressedSize; + uint64 fCompressedSize; + uint64 fOffsetTableSize; + uint64 fChunkCount; + uint32 fChunkSize; + uint32 fOffsetTableBufferEntryCount; + uint64* fOffsetTable; + int32 fOffsetTableIndex; +}; + + +// #pragma mark - BPackageDataReaderFactory + + +BPackageDataReaderFactory::BPackageDataReaderFactory(BBufferCache* bufferCache) + : + fBufferCache(bufferCache) +{ +} + + +status_t +BPackageDataReaderFactory::CreatePackageDataReader(BDataReader* dataReader, + const BPackageData& data, BPackageDataReader*& _reader) +{ + BPackageDataReader* reader; + + switch (data.Compression()) { + case B_HPKG_COMPRESSION_NONE: + reader = new(std::nothrow) UncompressedPackageDataReader( + dataReader, fBufferCache); + break; + case B_HPKG_COMPRESSION_ZLIB: + reader = new(std::nothrow) ZlibPackageDataReader(dataReader, + fBufferCache); + break; + default: + return B_BAD_VALUE; + } + + if (reader == NULL) + return B_NO_MEMORY; + + status_t error = reader->Init(data); + if (error != B_OK) { + delete reader; + return error; + } + + _reader = reader; + return B_OK; +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageDataV1.cpp b/src/kits/package/hpkg/v1/PackageDataV1.cpp new file mode 100644 index 0000000000..a52ed9d954 --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageDataV1.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +using namespace BPrivate; + + +BPackageData::BPackageData() + : + fCompressedSize(0), + fUncompressedSize(0), + fChunkSize(0), + fCompression(B_HPKG_COMPRESSION_NONE), + fEncodedInline(true) +{ +} + + +void +BPackageData::SetData(uint64 size, uint64 offset) +{ + fUncompressedSize = fCompressedSize = size; + fOffset = offset; + fEncodedInline = false; +} + + +void +BPackageData::SetData(uint8 size, const void* data) +{ + fUncompressedSize = fCompressedSize = size; + if (size > 0) + memcpy(fInlineData, data, size); + fEncodedInline = true; +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageEntryAttributeV1.cpp b/src/kits/package/hpkg/v1/PackageEntryAttributeV1.cpp new file mode 100644 index 0000000000..97694f7d48 --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageEntryAttributeV1.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +BPackageEntryAttribute::BPackageEntryAttribute(const char* name) + : + fName(name), + fType(0) +{ +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageEntryV1.cpp b/src/kits/package/hpkg/v1/PackageEntryV1.cpp new file mode 100644 index 0000000000..963432b7cb --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageEntryV1.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +BPackageEntry::BPackageEntry(BPackageEntry* parent, const char* name) + : + fParent(parent), + fName(name), + fUserToken(NULL), + fMode(S_IFREG | S_IRUSR | S_IRGRP | S_IROTH), + fSymlinkPath(NULL) +{ + fAccessTime.tv_sec = 0; + fAccessTime.tv_nsec = 0; + fModifiedTime.tv_sec = 0; + fModifiedTime.tv_nsec = 0; + fCreationTime.tv_sec = 0; + fCreationTime.tv_nsec = 0; +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageInfoContentHandlerV1.cpp b/src/kits/package/hpkg/v1/PackageInfoContentHandlerV1.cpp new file mode 100644 index 0000000000..3c9359701d --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageInfoContentHandlerV1.cpp @@ -0,0 +1,166 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +BPackageInfoContentHandler::BPackageInfoContentHandler( + BPackageInfo& packageInfo, BErrorOutput* errorOutput) + : + fPackageInfo(packageInfo), + fErrorOutput(errorOutput) +{ +} + + +BPackageInfoContentHandler::~BPackageInfoContentHandler() +{ +} + + +status_t +BPackageInfoContentHandler::HandleEntry(BPackageEntry* entry) +{ + return B_OK; +} + + +status_t +BPackageInfoContentHandler::HandleEntryAttribute(BPackageEntry* entry, + BPackageEntryAttribute* attribute) +{ + return B_OK; +} + + +status_t +BPackageInfoContentHandler::HandleEntryDone(BPackageEntry* entry) +{ + return B_OK; +} + + +status_t +BPackageInfoContentHandler::HandlePackageAttribute( + const BPackageInfoAttributeValue& value) +{ + switch (value.attributeID) { + case B_PACKAGE_INFO_NAME: + fPackageInfo.SetName(value.string); + break; + + case B_PACKAGE_INFO_SUMMARY: + fPackageInfo.SetSummary(value.string); + break; + + case B_PACKAGE_INFO_DESCRIPTION: + fPackageInfo.SetDescription(value.string); + break; + + case B_PACKAGE_INFO_VENDOR: + fPackageInfo.SetVendor(value.string); + break; + + case B_PACKAGE_INFO_PACKAGER: + fPackageInfo.SetPackager(value.string); + break; + + case B_PACKAGE_INFO_FLAGS: + fPackageInfo.SetFlags(value.unsignedInt); + break; + + case B_PACKAGE_INFO_ARCHITECTURE: + fPackageInfo.SetArchitecture( + (BPackageArchitecture)value.unsignedInt); + break; + + case B_PACKAGE_INFO_VERSION: + fPackageInfo.SetVersion(value.version); + break; + + case B_PACKAGE_INFO_COPYRIGHTS: + fPackageInfo.AddCopyright(value.string); + break; + + case B_PACKAGE_INFO_LICENSES: + fPackageInfo.AddLicense(value.string); + break; + + case B_PACKAGE_INFO_PROVIDES: + fPackageInfo.AddProvides(value.resolvable); + break; + + case B_PACKAGE_INFO_REQUIRES: + fPackageInfo.AddRequires(value.resolvableExpression); + break; + + case B_PACKAGE_INFO_SUPPLEMENTS: + fPackageInfo.AddSupplements(value.resolvableExpression); + break; + + case B_PACKAGE_INFO_CONFLICTS: + fPackageInfo.AddConflicts(value.resolvableExpression); + break; + + case B_PACKAGE_INFO_FRESHENS: + fPackageInfo.AddFreshens(value.resolvableExpression); + break; + + case B_PACKAGE_INFO_REPLACES: + fPackageInfo.AddReplaces(value.string); + break; + + case B_PACKAGE_INFO_URLS: + fPackageInfo.AddURL(value.string); + break; + + case B_PACKAGE_INFO_SOURCE_URLS: + fPackageInfo.AddSourceURL(value.string); + break; + + case B_PACKAGE_INFO_CHECKSUM: + fPackageInfo.SetChecksum(value.string); + break; + + case B_PACKAGE_INFO_INSTALL_PATH: + fPackageInfo.SetInstallPath(value.string); + break; + + default: + if (fErrorOutput != NULL) { + fErrorOutput->PrintError( + "Invalid package attribute section: unexpected package " + "attribute id %d encountered\n", value.attributeID); + } + return B_BAD_DATA; + } + + return B_OK; +} + + +void +BPackageInfoContentHandler::HandleErrorOccurred() +{ +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageReaderImplV1.cpp b/src/kits/package/hpkg/v1/PackageReaderImplV1.cpp new file mode 100644 index 0000000000..5fa75d5218 --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageReaderImplV1.cpp @@ -0,0 +1,742 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * 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 V1 { + +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; + + +// #pragma mark - DataAttributeHandler + + +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 HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_DATA_SIZE: + fData->SetUncompressedSize(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_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 B_HPKG_ATTRIBUTE_ID_DATA_CHUNK_SIZE: + fData->SetChunkSize(value.unsignedInt); + return B_OK; + } + + return AttributeHandler::HandleAttribute(context, id, value, _handler); + } + +private: + BPackageData* fData; +}; + + +// #pragma mark - AttributeAttributeHandler + + +struct PackageReaderImpl::AttributeAttributeHandler : AttributeHandler { + AttributeAttributeHandler(BPackageEntry* entry, const char* name) + : + fEntry(entry), + fAttribute(name) + { + } + + virtual status_t HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + 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); + + case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE: + fAttribute.SetType(value.unsignedInt); + return B_OK; + } + + return AttributeHandler::HandleAttribute(context, id, 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; +}; + + +// #pragma mark - EntryAttributeHandler + + +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 HandleAttribute(AttributeHandlerContext* context, + uint8 id, const AttributeValue& value, AttributeHandler** _handler) + { + switch (id) { + case B_HPKG_ATTRIBUTE_ID_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 B_HPKG_ATTRIBUTE_ID_FILE_TYPE: + return _SetFileType(context, value.unsignedInt); + + case B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS: + fEntry.SetPermissions(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_USER: + case B_HPKG_ATTRIBUTE_ID_FILE_GROUP: + // TODO:... + break; + + case B_HPKG_ATTRIBUTE_ID_FILE_ATIME: + fEntry.SetAccessTime(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_MTIME: + fEntry.SetModifiedTime(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_CRTIME: + fEntry.SetCreationTime(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_ATIME_NANOS: + fEntry.SetAccessTimeNanos(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_MTIME_NANOS: + fEntry.SetModifiedTimeNanos(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_FILE_CRTIM_NANOS: + fEntry.SetCreationTimeNanos(value.unsignedInt); + return B_OK; + + case B_HPKG_ATTRIBUTE_ID_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 B_HPKG_ATTRIBUTE_ID_DATA: + if (_handler != NULL) { + return DataAttributeHandler::Create(context, &fEntry.Data(), + value, *_handler); + } + return DataAttributeHandler::InitData(context, &fEntry.Data(), + value); + + case B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH: + fEntry.SetSymlinkPath(value.string); + return B_OK; + } + + return AttributeHandler::HandleAttribute(context, id, 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; +}; + + +// #pragma mark - RootAttributeHandler + + +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); + } + return B_OK; + } + + return inherited::HandleAttribute(context, id, value, _handler); + } +}; + + +// #pragma mark - PackageReaderImpl + + +PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput) + : + inherited(errorOutput), + fTOCSection("TOC") +{ +} + + +PackageReaderImpl::~PackageReaderImpl() +{ +} + + +status_t +PackageReaderImpl::Init(const char* fileName) +{ + // open file + int fd = open(fileName, O_RDONLY); + if (fd < 0) { + ErrorOutput()->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) +{ + status_t error = inherited::Init(fd, keepFD); + if (error != B_OK) + return error; + + // stat it + struct stat st; + if (fstat(FD(), &st) < 0) { + ErrorOutput()->PrintError("Error: Failed to access package file: %s\n", + strerror(errno)); + return errno; + } + + // read the header + hpkg_header header; + if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK) + return error; + + // check the header + + // magic + if (B_BENDIAN_TO_HOST_INT32(header.magic) != B_HPKG_MAGIC) { + ErrorOutput()->PrintError("Error: Invalid package file: Invalid " + "magic\n"); + return B_BAD_DATA; + } + + // version + if (B_BENDIAN_TO_HOST_INT16(header.version) != B_HPKG_VERSION) { + ErrorOutput()->PrintError("Error: Invalid/unsupported package file " + "version (%d)\n", B_BENDIAN_TO_HOST_INT16(header.version)); + return B_MISMATCHED_VALUES; + } + + // header size + fHeapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); + if ((size_t)fHeapOffset < sizeof(hpkg_header)) { + ErrorOutput()->PrintError("Error: Invalid package file: Invalid header " + "size (%llu)\n", fHeapOffset); + return B_BAD_DATA; + } + + // total size + fTotalSize = B_BENDIAN_TO_HOST_INT64(header.total_size); + if (fTotalSize != (uint64)st.st_size) { + ErrorOutput()->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)) { + ErrorOutput()->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)) { + ErrorOutput()->PrintError("Error: Invalid package file: TOC section: " + "%s\n", errorString); + return B_BAD_DATA; + } + + // TOC subsections + fTOCSection.stringsLength + = B_BENDIAN_TO_HOST_INT64(header.toc_strings_length); + fTOCSection.stringsCount + = B_BENDIAN_TO_HOST_INT64(header.toc_strings_count); + + if (fTOCSection.stringsLength > fTOCSection.uncompressedLength + || fTOCSection.stringsCount > fTOCSection.stringsLength) { + ErrorOutput()->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) { + ErrorOutput()->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) { + ErrorOutput()->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) { + ErrorOutput()->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; + } + + // read in the complete TOC + fTOCSection.data + = new(std::nothrow) uint8[fTOCSection.uncompressedLength]; + if (fTOCSection.data == NULL) { + ErrorOutput()->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) { + ErrorOutput()->PrintError("Error: Out of memory!\n"); + return B_NO_MEMORY; + } + error = ReadCompressedBuffer(fPackageAttributesSection); + if (error != B_OK) + return error; + + // start parsing the TOC + fTOCSection.currentOffset = 0; + SetCurrentSection(&fTOCSection); + + // strings + error = ParseStrings(); + if (error != B_OK) + return error; + + // parse strings from package attributes section + fPackageAttributesSection.currentOffset = 0; + SetCurrentSection(&fPackageAttributesSection); + + // strings + error = ParseStrings(); + if (error != B_OK) + return error; + + SetCurrentSection(NULL); + + return B_OK; +} + + +status_t +PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler) +{ + AttributeHandlerContext context(ErrorOutput(), contentHandler, + B_HPKG_SECTION_PACKAGE_ATTRIBUTES); + RootAttributeHandler rootAttributeHandler; + + status_t error + = ParsePackageAttributesSection(&context, &rootAttributeHandler); + + if (error == B_OK) { + context.section = B_HPKG_SECTION_PACKAGE_TOC; + error = _ParseTOC(&context, &rootAttributeHandler); + } + + return error; +} + + +status_t +PackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler) +{ + AttributeHandlerContext context(ErrorOutput(), contentHandler, + B_HPKG_SECTION_PACKAGE_ATTRIBUTES); + LowLevelAttributeHandler rootAttributeHandler; + + status_t error + = ParsePackageAttributesSection(&context, &rootAttributeHandler); + + if (error == B_OK) { + context.section = B_HPKG_SECTION_PACKAGE_TOC; + error = _ParseTOC(&context, &rootAttributeHandler); + } + + return error; +} + + +status_t +PackageReaderImpl::_ParseTOC(AttributeHandlerContext* context, + AttributeHandler* rootAttributeHandler) +{ + // parse the TOC + fTOCSection.currentOffset = fTOCSection.stringsLength; + SetCurrentSection(&fTOCSection); + + // prepare attribute handler context + context->heapOffset = fHeapOffset; + context->heapSize = fHeapSize; + + // init the attribute handler stack + rootAttributeHandler->SetLevel(0); + ClearAttributeHandlerStack(); + PushAttributeHandler(rootAttributeHandler); + + bool sectionHandled; + status_t error = ParseAttributeTree(context, sectionHandled); + if (error == B_OK && sectionHandled) { + if (fTOCSection.currentOffset < fTOCSection.uncompressedLength) { + ErrorOutput()->PrintError("Error: %llu excess byte(s) in TOC " + "section\n", + fTOCSection.uncompressedLength - fTOCSection.currentOffset); + error = B_BAD_DATA; + } + } + + // 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::ReadAttributeValue(uint8 type, uint8 encoding, + AttributeValue& _value) +{ + switch (type) { + 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) { + ErrorOutput()->PrintError("Error: Invalid %s section: " + "invalid data reference\n", CurrentSection()->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) { + ErrorOutput()->PrintError("Error: Invalid %s section: " + "inline data too long\n", CurrentSection()->name); + return B_BAD_DATA; + } + + const void* buffer; + error = _GetTOCBuffer(size, buffer); + if (error != B_OK) + return error; + _value.SetToData(size, buffer); + } else { + ErrorOutput()->PrintError("Error: Invalid %s section: invalid " + "raw encoding (%u)\n", CurrentSection()->name, encoding); + return B_BAD_DATA; + } + + return B_OK; + } + + default: + return inherited::ReadAttributeValue(type, encoding, _value); + } +} + + +status_t +PackageReaderImpl::_GetTOCBuffer(size_t size, const void*& _buffer) +{ + if (size > fTOCSection.uncompressedLength - fTOCSection.currentOffset) { + ErrorOutput()->PrintError("_GetTOCBuffer(%lu): read beyond TOC end\n", + size); + return B_BAD_DATA; + } + + _buffer = fTOCSection.data + fTOCSection.currentOffset; + fTOCSection.currentOffset += size; + return B_OK; +} + + +} // namespace BPrivate + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/PackageReaderV1.cpp b/src/kits/package/hpkg/v1/PackageReaderV1.cpp new file mode 100644 index 0000000000..eeae757cbc --- /dev/null +++ b/src/kits/package/hpkg/v1/PackageReaderV1.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + + +BPackageReader::BPackageReader(BErrorOutput* errorOutput) + : + fImpl(new (std::nothrow) PackageReaderImpl(errorOutput)) +{ +} + + +BPackageReader::~BPackageReader() +{ + delete fImpl; +} + + +status_t +BPackageReader::Init(const char* fileName) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->Init(fileName); +} + + +status_t +BPackageReader::Init(int fd, bool keepFD) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->Init(fd, keepFD); +} + + +status_t +BPackageReader::ParseContent(BPackageContentHandler* contentHandler) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->ParseContent(contentHandler); +} + + +status_t +BPackageReader::ParseContent(BLowLevelPackageContentHandler* contentHandler) +{ + if (fImpl == NULL) + return B_NO_INIT; + + return fImpl->ParseContent(contentHandler); +} + + +int +BPackageReader::PackageFileFD() +{ + if (fImpl == NULL) + return -1; + + return fImpl->PackageFileFD(); +} + + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit diff --git a/src/kits/package/hpkg/v1/ReaderImplBaseV1.cpp b/src/kits/package/hpkg/v1/ReaderImplBaseV1.cpp new file mode 100644 index 0000000000..d902e19b18 --- /dev/null +++ b/src/kits/package/hpkg/v1/ReaderImplBaseV1.cpp @@ -0,0 +1,1089 @@ +/* + * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Oliver Tappe + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +namespace BPackageKit { + +namespace BHPKG { + +namespace V1 { + +namespace BPrivate { + + +using BHPKG::BPrivate::ZlibDecompressor; + + +static const size_t kScratchBufferSize = 64 * 1024; + + +// #pragma mark - AttributeHandlerContext + + +ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( + BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, + BHPKGPackageSectionID section) + : + errorOutput(errorOutput), + packageContentHandler(packageContentHandler), + hasLowLevelHandler(false), + section(section) +{ +} + + +ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( + BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, + BHPKGPackageSectionID section) + : + errorOutput(errorOutput), + lowLevelHandler(lowLevelHandler), + hasLowLevelHandler(true), + section(section) +{ +} + + +void +ReaderImplBase::AttributeHandlerContext::ErrorOccurred() +{ + if (hasLowLevelHandler) + lowLevelHandler->HandleErrorOccurred(); + else + packageContentHandler->HandleErrorOccurred(); +} + + +// #pragma mark - AttributeHandler + + +ReaderImplBase::AttributeHandler::~AttributeHandler() +{ +} + + +void +ReaderImplBase::AttributeHandler::SetLevel(int level) +{ + fLevel = level; +} + + +status_t +ReaderImplBase::AttributeHandler::HandleAttribute( + AttributeHandlerContext* context, uint8 id, const AttributeValue& value, + AttributeHandler** _handler) +{ + return B_OK; +} + + +status_t +ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) +{ + delete this; + return B_OK; +} + + +// #pragma mark - PackageVersionAttributeHandler + + +ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue, + BPackageVersionData& versionData, bool notify) + : + fPackageInfoValue(packageInfoValue), + fPackageVersionData(versionData), + fNotify(notify) +{ +} + + +status_t +ReaderImplBase::PackageVersionAttributeHandler::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_PRE_RELEASE: + fPackageVersionData.preRelease = value.string; + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION: + fPackageVersionData.revision = 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; +} + + +status_t +ReaderImplBase::PackageVersionAttributeHandler::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; +} + + +// #pragma mark - PackageResolvableAttributeHandler + + +ReaderImplBase::PackageResolvableAttributeHandler + ::PackageResolvableAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue) + : + fPackageInfoValue(packageInfoValue) +{ +} + + +status_t +ReaderImplBase::PackageResolvableAttributeHandler::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; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE: + fPackageInfoValue.resolvable.haveCompatibleVersion = true; + fPackageInfoValue.resolvable.compatibleVersion.major = value.string; + if (_handler != NULL) { + *_handler + = new(std::nothrow) PackageVersionAttributeHandler( + fPackageInfoValue, + fPackageInfoValue.resolvable.compatibleVersion, 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; +} + + +status_t +ReaderImplBase::PackageResolvableAttributeHandler::Delete( + AttributeHandlerContext* context) +{ + status_t error = context->packageContentHandler->HandlePackageAttribute( + fPackageInfoValue); + fPackageInfoValue.Clear(); + + delete this; + return error; +} + + +// #pragma mark - PackageResolvableExpressionAttributeHandler + + +ReaderImplBase::PackageResolvableExpressionAttributeHandler + ::PackageResolvableExpressionAttributeHandler( + BPackageInfoAttributeValue& packageInfoValue) + : + fPackageInfoValue(packageInfoValue) +{ +} + + +status_t +ReaderImplBase::PackageResolvableExpressionAttributeHandler::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; +} + + +status_t +ReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete( + AttributeHandlerContext* context) +{ + status_t error = context->packageContentHandler->HandlePackageAttribute( + fPackageInfoValue); + fPackageInfoValue.Clear(); + + delete this; + return error; +} + + +// #pragma mark - PackageAttributeHandler + + +status_t +ReaderImplBase::PackageAttributeHandler::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_URL: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, 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; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); + break; + + case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH: + fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, 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; +} + + +// #pragma mark - LowLevelAttributeHandler + + +ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() + : + fParentToken(NULL), + fToken(NULL), + fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) +{ +} + + +ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, + const BPackageAttributeValue& value, void* parentToken, void* token) + : + fParentToken(NULL), + fToken(token), + fID(id), + fValue(value) +{ +} + + +status_t +ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( + AttributeHandlerContext* context, uint8 id, const AttributeValue& value, + AttributeHandler** _handler) +{ + // notify the content handler + void* token; + status_t error = context->lowLevelHandler->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) LowLevelAttributeHandler(id, value, + fToken, token); + if (*_handler == NULL) { + context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, + value, fToken, token); + return B_NO_MEMORY; + } + return B_OK; + } + + // no children -- just call the done hook + return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, + value, fToken, token); +} + + +status_t +ReaderImplBase::LowLevelAttributeHandler::Delete( + AttributeHandlerContext* context) +{ + status_t error = B_OK; + if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { + error = context->lowLevelHandler->HandleAttributeDone( + (BHPKGAttributeID)fID, fValue, fParentToken, fToken); + } + + delete this; + return error; +} + + +// #pragma mark - ReaderImplBase + + +ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput) + : + fPackageAttributesSection("package attributes"), + fErrorOutput(errorOutput), + fFD(-1), + fOwnsFD(false), + fCurrentSection(NULL), + fScratchBuffer(NULL), + fScratchBufferSize(0) +{ +} + + +ReaderImplBase::~ReaderImplBase() +{ + if (fOwnsFD && fFD >= 0) + close(fFD); + + delete[] fScratchBuffer; +} + + +status_t +ReaderImplBase::Init(int fd, bool keepFD) +{ + fFD = fd; + fOwnsFD = keepFD; + + // 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; + + return B_OK; +} + + +const char* +ReaderImplBase::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 +ReaderImplBase::ParseStrings() +{ + // allocate table, if there are any strings + if (fCurrentSection->stringsCount == 0) { + fCurrentSection->currentOffset += fCurrentSection->stringsLength; + return B_OK; + } + + 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; + } + + fCurrentSection->currentOffset += fCurrentSection->stringsLength; + + 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 +ReaderImplBase::ParsePackageAttributesSection( + AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) +{ + // parse package attributes + SetCurrentSection(&fPackageAttributesSection); + + // init the attribute handler stack + rootAttributeHandler->SetLevel(0); + ClearAttributeHandlerStack(); + PushAttributeHandler(rootAttributeHandler); + + bool sectionHandled; + status_t error = ParseAttributeTree(context, sectionHandled); + if (error == B_OK && sectionHandled) { + 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; + } + } + + SetCurrentSection(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 +ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, + bool& _sectionHandled) +{ + if (context->hasLowLevelHandler) { + bool handleSection = false; + status_t error = context->lowLevelHandler->HandleSectionStart( + context->section, handleSection); + if (error != B_OK) + return error; + + if (!handleSection) { + _sectionHandled = false; + return B_OK; + } + } + + status_t error = _ParseAttributeTree(context); + + if (context->hasLowLevelHandler) { + status_t endError = context->lowLevelHandler->HandleSectionEnd( + context->section); + if (error == B_OK) + error = endError; + } + + _sectionHandled = true; + return error; +} + + +status_t +ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) +{ + int level = 0; + + while (true) { + uint8 id; + AttributeValue value; + bool hasChildren; + uint64 tag; + + status_t error = _ReadAttribute(id, value, &hasChildren, &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; + } + + AttributeHandler* childHandler = NULL; + error = CurrentAttributeHandler()->HandleAttribute(context, id, 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); + } + } +} + + +status_t +ReaderImplBase::_ReadAttribute(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 = attribute_tag_type(tag); + if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { + 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, attribute_tag_encoding(tag), + _value); + if (error != B_OK) + return error; + + _id = 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 = attribute_tag_has_children(tag); + if (_tag != NULL) + *_tag = tag; + + return B_OK; +} + + +status_t +ReaderImplBase::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; + } + + default: + fErrorOutput->PrintError("Error: Invalid %s section: invalid " + "value type: %d\n", fCurrentSection->name, type); + return B_BAD_DATA; + } +} + + +status_t +ReaderImplBase::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 +ReaderImplBase::_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 +ReaderImplBase::_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 +ReaderImplBase::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 +ReaderImplBase::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((size_t)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: + { + fErrorOutput->PrintError("Error: Invalid compression type: %u\n", + section.compression); + return B_BAD_DATA; + } + } +} + + +} // namespace BPrivate + +} // namespace V1 + +} // namespace BHPKG + +} // namespace BPackageKit