* Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <package/hpkg/HPKGDefs.h>
#include <package/hpkg/PackageAttributeValue.h>
#include <package/hpkg/PackageContentHandler.h>
#include <package/hpkg/PackageEntry.h>
#include <package/hpkg/PackageEntryAttribute.h>
#include <package/hpkg/PackageReader.h>
#include <package/hpkg/StandardErrorOutput.h>
#include "package.h"
using namespace BPackageKit::BHPKG;
struct PackageContentDumpHandler : BLowLevelPackageContentHandler {
PackageContentDumpHandler()
:
fLevel(0),
fErrorOccurred(false),
fHasChildren(false)
{
}
virtual status_t HandleSectionStart(BHPKGPackageSectionID sectionID,
bool& _handleSection)
{
const char* sectionName;
switch (sectionID) {
case B_HPKG_SECTION_HEADER:
sectionName = "header";
break;
case B_HPKG_SECTION_HEAP:
sectionName = "heap";
break;
case B_HPKG_SECTION_PACKAGE_TOC:
sectionName = "TOC";
break;
case B_HPKG_SECTION_PACKAGE_ATTRIBUTES:
sectionName = "package attributes";
break;
case B_HPKG_SECTION_REPOSITORY_INFO:
sectionName = "repository info";
break;
default:
sectionName = "<unknown section>";
break;
}
printf("\n==== SECTION: %s ====\n", sectionName);
_handleSection = true;
return B_OK;
}
virtual status_t HandleSectionEnd(BHPKGPackageSectionID sectionID)
{
return B_OK;
}
virtual status_t HandleAttribute(BHPKGAttributeID attributeID,
const BPackageAttributeValue& value, void* parentToken, void*& _token)
{
if (fErrorOccurred)
return B_OK;
printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID));
_PrintValue(value);
printf("\n");
fHasChildren = false;
fLevel++;
return B_OK;
}
virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID,
const BPackageAttributeValue& value, void* parentToken, void* token)
{
if (fErrorOccurred)
return B_OK;
fLevel--;
if (fHasChildren)
printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID));
fHasChildren = true;
return B_OK;
}
virtual void HandleErrorOccurred()
{
fErrorOccurred = true;
}
private:
void _PrintValue(const BPackageAttributeValue& value)
{
switch (value.type) {
case B_HPKG_ATTRIBUTE_TYPE_INT:
printf("%lld (%#llx)", (long long)value.signedInt,
(long long)value.signedInt);
break;
case B_HPKG_ATTRIBUTE_TYPE_UINT:
printf("%llu (%#llx)", (unsigned long long)value.unsignedInt,
(unsigned long long)value.unsignedInt);
break;
case B_HPKG_ATTRIBUTE_TYPE_STRING:
printf("\"%s\"", value.string);
break;
case B_HPKG_ATTRIBUTE_TYPE_RAW:
switch (value.encoding) {
case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE:
printf("data: size: %llu, inline",
(unsigned long long)value.data.size);
break;
case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP:
printf("data: size: %llu, offset: %llu",
(unsigned long long)value.data.size,
(unsigned long long)value.data.offset);
break;
default:
break;
}
break;
default:
printf("<unknown type %u>\n", value.type);
break;
}
}
private:
int fLevel;
bool fErrorOccurred;
bool fHasChildren;
};
int
command_dump(int argc, const char* const* argv)
{
while (true) {
static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
opterr = 0;
int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'h':
print_usage_and_exit(false);
break;
default:
print_usage_and_exit(true);
break;
}
}
if (optind + 1 != argc)
print_usage_and_exit(true);
const char* packageFileName = argv[optind++];
BStandardErrorOutput errorOutput;
BPackageReader packageReader(&errorOutput);
status_t error = packageReader.Init(packageFileName);
if (error != B_OK)
return 1;
PackageContentDumpHandler handler;
error = packageReader.ParseContent(&handler);
if (error != B_OK)
return 1;
return 0;
}