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:
@@ -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>
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user