command_dump.cpp revision 33bc4425
1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <ctype.h>
8#include <errno.h>
9#include <getopt.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <package/hpkg/HPKGDefs.h>
15#include <package/hpkg/PackageAttributeValue.h>
16#include <package/hpkg/PackageContentHandler.h>
17#include <package/hpkg/PackageEntry.h>
18#include <package/hpkg/PackageEntryAttribute.h>
19#include <package/hpkg/PackageReader.h>
20
21#include "package.h"
22#include "StandardErrorOutput.h"
23
24
25using namespace BPackageKit::BHPKG;
26
27
28struct PackageContentDumpHandler : BLowLevelPackageContentHandler {
29	PackageContentDumpHandler()
30		:
31		fLevel(0),
32		fErrorOccurred(false),
33		fHasChildren(false)
34	{
35	}
36
37	virtual status_t HandleAttribute(BHPKGAttributeID attributeID,
38		const BPackageAttributeValue& value, void* parentToken, void*& _token)
39	{
40		if (fErrorOccurred)
41			return B_OK;
42
43		printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID));
44		_PrintValue(value);
45		printf("\n");
46
47		fHasChildren = false;
48		fLevel++;
49		return B_OK;
50	}
51
52	virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID,
53		const BPackageAttributeValue& value, void* token)
54	{
55		if (fErrorOccurred)
56			return B_OK;
57
58		fLevel--;
59
60		if (fHasChildren)
61			printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID));
62
63		fHasChildren = true;
64		return B_OK;
65	}
66
67	virtual void HandleErrorOccurred()
68	{
69		fErrorOccurred = true;
70	}
71
72private:
73	void _PrintValue(const BPackageAttributeValue& value)
74	{
75		switch (value.type) {
76			case B_HPKG_ATTRIBUTE_TYPE_INT:
77				printf("%lld (%#llx)", value.signedInt, value.signedInt);
78				break;
79			case B_HPKG_ATTRIBUTE_TYPE_UINT:
80				printf("%llu (%#llx)", value.unsignedInt, value.unsignedInt);
81				break;
82			case B_HPKG_ATTRIBUTE_TYPE_STRING:
83				printf("\"%s\"", value.string);
84				break;
85			case B_HPKG_ATTRIBUTE_TYPE_RAW:
86				switch (value.encoding) {
87					case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE:
88						printf("data: size: %llu, inline", value.data.size);
89						// TODO: Print the data bytes!
90						break;
91					case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP:
92						printf("data: size: %llu, offset: %llu",
93							value.data.size, value.data.offset);
94						break;
95					default:
96						break;
97				}
98				break;
99			default:
100				printf("<unknown type %u>\n", value.type);
101				break;
102		}
103	}
104
105private:
106	int		fLevel;
107	bool	fErrorOccurred;
108	bool	fHasChildren;
109};
110
111
112int
113command_dump(int argc, const char* const* argv)
114{
115	while (true) {
116		static struct option sLongOptions[] = {
117			{ "help", no_argument, 0, 'h' },
118			{ 0, 0, 0, 0 }
119		};
120
121		opterr = 0; // don't print errors
122		int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL);
123		if (c == -1)
124			break;
125
126		switch (c) {
127			case 'h':
128				print_usage_and_exit(false);
129				break;
130
131			default:
132				print_usage_and_exit(true);
133				break;
134		}
135	}
136
137	// One argument should remain -- the package file name.
138	if (optind + 1 != argc)
139		print_usage_and_exit(true);
140
141	const char* packageFileName = argv[optind++];
142
143	// open package
144	StandardErrorOutput errorOutput;
145	BPackageReader packageReader(&errorOutput);
146	status_t error = packageReader.Init(packageFileName);
147	if (error != B_OK)
148		return 1;
149
150	// list
151	PackageContentDumpHandler handler;
152	error = packageReader.ParseContent(&handler);
153	if (error != B_OK)
154		return 1;
155
156	return 0;
157}
158