Implemented reading of package info attributes from hpkg file
* added kernel-compatible datatypes for reading package info attribute values (PackageInfoAttributeValue.h) - these will be used at a later stage by the package-fs to transport those attributes to userland when asked to do so (by ioctl) * implemented parsing of package info attributes in PackageReaderImpl * added support for compressed package attribute section to PackageReaderImpl * completed the writing of package info attributes in PackageWriterImpl and fixed a couple of bugs exposed by parsing * adjusted 'package list' to show the package info attributes as they are found git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40354 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__PACKAGE_ARCHITECTURE_H_
|
||||||
|
#define _PACKAGE__PACKAGE_ARCHITECTURE_H_
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
enum BPackageArchitecture {
|
||||||
|
B_PACKAGE_ARCHITECTURE_ANY = 0,
|
||||||
|
B_PACKAGE_ARCHITECTURE_X86,
|
||||||
|
B_PACKAGE_ARCHITECTURE_X86_GCC2,
|
||||||
|
//
|
||||||
|
B_PACKAGE_ARCHITECTURE_ENUM_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__PACKAGE_ARCHITECTURE_H_
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <package/PackageArchitecture.h>
|
||||||
|
#include <package/PackageInfoAttributes.h>
|
||||||
#include <package/PackageResolvable.h>
|
#include <package/PackageResolvable.h>
|
||||||
#include <package/PackageResolvableExpression.h>
|
#include <package/PackageResolvableExpression.h>
|
||||||
#include <package/PackageVersion.h>
|
#include <package/PackageVersion.h>
|
||||||
@@ -20,44 +22,6 @@ class BEntry;
|
|||||||
namespace BPackageKit {
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
enum BPackageInfoIndex {
|
|
||||||
B_PACKAGE_INFO_NAME = 0,
|
|
||||||
B_PACKAGE_INFO_SUMMARY, // single line
|
|
||||||
B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible
|
|
||||||
B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project"
|
|
||||||
B_PACKAGE_INFO_PACKAGER, // e-mail address preferred
|
|
||||||
B_PACKAGE_INFO_ARCHITECTURE,
|
|
||||||
B_PACKAGE_INFO_VERSION, // <major>[.<minor>[.<micro>]]
|
|
||||||
B_PACKAGE_INFO_COPYRIGHTS, // list
|
|
||||||
B_PACKAGE_INFO_LICENSES, // list
|
|
||||||
B_PACKAGE_INFO_PROVIDES, // list of resolvables this package provides,
|
|
||||||
// each optionally giving a version
|
|
||||||
B_PACKAGE_INFO_REQUIRES, // list of resolvables required by this package,
|
|
||||||
// each optionally specifying a version relation
|
|
||||||
// (e.g. libssl.so >= 0.9.8)
|
|
||||||
B_PACKAGE_INFO_SUPPLEMENTS, // list of resolvables that are supplemented
|
|
||||||
// by this package, i.e. this package marks
|
|
||||||
// itself as an extension to other packages
|
|
||||||
B_PACKAGE_INFO_CONFLICTS, // list of resolvables that inhibit installation
|
|
||||||
// of this package
|
|
||||||
B_PACKAGE_INFO_REPLACES, // list of resolvables that this package
|
|
||||||
// will replace (upon update)
|
|
||||||
B_PACKAGE_INFO_FRESHENS, // list of resolvables that this package
|
|
||||||
// contains a patch for
|
|
||||||
//
|
|
||||||
B_PACKAGE_INFO_ENUM_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum BPackageArchitecture {
|
|
||||||
B_PACKAGE_ARCHITECTURE_ANY = 0,
|
|
||||||
B_PACKAGE_ARCHITECTURE_X86,
|
|
||||||
B_PACKAGE_ARCHITECTURE_X86_GCC2,
|
|
||||||
//
|
|
||||||
B_PACKAGE_ARCHITECTURE_ENUM_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keeps a list of package info elements (e.g. name, version, vendor, ...) which
|
* Keeps a list of package info elements (e.g. name, version, vendor, ...) which
|
||||||
* will be converted to package attributes when creating a package. Usually,
|
* will be converted to package attributes when creating a package. Usually,
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_
|
||||||
|
#define _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
enum BPackageInfoAttributeIndex {
|
||||||
|
B_PACKAGE_INFO_NAME = 0,
|
||||||
|
B_PACKAGE_INFO_SUMMARY, // single line
|
||||||
|
B_PACKAGE_INFO_DESCRIPTION, // multiple lines possible
|
||||||
|
B_PACKAGE_INFO_VENDOR, // e.g. "Haiku Project"
|
||||||
|
B_PACKAGE_INFO_PACKAGER, // e-mail address preferred
|
||||||
|
B_PACKAGE_INFO_ARCHITECTURE,
|
||||||
|
B_PACKAGE_INFO_VERSION, // <major>[.<minor>[.<micro>]]
|
||||||
|
B_PACKAGE_INFO_COPYRIGHTS, // list
|
||||||
|
B_PACKAGE_INFO_LICENSES, // list
|
||||||
|
B_PACKAGE_INFO_PROVIDES, // list of resolvables this package provides,
|
||||||
|
// each optionally giving a version
|
||||||
|
B_PACKAGE_INFO_REQUIRES, // list of resolvables required by this package,
|
||||||
|
// each optionally specifying a version relation
|
||||||
|
// (e.g. libssl.so >= 0.9.8)
|
||||||
|
B_PACKAGE_INFO_SUPPLEMENTS, // list of resolvables that are supplemented
|
||||||
|
// by this package, i.e. this package marks
|
||||||
|
// itself as an extension to other packages
|
||||||
|
B_PACKAGE_INFO_CONFLICTS, // list of resolvables that inhibit installation
|
||||||
|
// of this package
|
||||||
|
B_PACKAGE_INFO_FRESHENS, // list of resolvables that this package
|
||||||
|
// contains a patch for
|
||||||
|
B_PACKAGE_INFO_REPLACES, // list of resolvables that this package
|
||||||
|
// will replace (upon update)
|
||||||
|
//
|
||||||
|
B_PACKAGE_INFO_ENUM_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__PACKAGE_INFO_ATTRIBUTES_H_
|
||||||
@@ -2,29 +2,19 @@
|
|||||||
* Copyright 2011, Haiku, Inc.
|
* Copyright 2011, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _PACKAGE__PACKAGE_RESOLVALBE_H_
|
#ifndef _PACKAGE__PACKAGE_RESOLVABLE_H_
|
||||||
#define _PACKAGE__PACKAGE_RESOLVALBE_H_
|
#define _PACKAGE__PACKAGE_RESOLVABLE_H_
|
||||||
|
|
||||||
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <package/PackageResolvableType.h>
|
||||||
#include <package/PackageVersion.h>
|
#include <package/PackageVersion.h>
|
||||||
|
|
||||||
|
|
||||||
namespace BPackageKit {
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
enum BPackageResolvableType {
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_DEFAULT = 0,
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_LIBRARY,
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_COMMAND,
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_APPLICATION,
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_ADD_ON,
|
|
||||||
//
|
|
||||||
B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defines a resolvable (something other packages can depend upon).
|
* Defines a resolvable (something other packages can depend upon).
|
||||||
* Each resolvable is defined as a name (with an optional type prefix)
|
* Each resolvable is defined as a name (with an optional type prefix)
|
||||||
@@ -83,4 +73,4 @@ private:
|
|||||||
} // namespace BPackageKit
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
#endif // _PACKAGE__PACKAGE_RESOLVALBE_H_
|
#endif // _PACKAGE__PACKAGE_RESOLVABLE_H_
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_
|
||||||
|
#define _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
enum BPackageResolvableOperator {
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_LESS,
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL,
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_EQUAL,
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL,
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL,
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_GREATER,
|
||||||
|
//
|
||||||
|
B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__PACKAGE_RESOLVABLE_OPERATOR_H_
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_
|
||||||
|
#define _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
enum BPackageResolvableType {
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_DEFAULT = 0,
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_LIBRARY,
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_COMMAND,
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_APPLICATION,
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_ADD_ON,
|
||||||
|
//
|
||||||
|
B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__PACKAGE_RESOLVABLE_TYPE_H_
|
||||||
@@ -28,7 +28,9 @@ enum {
|
|||||||
B_HPKG_ATTRIBUTE_TYPE_INT = 1,
|
B_HPKG_ATTRIBUTE_TYPE_INT = 1,
|
||||||
B_HPKG_ATTRIBUTE_TYPE_UINT = 2,
|
B_HPKG_ATTRIBUTE_TYPE_UINT = 2,
|
||||||
B_HPKG_ATTRIBUTE_TYPE_STRING = 3,
|
B_HPKG_ATTRIBUTE_TYPE_STRING = 3,
|
||||||
B_HPKG_ATTRIBUTE_TYPE_RAW = 4
|
B_HPKG_ATTRIBUTE_TYPE_RAW = 4,
|
||||||
|
//
|
||||||
|
B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -63,6 +65,34 @@ enum {
|
|||||||
#define B_HPKG_PACKAGE_INFO_FILE_NAME ".PackageInfo"
|
#define B_HPKG_PACKAGE_INFO_FILE_NAME ".PackageInfo"
|
||||||
|
|
||||||
|
|
||||||
|
// package attribute IDs
|
||||||
|
enum BPackageAttributeID {
|
||||||
|
B_PACKAGE_ATTRIBUTE_NAME = 0,
|
||||||
|
B_PACKAGE_ATTRIBUTE_SUMMARY,
|
||||||
|
B_PACKAGE_ATTRIBUTE_DESCRIPTION,
|
||||||
|
B_PACKAGE_ATTRIBUTE_VENDOR,
|
||||||
|
B_PACKAGE_ATTRIBUTE_PACKAGER,
|
||||||
|
B_PACKAGE_ATTRIBUTE_ARCHITECTURE,
|
||||||
|
B_PACKAGE_ATTRIBUTE_VERSION_MAJOR,
|
||||||
|
B_PACKAGE_ATTRIBUTE_VERSION_MINOR,
|
||||||
|
B_PACKAGE_ATTRIBUTE_VERSION_MICRO,
|
||||||
|
B_PACKAGE_ATTRIBUTE_VERSION_RELEASE,
|
||||||
|
B_PACKAGE_ATTRIBUTE_COPYRIGHT,
|
||||||
|
B_PACKAGE_ATTRIBUTE_LICENSE,
|
||||||
|
B_PACKAGE_ATTRIBUTE_PROVIDES,
|
||||||
|
B_PACKAGE_ATTRIBUTE_PROVIDES_TYPE,
|
||||||
|
B_PACKAGE_ATTRIBUTE_REQUIRES,
|
||||||
|
B_PACKAGE_ATTRIBUTE_SUPPLEMENTS,
|
||||||
|
B_PACKAGE_ATTRIBUTE_CONFLICTS,
|
||||||
|
B_PACKAGE_ATTRIBUTE_FRESHENS,
|
||||||
|
B_PACKAGE_ATTRIBUTE_REPLACES,
|
||||||
|
B_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR,
|
||||||
|
//
|
||||||
|
B_PACKAGE_ATTRIBUTE_ENUM_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: make this accessible via a function
|
||||||
// default values
|
// default values
|
||||||
enum {
|
enum {
|
||||||
B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB = 64 * 1024
|
B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB = 64 * 1024
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace BHPKG {
|
|||||||
class BPackageAttributeValue;
|
class BPackageAttributeValue;
|
||||||
class BPackageEntry;
|
class BPackageEntry;
|
||||||
class BPackageEntryAttribute;
|
class BPackageEntryAttribute;
|
||||||
|
class BPackageInfoAttributeValue;
|
||||||
|
|
||||||
|
|
||||||
class BLowLevelPackageContentHandler {
|
class BLowLevelPackageContentHandler {
|
||||||
@@ -43,6 +44,10 @@ public:
|
|||||||
BPackageEntryAttribute* attribute) = 0;
|
BPackageEntryAttribute* attribute) = 0;
|
||||||
virtual status_t HandleEntryDone(BPackageEntry* entry) = 0;
|
virtual status_t HandleEntryDone(BPackageEntry* entry) = 0;
|
||||||
|
|
||||||
|
virtual status_t HandlePackageAttribute(
|
||||||
|
const BPackageInfoAttributeValue& value
|
||||||
|
) = 0;
|
||||||
|
|
||||||
virtual void HandleErrorOccurred() = 0;
|
virtual void HandleErrorOccurred() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009,2011, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__HPKG__PACKAGE_INFO_ATTRIBUTE_VALUE_H_
|
||||||
|
#define _PACKAGE__HPKG__PACKAGE_INFO_ATTRIBUTE_VALUE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <package/PackageArchitecture.h>
|
||||||
|
#include <package/PackageInfoAttributes.h>
|
||||||
|
#include <package/PackageResolvableOperator.h>
|
||||||
|
#include <package/PackageResolvableType.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
namespace BHPKG {
|
||||||
|
|
||||||
|
|
||||||
|
struct BPackageVersionData {
|
||||||
|
const char* major;
|
||||||
|
const char* minor;
|
||||||
|
const char* micro;
|
||||||
|
uint8 release;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct BPackageResolvableData {
|
||||||
|
BPackageResolvableType type;
|
||||||
|
const char* name;
|
||||||
|
bool haveVersion;
|
||||||
|
BPackageVersionData version;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct BPackageResolvableExpressionData {
|
||||||
|
const char* name;
|
||||||
|
bool haveOpAndVersion;
|
||||||
|
BPackageResolvableOperator op;
|
||||||
|
BPackageVersionData version;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct BPackageInfoAttributeValue {
|
||||||
|
union {
|
||||||
|
uint64 unsignedInt;
|
||||||
|
const char* string;
|
||||||
|
BPackageVersionData version;
|
||||||
|
BPackageResolvableData resolvable;
|
||||||
|
BPackageResolvableExpressionData resolvableExpression;
|
||||||
|
};
|
||||||
|
uint8 attributeIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline BPackageInfoAttributeValue();
|
||||||
|
|
||||||
|
inline void SetTo(BPackageInfoAttributeIndex index,
|
||||||
|
uint8 value);
|
||||||
|
inline void SetTo(BPackageInfoAttributeIndex index,
|
||||||
|
const char* value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BPackageInfoAttributeValue::BPackageInfoAttributeValue()
|
||||||
|
:
|
||||||
|
attributeIndex(B_PACKAGE_INFO_ENUM_COUNT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index, uint8 value)
|
||||||
|
{
|
||||||
|
attributeIndex = index;
|
||||||
|
unsignedInt = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPackageInfoAttributeValue::SetTo(BPackageInfoAttributeIndex index,
|
||||||
|
const char* value)
|
||||||
|
{
|
||||||
|
attributeIndex = index;
|
||||||
|
string = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BHPKG
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__HPKG__PACKAGE_ATTRIBUTE_VALUE_H_
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <package/hpkg/PackageAttributeValue.h>
|
#include <package/hpkg/PackageAttributeValue.h>
|
||||||
#include <package/hpkg/PackageContentHandler.h>
|
#include <package/hpkg/PackageContentHandler.h>
|
||||||
|
#include <package/hpkg/PackageInfoAttributeValue.h>
|
||||||
#include <package/hpkg/PackageReader.h>
|
#include <package/hpkg/PackageReader.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -74,6 +75,25 @@ private:
|
|||||||
status_t _ParseAttributeTree(
|
status_t _ParseAttributeTree(
|
||||||
AttributeHandlerContext* context);
|
AttributeHandlerContext* context);
|
||||||
|
|
||||||
|
status_t _ParsePackageAttributes(
|
||||||
|
AttributeHandlerContext* context);
|
||||||
|
status_t _ParsePackageVersion(
|
||||||
|
BPackageVersionData& _version,
|
||||||
|
const char* major = NULL);
|
||||||
|
status_t _ParsePackageProvides(
|
||||||
|
BPackageResolvableData& _resolvable,
|
||||||
|
BPackageResolvableType providesType);
|
||||||
|
status_t _ParsePackageResolvableExpression(
|
||||||
|
BPackageResolvableExpressionData&
|
||||||
|
_resolvableExpression,
|
||||||
|
const char* resolvableName,
|
||||||
|
bool hasChildren);
|
||||||
|
|
||||||
|
status_t _ReadPackageAttribute(uint8& _id,
|
||||||
|
AttributeValue& _value,
|
||||||
|
bool* _hasChildren = NULL,
|
||||||
|
uint64* _tag = NULL);
|
||||||
|
|
||||||
status_t _ReadAttributeValue(uint8 type, uint8 encoding,
|
status_t _ReadAttributeValue(uint8 type, uint8 encoding,
|
||||||
AttributeValue& _value);
|
AttributeValue& _value);
|
||||||
|
|
||||||
@@ -88,6 +108,9 @@ private:
|
|||||||
const void*& _buffer);
|
const void*& _buffer);
|
||||||
status_t _ReadTOCBuffer(void* buffer, size_t size);
|
status_t _ReadTOCBuffer(void* buffer, size_t size);
|
||||||
|
|
||||||
|
status_t _ReadPackageAttributesBuffer(void* buffer,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
status_t _ReadBuffer(off_t offset, void* buffer,
|
status_t _ReadBuffer(off_t offset, void* buffer,
|
||||||
size_t size);
|
size_t size);
|
||||||
status_t _ReadCompressedBuffer(off_t offset,
|
status_t _ReadCompressedBuffer(off_t offset,
|
||||||
@@ -103,7 +126,7 @@ private:
|
|||||||
inline AttributeHandler* _PopAttributeHandler();
|
inline AttributeHandler* _PopAttributeHandler();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BErrorOutput* fErrorOutput;
|
BErrorOutput* fErrorOutput;
|
||||||
int fFD;
|
int fFD;
|
||||||
bool fOwnsFD;
|
bool fOwnsFD;
|
||||||
|
|
||||||
@@ -120,6 +143,8 @@ private:
|
|||||||
uint64 fTOCStringsLength;
|
uint64 fTOCStringsLength;
|
||||||
uint64 fTOCStringsCount;
|
uint64 fTOCStringsCount;
|
||||||
|
|
||||||
|
bool fInPackageAttributes;
|
||||||
|
|
||||||
uint32 fPackageAttributesCompression;
|
uint32 fPackageAttributesCompression;
|
||||||
uint32 fPackageAttributesCompressedLength;
|
uint32 fPackageAttributesCompressedLength;
|
||||||
uint32 fPackageAttributesUncompressedLength;
|
uint32 fPackageAttributesUncompressedLength;
|
||||||
@@ -127,6 +152,10 @@ private:
|
|||||||
|
|
||||||
uint8* fTOCSection;
|
uint8* fTOCSection;
|
||||||
uint64 fCurrentTOCOffset;
|
uint64 fCurrentTOCOffset;
|
||||||
|
|
||||||
|
uint8* fPackageAttributesSection;
|
||||||
|
uint64 fCurrentPackageAttributesOffset;
|
||||||
|
|
||||||
AttributeTypeReference* fAttributeTypes;
|
AttributeTypeReference* fAttributeTypes;
|
||||||
char** fStrings;
|
char** fStrings;
|
||||||
|
|
||||||
@@ -141,7 +170,9 @@ template<typename Type>
|
|||||||
status_t
|
status_t
|
||||||
PackageReaderImpl::_Read(Type& _value)
|
PackageReaderImpl::_Read(Type& _value)
|
||||||
{
|
{
|
||||||
return _ReadTOCBuffer(&_value, sizeof(Type));
|
return fInPackageAttributes
|
||||||
|
? _ReadPackageAttributesBuffer(&_value, sizeof(Type))
|
||||||
|
: _ReadTOCBuffer(&_value, sizeof(Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ private:
|
|||||||
|
|
||||||
void _WritePackageVersion(
|
void _WritePackageVersion(
|
||||||
const BPackageVersion& version);
|
const BPackageVersion& version);
|
||||||
|
void _WritePackageResolvableExpressionList(
|
||||||
|
const BObjectList<
|
||||||
|
BPackageResolvableExpression>& list,
|
||||||
|
uint8 id);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
inline void _Write(const Type& value);
|
inline void _Write(const Type& value);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ enum {
|
|||||||
|
|
||||||
|
|
||||||
// package attribute IDs
|
// package attribute IDs
|
||||||
enum {
|
enum BHPKGPackageAttributeID {
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_NAME = 0,
|
B_HPKG_PACKAGE_ATTRIBUTE_NAME = 0,
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_SUMMARY,
|
B_HPKG_PACKAGE_ATTRIBUTE_SUMMARY,
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION,
|
B_HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION,
|
||||||
@@ -150,6 +150,8 @@ enum {
|
|||||||
B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS,
|
B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS,
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_REPLACES,
|
B_HPKG_PACKAGE_ATTRIBUTE_REPLACES,
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR,
|
B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR,
|
||||||
|
//
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -257,6 +257,13 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler {
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual status_t HandlePackageAttribute(
|
||||||
|
const BPackageInfoAttributeValue& value)
|
||||||
|
{
|
||||||
|
// TODO!
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void HandleErrorOccurred()
|
virtual void HandleErrorOccurred()
|
||||||
{
|
{
|
||||||
fErrorOccurred = true;
|
fErrorOccurred = true;
|
||||||
|
|||||||
@@ -223,6 +223,12 @@ struct PackageContentExtractHandler : BPackageContentHandler {
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual status_t HandlePackageAttribute(
|
||||||
|
const BPackageInfoAttributeValue& value)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void HandleErrorOccurred()
|
virtual void HandleErrorOccurred()
|
||||||
{
|
{
|
||||||
fErrorOccurred = true;
|
fErrorOccurred = true;
|
||||||
|
|||||||
@@ -14,13 +14,17 @@
|
|||||||
#include <package/hpkg/PackageContentHandler.h>
|
#include <package/hpkg/PackageContentHandler.h>
|
||||||
#include <package/hpkg/PackageEntry.h>
|
#include <package/hpkg/PackageEntry.h>
|
||||||
#include <package/hpkg/PackageEntryAttribute.h>
|
#include <package/hpkg/PackageEntryAttribute.h>
|
||||||
|
#include <package/hpkg/PackageInfoAttributeValue.h>
|
||||||
#include <package/hpkg/PackageReader.h>
|
#include <package/hpkg/PackageReader.h>
|
||||||
|
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
|
|
||||||
#include "package.h"
|
#include "package.h"
|
||||||
#include "StandardErrorOutput.h"
|
#include "StandardErrorOutput.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace BPackageKit::BHPKG;
|
using namespace BPackageKit::BHPKG;
|
||||||
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
struct PackageContentListHandler : BPackageContentHandler {
|
struct PackageContentListHandler : BPackageContentHandler {
|
||||||
@@ -104,6 +108,114 @@ struct PackageContentListHandler : BPackageContentHandler {
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual status_t HandlePackageAttribute(
|
||||||
|
const BPackageInfoAttributeValue& value)
|
||||||
|
{
|
||||||
|
switch (value.attributeIndex) {
|
||||||
|
case B_PACKAGE_INFO_NAME:
|
||||||
|
printf("package-attributes:\n");
|
||||||
|
printf("\tname: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_SUMMARY:
|
||||||
|
printf("\tsummary: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_DESCRIPTION:
|
||||||
|
printf("\tdescription: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_VENDOR:
|
||||||
|
printf("\tvendor: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_PACKAGER:
|
||||||
|
printf("\tpackager: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_ARCHITECTURE:
|
||||||
|
printf("\tarchitecure: %s\n",
|
||||||
|
BPackageInfo::kArchitectureNames[value.unsignedInt]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_VERSION:
|
||||||
|
printf("\tversion: %s.%s.%s-%d\n", value.version.major,
|
||||||
|
value.version.minor, value.version.micro,
|
||||||
|
value.version.release);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_COPYRIGHTS:
|
||||||
|
printf("\tcopyright: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_LICENSES:
|
||||||
|
printf("\tlicense: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_PROVIDES:
|
||||||
|
printf("\tprovides: %s", value.resolvable.name);
|
||||||
|
if (value.resolvable.haveVersion) {
|
||||||
|
printf(" = ");
|
||||||
|
_PrintPackageVersion(value.resolvable.version);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_REQUIRES:
|
||||||
|
printf("\trequires: %s", value.resolvableExpression.name);
|
||||||
|
if (value.resolvableExpression.haveOpAndVersion) {
|
||||||
|
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
|
||||||
|
value.resolvableExpression.op]);
|
||||||
|
_PrintPackageVersion(value.resolvableExpression.version);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_SUPPLEMENTS:
|
||||||
|
printf("\tsupplements: %s", value.resolvableExpression.name);
|
||||||
|
if (value.resolvableExpression.haveOpAndVersion) {
|
||||||
|
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
|
||||||
|
value.resolvableExpression.op]);
|
||||||
|
_PrintPackageVersion(value.resolvableExpression.version);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_CONFLICTS:
|
||||||
|
printf("\tconflicts: %s", value.resolvableExpression.name);
|
||||||
|
if (value.resolvableExpression.haveOpAndVersion) {
|
||||||
|
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
|
||||||
|
value.resolvableExpression.op]);
|
||||||
|
_PrintPackageVersion(value.resolvableExpression.version);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_FRESHENS:
|
||||||
|
printf("\tfreshens: %s", value.resolvableExpression.name);
|
||||||
|
if (value.resolvableExpression.haveOpAndVersion) {
|
||||||
|
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
|
||||||
|
value.resolvableExpression.op]);
|
||||||
|
_PrintPackageVersion(value.resolvableExpression.version);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_REPLACES:
|
||||||
|
printf("\treplaces: %s\n", value.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf(
|
||||||
|
"*** Invalid package attribute section: unexpected "
|
||||||
|
"package attribute index %d encountered\n",
|
||||||
|
value.attributeIndex);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void HandleErrorOccurred()
|
virtual void HandleErrorOccurred()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -123,6 +235,17 @@ private:
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _PrintPackageVersion(const BPackageVersionData& version)
|
||||||
|
{
|
||||||
|
printf("%s", version.major);
|
||||||
|
if (version.minor != NULL && version.minor[0] != '\0')
|
||||||
|
printf(".%s", version.minor);
|
||||||
|
if (version.micro != NULL && version.micro[0] != '\0')
|
||||||
|
printf(".%s", version.micro);
|
||||||
|
if (version.release > 0)
|
||||||
|
printf("-%d", version.release);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fLevel;
|
int fLevel;
|
||||||
bool fListAttribute;
|
bool fListAttribute;
|
||||||
|
|||||||
@@ -41,9 +41,12 @@ namespace BPrivate {
|
|||||||
|
|
||||||
|
|
||||||
// maximum TOC size we support reading
|
// maximum TOC size we support reading
|
||||||
static const size_t kMaxTOCSize = 64 * 1024 * 1024;
|
static const size_t kMaxTOCSize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
static const size_t kScratchBufferSize = 64 * 1024;
|
// maximum package attributes size we support reading
|
||||||
|
static const size_t kMaxPackageAttributesSize = 1 * 1024 * 1024;
|
||||||
|
|
||||||
|
static const size_t kScratchBufferSize = 64 * 1024;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -612,7 +615,9 @@ PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput)
|
|||||||
fErrorOutput(errorOutput),
|
fErrorOutput(errorOutput),
|
||||||
fFD(-1),
|
fFD(-1),
|
||||||
fOwnsFD(false),
|
fOwnsFD(false),
|
||||||
|
fInPackageAttributes(false),
|
||||||
fTOCSection(NULL),
|
fTOCSection(NULL),
|
||||||
|
fPackageAttributesSection(NULL),
|
||||||
fAttributeTypes(NULL),
|
fAttributeTypes(NULL),
|
||||||
fStrings(NULL),
|
fStrings(NULL),
|
||||||
fScratchBuffer(NULL),
|
fScratchBuffer(NULL),
|
||||||
@@ -630,6 +635,7 @@ PackageReaderImpl::~PackageReaderImpl()
|
|||||||
delete[] fStrings;
|
delete[] fStrings;
|
||||||
delete[] fAttributeTypes;
|
delete[] fAttributeTypes;
|
||||||
delete[] fTOCSection;
|
delete[] fTOCSection;
|
||||||
|
delete[] fPackageAttributesSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -772,6 +778,15 @@ PackageReaderImpl::Init(int fd, bool keepFD)
|
|||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// package attributes size sanity check
|
||||||
|
if (fPackageAttributesUncompressedLength > kMaxPackageAttributesSize) {
|
||||||
|
fErrorOutput->PrintError(
|
||||||
|
"Error: Package file package attributes section size "
|
||||||
|
"is %llu bytes. This is beyond the reader's sanity limit\n",
|
||||||
|
fPackageAttributesUncompressedLength);
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate a scratch buffer
|
// allocate a scratch buffer
|
||||||
fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
|
fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
|
||||||
if (fScratchBuffer == NULL) {
|
if (fScratchBuffer == NULL) {
|
||||||
@@ -786,13 +801,26 @@ PackageReaderImpl::Init(int fd, bool keepFD)
|
|||||||
fErrorOutput->PrintError("Error: Out of memory!\n");
|
fErrorOutput->PrintError("Error: Out of memory!\n");
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection,
|
error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection,
|
||||||
fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression);
|
fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
// read in the complete package attributes section
|
||||||
|
fPackageAttributesSection
|
||||||
|
= new(std::nothrow) uint8[fPackageAttributesUncompressedLength];
|
||||||
|
if (fPackageAttributesSection == NULL) {
|
||||||
|
fErrorOutput->PrintError("Error: Out of memory!\n");
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
error = _ReadCompressedBuffer(fPackageAttributesOffset,
|
||||||
|
fPackageAttributesSection, fPackageAttributesCompressedLength,
|
||||||
|
fPackageAttributesUncompressedLength, fPackageAttributesCompression);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
// start parsing the TOC
|
// start parsing the TOC
|
||||||
|
fInPackageAttributes = false;
|
||||||
fCurrentTOCOffset = 0;
|
fCurrentTOCOffset = 0;
|
||||||
|
|
||||||
// attribute types
|
// attribute types
|
||||||
@@ -816,7 +844,15 @@ PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler)
|
|||||||
{
|
{
|
||||||
AttributeHandlerContext context(fErrorOutput, contentHandler);
|
AttributeHandlerContext context(fErrorOutput, contentHandler);
|
||||||
RootAttributeHandler rootAttributeHandler;
|
RootAttributeHandler rootAttributeHandler;
|
||||||
return _ParseContent(&context, &rootAttributeHandler);
|
|
||||||
|
status_t result = _ParseContent(&context, &rootAttributeHandler);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fInPackageAttributes = true;
|
||||||
|
fCurrentPackageAttributesOffset = 0;
|
||||||
|
|
||||||
|
return _ParsePackageAttributes(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1070,6 +1106,350 @@ PackageReaderImpl::_ParseAttributeTree(AttributeHandlerContext* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ParsePackageAttributes(AttributeHandlerContext* context)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
uint8 id;
|
||||||
|
AttributeValue attributeValue;
|
||||||
|
bool hasChildren;
|
||||||
|
uint64 tag;
|
||||||
|
BPackageInfoAttributeValue handlerValue;
|
||||||
|
|
||||||
|
status_t error
|
||||||
|
= _ReadPackageAttribute(id, attributeValue, &hasChildren, &tag);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (tag == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_NAME:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_NAME, attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_SUMMARY:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_SUMMARY,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_VENDOR:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_VENDOR,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_PACKAGER:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_PACKAGER,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE:
|
||||||
|
if (attributeValue.unsignedInt
|
||||||
|
>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
|
||||||
|
fErrorOutput->PrintError(
|
||||||
|
"Error: Invalid package attribute section: "
|
||||||
|
"Invalid package architecture %lld encountered\n",
|
||||||
|
attributeValue.unsignedInt);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
|
||||||
|
(uint8)attributeValue.unsignedInt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR:
|
||||||
|
error = _ParsePackageVersion(handlerValue.version,
|
||||||
|
attributeValue.string);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_VERSION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_COPYRIGHT:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_LICENSE:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_LICENSES,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE:
|
||||||
|
error = _ParsePackageProvides(handlerValue.resolvable,
|
||||||
|
(BPackageResolvableType)attributeValue.unsignedInt);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_PROVIDES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_REQUIRES:
|
||||||
|
error = _ParsePackageResolvableExpression(
|
||||||
|
handlerValue.resolvableExpression, attributeValue.string,
|
||||||
|
hasChildren);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_REQUIRES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS:
|
||||||
|
error = _ParsePackageResolvableExpression(
|
||||||
|
handlerValue.resolvableExpression, attributeValue.string,
|
||||||
|
hasChildren);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_SUPPLEMENTS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_CONFLICTS:
|
||||||
|
error = _ParsePackageResolvableExpression(
|
||||||
|
handlerValue.resolvableExpression, attributeValue.string,
|
||||||
|
hasChildren);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_CONFLICTS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS:
|
||||||
|
error = _ParsePackageResolvableExpression(
|
||||||
|
handlerValue.resolvableExpression, attributeValue.string,
|
||||||
|
hasChildren);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
handlerValue.attributeIndex = B_PACKAGE_INFO_FRESHENS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_HPKG_PACKAGE_ATTRIBUTE_REPLACES:
|
||||||
|
handlerValue.SetTo(B_PACKAGE_INFO_REPLACES,
|
||||||
|
attributeValue.string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fErrorOutput->PrintError(
|
||||||
|
"Error: Invalid package attribute section: unexpected "
|
||||||
|
"package attribute id %d encountered\n", id);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = context->packageContentHandler->HandlePackageAttribute(
|
||||||
|
handlerValue);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ParsePackageVersion(BPackageVersionData& _version,
|
||||||
|
const char* major)
|
||||||
|
{
|
||||||
|
uint8 id;
|
||||||
|
AttributeValue value;
|
||||||
|
status_t error;
|
||||||
|
|
||||||
|
_version.major = NULL;
|
||||||
|
_version.minor = NULL;
|
||||||
|
_version.micro = NULL;
|
||||||
|
_version.release = 0;
|
||||||
|
|
||||||
|
// major (may have been read already)
|
||||||
|
if (major == NULL) {
|
||||||
|
error = _ReadPackageAttribute(id, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package version, expected major\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
major = value.string;
|
||||||
|
}
|
||||||
|
_version.major = major;
|
||||||
|
|
||||||
|
// minor
|
||||||
|
error = _ReadPackageAttribute(id, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package version, expected minor\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_version.minor = value.string;
|
||||||
|
|
||||||
|
// micro
|
||||||
|
error = _ReadPackageAttribute(id, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_VERSION_MICRO) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package version, expected micro\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_version.micro = value.string;
|
||||||
|
|
||||||
|
// release
|
||||||
|
error = _ReadPackageAttribute(id, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_VERSION_RELEASE) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package version, expected release\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_version.release = (uint8)value.unsignedInt;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ParsePackageProvides(BPackageResolvableData& _resolvable,
|
||||||
|
BPackageResolvableType providesType)
|
||||||
|
{
|
||||||
|
uint8 id;
|
||||||
|
AttributeValue value;
|
||||||
|
bool hasChildren;
|
||||||
|
|
||||||
|
if (providesType >= B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section: "
|
||||||
|
"Invalid package provides type %lld encountered\n", providesType);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_resolvable.type = providesType;
|
||||||
|
_resolvable.haveVersion = false;
|
||||||
|
|
||||||
|
// provides name
|
||||||
|
status_t error = _ReadPackageAttribute(id, value, &hasChildren);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section: "
|
||||||
|
"Invalid package provides, expected name of resolvable\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
_resolvable.name = value.string;
|
||||||
|
|
||||||
|
// there may be a version added as child
|
||||||
|
if (hasChildren) {
|
||||||
|
error = _ParsePackageVersion(_resolvable.version);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_resolvable.haveVersion = true;
|
||||||
|
|
||||||
|
uint64 tag;
|
||||||
|
if ((error = _ReadUnsignedLEB128(tag)) != B_OK)
|
||||||
|
return error;
|
||||||
|
if (tag != 0) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute "
|
||||||
|
"section: Invalid package provides, expected end-tag\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ParsePackageResolvableExpression(
|
||||||
|
BPackageResolvableExpressionData& _resolvableExpression,
|
||||||
|
const char* resolvableName, bool hasChildren)
|
||||||
|
{
|
||||||
|
_resolvableExpression.name = resolvableName;
|
||||||
|
_resolvableExpression.haveOpAndVersion = false;
|
||||||
|
|
||||||
|
// there may be an operator and a version added as child
|
||||||
|
if (hasChildren) {
|
||||||
|
// resolvable-expression operator
|
||||||
|
uint8 id;
|
||||||
|
AttributeValue value;
|
||||||
|
status_t error = _ReadPackageAttribute(id, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (id != B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package resolvable expression, expected operator\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package resolvable operator %lld encountered\n",
|
||||||
|
value.unsignedInt);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
_resolvableExpression.op
|
||||||
|
= (BPackageResolvableOperator)value.unsignedInt;
|
||||||
|
|
||||||
|
error = _ParsePackageVersion(_resolvableExpression.version);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_resolvableExpression.haveOpAndVersion = true;
|
||||||
|
|
||||||
|
uint64 tag;
|
||||||
|
if ((error = _ReadUnsignedLEB128(tag)) != B_OK)
|
||||||
|
return error;
|
||||||
|
if (tag != 0) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section:"
|
||||||
|
" Invalid package resolvable expression, expected end-tag\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ReadPackageAttribute(uint8& _id, AttributeValue& _value,
|
||||||
|
bool* _hasChildren, uint64* _tag)
|
||||||
|
{
|
||||||
|
uint64 tag;
|
||||||
|
status_t error = _ReadUnsignedLEB128(tag);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (tag != 0) {
|
||||||
|
// get the type
|
||||||
|
uint16 type = B_HPKG_PACKAGE_ATTRIBUTE_TAG_TYPE(tag);
|
||||||
|
if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute "
|
||||||
|
"section: attribute type %d not supported!\n", type);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the value
|
||||||
|
error = _ReadAttributeValue(type,
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_TAG_ENCODING(tag), _value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_id = B_HPKG_PACKAGE_ATTRIBUTE_TAG_ID(tag);
|
||||||
|
if (_id >= B_HPKG_PACKAGE_ATTRIBUTE_ENUM_COUNT) {
|
||||||
|
fErrorOutput->PrintError("Error: Invalid package attribute section: "
|
||||||
|
"attribute id %d not supported!\n", _id);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hasChildren != NULL)
|
||||||
|
*_hasChildren = B_HPKG_PACKAGE_ATTRIBUTE_TAG_HAS_CHILDREN(tag);
|
||||||
|
if (_tag != NULL)
|
||||||
|
*_tag = tag;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageReaderImpl::_ReadAttributeValue(uint8 type, uint8 encoding,
|
PackageReaderImpl::_ReadAttributeValue(uint8 type, uint8 encoding,
|
||||||
AttributeValue& _value)
|
AttributeValue& _value)
|
||||||
@@ -1235,6 +1615,29 @@ PackageReaderImpl::_ReadUnsignedLEB128(uint64& _value)
|
|||||||
status_t
|
status_t
|
||||||
PackageReaderImpl::_ReadString(const char*& _string, size_t* _stringLength)
|
PackageReaderImpl::_ReadString(const char*& _string, size_t* _stringLength)
|
||||||
{
|
{
|
||||||
|
if (fInPackageAttributes) {
|
||||||
|
const char* string = (const char*)fPackageAttributesSection
|
||||||
|
+ fCurrentPackageAttributesOffset;
|
||||||
|
size_t stringLength = strnlen(string,
|
||||||
|
fPackageAttributesUncompressedLength
|
||||||
|
- fCurrentPackageAttributesOffset);
|
||||||
|
|
||||||
|
if (stringLength == fPackageAttributesUncompressedLength
|
||||||
|
- fCurrentPackageAttributesOffset) {
|
||||||
|
fErrorOutput->PrintError(
|
||||||
|
"_ReadString(): string extends beyond package attributes "
|
||||||
|
"section end\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
_string = string;
|
||||||
|
if (_stringLength != NULL)
|
||||||
|
*_stringLength = stringLength;
|
||||||
|
|
||||||
|
fCurrentPackageAttributesOffset += stringLength + 1;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
const char* string = (const char*)fTOCSection + fCurrentTOCOffset;
|
const char* string = (const char*)fTOCSection + fCurrentTOCOffset;
|
||||||
size_t stringLength = strnlen(string,
|
size_t stringLength = strnlen(string,
|
||||||
fTOCUncompressedLength - fCurrentTOCOffset);
|
fTOCUncompressedLength - fCurrentTOCOffset);
|
||||||
@@ -1284,6 +1687,24 @@ PackageReaderImpl::_ReadTOCBuffer(void* buffer, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReaderImpl::_ReadPackageAttributesBuffer(void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (size > fPackageAttributesUncompressedLength
|
||||||
|
- fCurrentPackageAttributesOffset) {
|
||||||
|
fErrorOutput->PrintError(
|
||||||
|
"_ReadPackageAttributesBuffer(%lu): read beyond section end\n",
|
||||||
|
size);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, fPackageAttributesSection + fCurrentPackageAttributesOffset,
|
||||||
|
size);
|
||||||
|
fCurrentPackageAttributesOffset += size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageReaderImpl::_ReadBuffer(off_t offset, void* buffer, size_t size)
|
PackageReaderImpl::_ReadBuffer(off_t offset, void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1068,6 +1068,7 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
|
|||||||
_WriteString(licenseList.ItemAt(i)->String());
|
_WriteString(licenseList.ItemAt(i)->String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// provides list
|
||||||
const BObjectList<BPackageResolvable>& providesList
|
const BObjectList<BPackageResolvable>& providesList
|
||||||
= fPackageInfo.ProvidesList();
|
= fPackageInfo.ProvidesList();
|
||||||
for (int i = 0; i < providesList.CountItems(); ++i) {
|
for (int i = 0; i < providesList.CountItems(); ++i) {
|
||||||
@@ -1075,31 +1076,41 @@ PackageWriterImpl::_WritePackageAttributes(hpkg_header& header)
|
|||||||
bool hasVersion = resolvable->Version().InitCheck() == B_OK;
|
bool hasVersion = resolvable->Version().InitCheck() == B_OK;
|
||||||
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT,
|
B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT,
|
||||||
B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT, hasVersion ? 1 : 0));
|
B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT, 0));
|
||||||
_Write<uint8>(fPackageInfo.Architecture());
|
_Write<uint8>((uint8)resolvable->Type());
|
||||||
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING,
|
B_HPKG_PACKAGE_ATTRIBUTE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING,
|
||||||
B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, 1));
|
B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion));
|
||||||
_WriteString(resolvable->AsString().String());
|
_WriteString(resolvable->Name().String());
|
||||||
if (hasVersion) {
|
if (hasVersion) {
|
||||||
_WritePackageVersion(resolvable->Version());
|
_WritePackageVersion(resolvable->Version());
|
||||||
_Write<uint8>(0);
|
_Write<uint8>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BObjectList<BPackageResolvableExpression>& requiresList
|
// requires list
|
||||||
= fPackageInfo.RequiresList();
|
_WritePackageResolvableExpressionList(fPackageInfo.RequiresList(),
|
||||||
for (int i = 0; i < requiresList.CountItems(); ++i) {
|
B_HPKG_PACKAGE_ATTRIBUTE_REQUIRES);
|
||||||
BPackageResolvableExpression* resolvableExpr = requiresList.ItemAt(i);
|
|
||||||
bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK;
|
// supplements list
|
||||||
|
_WritePackageResolvableExpressionList(fPackageInfo.SupplementsList(),
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_SUPPLEMENTS);
|
||||||
|
|
||||||
|
// conflicts list
|
||||||
|
_WritePackageResolvableExpressionList(fPackageInfo.ConflictsList(),
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_CONFLICTS);
|
||||||
|
|
||||||
|
// freshens list
|
||||||
|
_WritePackageResolvableExpressionList(fPackageInfo.FreshensList(),
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_FRESHENS);
|
||||||
|
|
||||||
|
// replaces list
|
||||||
|
const BObjectList<BString>& replacesList = fPackageInfo.ReplacesList();
|
||||||
|
for (int i = 0; i < replacesList.CountItems(); ++i) {
|
||||||
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
||||||
B_HPKG_PACKAGE_ATTRIBUTE_REQUIRES, B_HPKG_ATTRIBUTE_TYPE_STRING,
|
B_HPKG_PACKAGE_ATTRIBUTE_REPLACES, B_HPKG_ATTRIBUTE_TYPE_STRING,
|
||||||
B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion));
|
B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, 0));
|
||||||
_WriteString(resolvableExpr->AsString().String());
|
_WriteString(replacesList.ItemAt(i)->String());
|
||||||
if (hasVersion) {
|
|
||||||
_WritePackageVersion(resolvableExpr->Version());
|
|
||||||
_Write<uint8>(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_Write<uint8>(0);
|
_Write<uint8>(0);
|
||||||
@@ -1143,6 +1154,30 @@ PackageWriterImpl::_WritePackageVersion(const BPackageVersion& version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageWriterImpl::_WritePackageResolvableExpressionList(
|
||||||
|
const BObjectList<BPackageResolvableExpression>& list, uint8 id)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < list.CountItems(); ++i) {
|
||||||
|
BPackageResolvableExpression* resolvableExpr = list.ItemAt(i);
|
||||||
|
bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK;
|
||||||
|
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
||||||
|
id, B_HPKG_ATTRIBUTE_TYPE_STRING,
|
||||||
|
B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE, hasVersion));
|
||||||
|
_WriteString(resolvableExpr->Name().String());
|
||||||
|
if (hasVersion) {
|
||||||
|
_WriteUnsignedLEB128(B_HPKG_PACKAGE_ATTRIBUTE_TAG_COMPOSE(
|
||||||
|
B_HPKG_PACKAGE_ATTRIBUTE_RESOLVABLE_OPERATOR,
|
||||||
|
B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT,
|
||||||
|
0));
|
||||||
|
_Write<uint8>(resolvableExpr->Operator());
|
||||||
|
_WritePackageVersion(resolvableExpr->Version());
|
||||||
|
_Write<uint8>(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
|
PackageWriterImpl::_WriteAttributeValue(const AttributeValue& value,
|
||||||
uint8 encoding)
|
uint8 encoding)
|
||||||
|
|||||||
Reference in New Issue
Block a user