From 47039b852eeebb91396d19e0f9313cf23bf535ee Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 22 May 2013 00:20:13 +0200 Subject: [PATCH] Package/repository file format: Add a minor version header field * Add minor_version to hpkg_header and hpkg_repo_header and make heap_compression uint16. * If the minor version of a package/repository file is greater than the current one unknown attributes are ignored without error. This allows introducing new harmless attributes without making the resulting files unreadable for older package kit versions. --- headers/os/package/hpkg/HPKGDefs.h | 10 ++++++---- headers/private/package/hpkg/HPKGDefsPrivate.h | 6 ++++-- headers/private/package/hpkg/ReaderImplBase.h | 17 +++++++++++++---- src/kits/package/hpkg/PackageReaderImpl.cpp | 6 ++++-- src/kits/package/hpkg/PackageWriterImpl.cpp | 3 ++- src/kits/package/hpkg/ReaderImplBase.cpp | 18 ++++++++++++++++-- src/kits/package/hpkg/RepositoryReaderImpl.cpp | 3 ++- src/kits/package/hpkg/RepositoryWriterImpl.cpp | 1 + 8 files changed, 48 insertions(+), 16 deletions(-) diff --git a/headers/os/package/hpkg/HPKGDefs.h b/headers/os/package/hpkg/HPKGDefs.h index 9f1029e5e3..f1e2ed58fa 100644 --- a/headers/os/package/hpkg/HPKGDefs.h +++ b/headers/os/package/hpkg/HPKGDefs.h @@ -16,11 +16,13 @@ namespace BHPKG { // magic & version of package and repository files enum { - B_HPKG_MAGIC = 'hpkg', - B_HPKG_VERSION = 2, + B_HPKG_MAGIC = 'hpkg', + B_HPKG_VERSION = 2, + B_HPKG_MINOR_VERSION = 0, // - B_HPKG_REPO_MAGIC = 'hpkr', - B_HPKG_REPO_VERSION = 2 + B_HPKG_REPO_MAGIC = 'hpkr', + B_HPKG_REPO_VERSION = 2, + B_HPKG_REPO_MINOR_VERSION = 0 }; diff --git a/headers/private/package/hpkg/HPKGDefsPrivate.h b/headers/private/package/hpkg/HPKGDefsPrivate.h index ce8837dd34..cfc614366a 100644 --- a/headers/private/package/hpkg/HPKGDefsPrivate.h +++ b/headers/private/package/hpkg/HPKGDefsPrivate.h @@ -24,9 +24,10 @@ struct hpkg_header { uint16 header_size; uint16 version; uint64 total_size; + uint16 minor_version; // heap - uint32 heap_compression; + uint16 heap_compression; uint32 heap_chunk_size; uint64 heap_size_compressed; uint64 heap_size_uncompressed; @@ -50,9 +51,10 @@ struct hpkg_repo_header { uint16 header_size; uint16 version; uint64 total_size; + uint16 minor_version; // heap - uint32 heap_compression; + uint16 heap_compression; uint32 heap_chunk_size; uint64 heap_size_compressed; uint64 heap_size_uncompressed; diff --git a/headers/private/package/hpkg/ReaderImplBase.h b/headers/private/package/hpkg/ReaderImplBase.h index 53248127ea..de25a3fa59 100644 --- a/headers/private/package/hpkg/ReaderImplBase.h +++ b/headers/private/package/hpkg/ReaderImplBase.h @@ -72,6 +72,9 @@ protected: BErrorOutput* ErrorOutput() const; + uint16 MinorFormatVersion() const + { return fMinorFormatVersion; } + uint64 UncompressedHeapSize() const; PackageFileHeapReader* RawHeapReader() const @@ -175,6 +178,7 @@ private: BErrorOutput* fErrorOutput; int fFD; bool fOwnsFD; + uint16 fMinorFormatVersion; PackageFileHeapReader* fRawHeapReader; BAbstractBufferedDataReader* fHeapReader; @@ -199,7 +203,8 @@ public: BLowLevelPackageContentHandler* lowLevelHandler; }; bool hasLowLevelHandler; - + bool ignoreUnknownAttributes; + BHPKGPackageSectionID section; public: @@ -207,12 +212,14 @@ public: BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, - BHPKGPackageSectionID section); + BHPKGPackageSectionID section, + bool ignoreUnknownAttributes); AttributeHandlerContext( BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, - BHPKGPackageSectionID section); + BHPKGPackageSectionID section, + bool ignoreUnknownAttributes); void ErrorOccurred(); }; @@ -375,6 +382,8 @@ ReaderImplBase::Init(int fd, bool keepFD, Header& header, uint32 flags) return B_MISMATCHED_VALUES; } + fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version); + // header size uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size); if (heapOffset < (off_t)sizeof(header)) { @@ -405,7 +414,7 @@ ReaderImplBase::Init(int fd, bool keepFD, Header& header, uint32 flags) } error = InitHeapReader( - B_BENDIAN_TO_HOST_INT32(header.heap_compression), + B_BENDIAN_TO_HOST_INT16(header.heap_compression), B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset, compressedHeapSize, B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed)); diff --git a/src/kits/package/hpkg/PackageReaderImpl.cpp b/src/kits/package/hpkg/PackageReaderImpl.cpp index 83ff096de7..370a89ae4d 100644 --- a/src/kits/package/hpkg/PackageReaderImpl.cpp +++ b/src/kits/package/hpkg/PackageReaderImpl.cpp @@ -375,7 +375,8 @@ status_t PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler) { AttributeHandlerContext context(ErrorOutput(), contentHandler, - B_HPKG_SECTION_PACKAGE_ATTRIBUTES); + B_HPKG_SECTION_PACKAGE_ATTRIBUTES, + MinorFormatVersion() > B_HPKG_MINOR_VERSION); RootAttributeHandler rootAttributeHandler; status_t error @@ -394,7 +395,8 @@ status_t PackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler) { AttributeHandlerContext context(ErrorOutput(), contentHandler, - B_HPKG_SECTION_PACKAGE_ATTRIBUTES); + B_HPKG_SECTION_PACKAGE_ATTRIBUTES, + MinorFormatVersion() > B_HPKG_MINOR_VERSION); LowLevelAttributeHandler rootAttributeHandler; status_t error diff --git a/src/kits/package/hpkg/PackageWriterImpl.cpp b/src/kits/package/hpkg/PackageWriterImpl.cpp index b7fc37a80f..228e1db905 100644 --- a/src/kits/package/hpkg/PackageWriterImpl.cpp +++ b/src/kits/package/hpkg/PackageWriterImpl.cpp @@ -1077,7 +1077,7 @@ PackageWriterImpl::_Finish() uint64 compressedHeapSize = fHeapWriter->CompressedHeapSize(); - header.heap_compression = B_HOST_TO_BENDIAN_INT32(B_HPKG_COMPRESSION_ZLIB); + header.heap_compression = B_HOST_TO_BENDIAN_INT16(B_HPKG_COMPRESSION_ZLIB); header.heap_chunk_size = B_HOST_TO_BENDIAN_INT32(fHeapWriter->ChunkSize()); header.heap_size_compressed = B_HOST_TO_BENDIAN_INT64( fHeapWriter->CompressedHeapSize()); @@ -1104,6 +1104,7 @@ PackageWriterImpl::_Finish() header.header_size = B_HOST_TO_BENDIAN_INT16(fHeaderSize); header.version = B_HOST_TO_BENDIAN_INT16(B_HPKG_VERSION); header.total_size = B_HOST_TO_BENDIAN_INT64(totalSize); + header.minor_version = B_HOST_TO_BENDIAN_INT16(B_HPKG_MINOR_VERSION); // write the header RawWriteBuffer(&header, sizeof(hpkg_header), 0); diff --git a/src/kits/package/hpkg/ReaderImplBase.cpp b/src/kits/package/hpkg/ReaderImplBase.cpp index ba4b0b56cd..a9d6ec8d1b 100644 --- a/src/kits/package/hpkg/ReaderImplBase.cpp +++ b/src/kits/package/hpkg/ReaderImplBase.cpp @@ -39,11 +39,12 @@ static const size_t kScratchBufferSize = 64 * 1024; ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, - BHPKGPackageSectionID section) + BHPKGPackageSectionID section, bool ignoreUnknownAttributes) : errorOutput(errorOutput), packageContentHandler(packageContentHandler), hasLowLevelHandler(false), + ignoreUnknownAttributes(ignoreUnknownAttributes), section(section) { } @@ -51,11 +52,12 @@ ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, - BHPKGPackageSectionID section) + BHPKGPackageSectionID section, bool ignoreUnknownAttributes) : errorOutput(errorOutput), lowLevelHandler(lowLevelHandler), hasLowLevelHandler(true), + ignoreUnknownAttributes(ignoreUnknownAttributes), section(section) { } @@ -140,6 +142,9 @@ ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute( break; default: + if (context->ignoreUnknownAttributes) + break; + context->errorOutput->PrintError("Error: Invalid package " "attribute section: unexpected package attribute id %d " "encountered when parsing package version\n", id); @@ -212,6 +217,9 @@ ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute( break; default: + if (context->ignoreUnknownAttributes) + break; + context->errorOutput->PrintError("Error: Invalid package " "attribute section: unexpected package attribute id %d " "encountered when parsing package resolvable\n", id); @@ -281,6 +289,9 @@ ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute( return B_OK; default: + if (context->ignoreUnknownAttributes) + break; + context->errorOutput->PrintError("Error: Invalid package " "attribute section: unexpected package attribute id %d " "encountered when parsing package resolvable-expression\n", @@ -445,6 +456,9 @@ ReaderImplBase::PackageAttributeHandler::HandleAttribute( break; default: + if (context->ignoreUnknownAttributes) + break; + context->errorOutput->PrintError( "Error: Invalid package attribute section: unexpected " "package attribute id %d encountered\n", id); diff --git a/src/kits/package/hpkg/RepositoryReaderImpl.cpp b/src/kits/package/hpkg/RepositoryReaderImpl.cpp index 98867ab81e..a9a5b1c662 100644 --- a/src/kits/package/hpkg/RepositoryReaderImpl.cpp +++ b/src/kits/package/hpkg/RepositoryReaderImpl.cpp @@ -141,7 +141,8 @@ RepositoryReaderImpl::ParseContent(BRepositoryContentHandler* contentHandler) status_t result = contentHandler->HandleRepositoryInfo(fRepositoryInfo); if (result == B_OK) { AttributeHandlerContext context(ErrorOutput(), contentHandler, - B_HPKG_SECTION_PACKAGE_ATTRIBUTES); + B_HPKG_SECTION_PACKAGE_ATTRIBUTES, + MinorFormatVersion() > B_HPKG_REPO_MINOR_VERSION); PackageAttributeHandler rootAttributeHandler; result = ParsePackageAttributesSection(&context, &rootAttributeHandler); } diff --git a/src/kits/package/hpkg/RepositoryWriterImpl.cpp b/src/kits/package/hpkg/RepositoryWriterImpl.cpp index ec9cf99ccc..619d6d2383 100644 --- a/src/kits/package/hpkg/RepositoryWriterImpl.cpp +++ b/src/kits/package/hpkg/RepositoryWriterImpl.cpp @@ -285,6 +285,7 @@ RepositoryWriterImpl::_Finish() header.header_size = B_HOST_TO_BENDIAN_INT16((uint16)sizeof(header)); header.version = B_HOST_TO_BENDIAN_INT16(B_HPKG_REPO_VERSION); header.total_size = B_HOST_TO_BENDIAN_INT64(totalSize); + header.minor_version = B_HOST_TO_BENDIAN_INT16(B_HPKG_REPO_MINOR_VERSION); RawWriteBuffer(&header, sizeof(header), 0);