Clone read support functionality for HPKG format version 1

It uses sub-namespace BPackage::BHPKG::V1. Unlike the one for the
current format version, the V1 version of BPackageInfoContentHandler
lives in BHPKG(::V1) sub-namespace and is private.
This commit is contained in:
Ingo Weinhold
2013-05-25 01:12:22 +02:00
parent 171fd58c4b
commit 7575abbca2
36 changed files with 4209 additions and 0 deletions
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/HPKGDefs.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageAttributeValue.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageContentHandler.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageData.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageDataReader.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageEntry.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageEntryAttribute.h>
@@ -0,0 +1 @@
#include <../os/package/hpkg/v1/PackageReader.h>
@@ -0,0 +1 @@
#include <../private/package/hpkg/v1/HPKGDefsPrivate.h>
@@ -0,0 +1 @@
#include <../private/package/hpkg/v1/PackageInfoContentHandler.h>
@@ -0,0 +1 @@
#include <../private/package/hpkg/v1/PackageReaderImpl.h>
@@ -0,0 +1 @@
#include <../private/package/hpkg/v1/ReaderImplBase.h>
+183
View File
@@ -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 <SupportDefs.h>
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_
@@ -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 <string.h>
#include <package/hpkg/v1/HPKGDefs.h>
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_
@@ -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 <SupportDefs.h>
#include <package/hpkg/v1/HPKGDefs.h>
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_
+66
View File
@@ -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 <package/hpkg/v1/HPKGDefs.h>
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_
@@ -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 <package/hpkg/DataReader.h>
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_
+98
View File
@@ -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 <sys/stat.h>
#include <package/hpkg/v1/PackageData.h>
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_
@@ -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 <package/hpkg/v1/PackageData.h>
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_
@@ -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 <SupportDefs.h>
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_
@@ -0,0 +1,115 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* 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 <SupportDefs.h>
#include <package/hpkg/HPKGDefs.h>
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_
@@ -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 <package/hpkg/v1/PackageContentHandler.h>
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_
@@ -0,0 +1,102 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2011, Oliver Tappe <[email protected]>
* 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 <package/hpkg/v1/ReaderImplBase.h>
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_
@@ -0,0 +1,338 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2011, Oliver Tappe <[email protected]>
* 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 <SupportDefs.h>
#include <util/SinglyLinkedList.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
#include <package/hpkg/v1/PackageAttributeValue.h>
#include <package/hpkg/v1/PackageContentHandler.h>
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<AttributeHandler> {
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<AttributeHandler> 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<typename Type>
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<typename Type>
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_
+13
View File
@@ -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
+13
View File
@@ -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
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright 2013, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/HPKGDefs.h>
namespace BPackageKit {
namespace BHPKG {
namespace V1 {
const char* const B_HPKG_PACKAGE_INFO_FILE_NAME = ".PackageInfo";
} // namespace V1
} // namespace BHPKG
} // namespace BPackageKit
@@ -0,0 +1,97 @@
/*
* Copyright 2009-2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageContentHandler.h>
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
@@ -0,0 +1,469 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageDataReader.h>
#include <string.h>
#include <algorithm>
#include <new>
#include <package/hpkg/BufferCache.h>
#include <package/hpkg/CachedBuffer.h>
#include <package/hpkg/DataOutput.h>
#include <package/hpkg/v1/HPKGDefsPrivate.h>
#include <package/hpkg/v1/PackageData.h>
#include <package/hpkg/ZlibDecompressor.h>
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
@@ -0,0 +1,58 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageData.h>
#include <string.h>
#include <package/hpkg/v1/HPKGDefsPrivate.h>
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
@@ -0,0 +1,29 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageEntryAttribute.h>
namespace BPackageKit {
namespace BHPKG {
namespace V1 {
BPackageEntryAttribute::BPackageEntryAttribute(const char* name)
:
fName(name),
fType(0)
{
}
} // namespace V1
} // namespace BHPKG
} // namespace BPackageKit
@@ -0,0 +1,38 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageEntry.h>
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
@@ -0,0 +1,166 @@
/*
* Copyright 2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageInfoContentHandler.h>
#include <package/PackageInfo.h>
#include <package/hpkg/ErrorOutput.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
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
@@ -0,0 +1,742 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2011, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageReaderImpl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <algorithm>
#include <new>
#include <ByteOrder.h>
#include <package/hpkg/v1/HPKGDefsPrivate.h>
#include <package/hpkg/DataOutput.h>
#include <package/hpkg/ErrorOutput.h>
#include <package/hpkg/v1/PackageData.h>
#include <package/hpkg/v1/PackageEntry.h>
#include <package/hpkg/v1/PackageEntryAttribute.h>
#include <package/hpkg/ZlibDecompressor.h>
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
@@ -0,0 +1,89 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <package/hpkg/v1/PackageReader.h>
#include <new>
#include <package/hpkg/ErrorOutput.h>
#include <package/hpkg/v1/PackageReaderImpl.h>
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
File diff suppressed because it is too large Load Diff