xref: /haiku/src/bin/package/command_dump.cpp (revision b46615c55ad2c8fe6de54412055a0713da3d610a)
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 
25 using namespace BPackageKit::BHPKG;
26 
27 
28 struct 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 
72 private:
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 
105 private:
106 	int		fLevel;
107 	bool	fErrorOccurred;
108 	bool	fHasChildren;
109 };
110 
111 
112 int
113 command_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