xref: /haiku/src/bin/package/command_dump.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2009-2013, 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 #include <package/hpkg/StandardErrorOutput.h>
21 
22 #include "package.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 HandleSectionStart(BHPKGPackageSectionID sectionID,
38 		bool& _handleSection)
39 	{
40 		const char* sectionName;
41 
42 		switch (sectionID) {
43 			case B_HPKG_SECTION_HEADER:
44 				sectionName = "header";
45 				break;
46 			case B_HPKG_SECTION_HEAP:
47 				sectionName = "heap";
48 				break;
49 			case B_HPKG_SECTION_PACKAGE_TOC:
50 				sectionName = "TOC";
51 				break;
52 			case B_HPKG_SECTION_PACKAGE_ATTRIBUTES:
53 				sectionName = "package attributes";
54 				break;
55 			case B_HPKG_SECTION_REPOSITORY_INFO:
56 				sectionName = "repository info";
57 				break;
58 			default:
59 				sectionName = "<unknown section>";
60 				break;
61 		}
62 
63 		printf("\n====  SECTION: %s ====\n", sectionName);
64 
65 		_handleSection = true;
66 		return B_OK;
67 	}
68 
69 	virtual status_t HandleSectionEnd(BHPKGPackageSectionID sectionID)
70 	{
71 		return B_OK;
72 	}
73 
74 	virtual status_t HandleAttribute(BHPKGAttributeID attributeID,
75 		const BPackageAttributeValue& value, void* parentToken, void*& _token)
76 	{
77 		if (fErrorOccurred)
78 			return B_OK;
79 
80 		printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID));
81 		_PrintValue(value);
82 		printf("\n");
83 
84 		fHasChildren = false;
85 		fLevel++;
86 		return B_OK;
87 	}
88 
89 	virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID,
90 		const BPackageAttributeValue& value, void* parentToken, void* token)
91 	{
92 		if (fErrorOccurred)
93 			return B_OK;
94 
95 		fLevel--;
96 
97 		if (fHasChildren)
98 			printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID));
99 
100 		fHasChildren = true;
101 		return B_OK;
102 	}
103 
104 	virtual void HandleErrorOccurred()
105 	{
106 		fErrorOccurred = true;
107 	}
108 
109 private:
110 	void _PrintValue(const BPackageAttributeValue& value)
111 	{
112 		switch (value.type) {
113 			case B_HPKG_ATTRIBUTE_TYPE_INT:
114 				printf("%lld (%#llx)", (long long)value.signedInt,
115 					(long long)value.signedInt);
116 				break;
117 			case B_HPKG_ATTRIBUTE_TYPE_UINT:
118 				printf("%llu (%#llx)", (unsigned long long)value.unsignedInt,
119 					(unsigned long long)value.unsignedInt);
120 				break;
121 			case B_HPKG_ATTRIBUTE_TYPE_STRING:
122 				printf("\"%s\"", value.string);
123 				break;
124 			case B_HPKG_ATTRIBUTE_TYPE_RAW:
125 				switch (value.encoding) {
126 					case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE:
127 						printf("data: size: %llu, inline",
128 							(unsigned long long)value.data.size);
129 						// TODO: Print the data bytes!
130 						break;
131 					case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP:
132 						printf("data: size: %llu, offset: %llu",
133 							(unsigned long long)value.data.size,
134 							(unsigned long long)value.data.offset);
135 						break;
136 					default:
137 						break;
138 				}
139 				break;
140 			default:
141 				printf("<unknown type %u>\n", value.type);
142 				break;
143 		}
144 	}
145 
146 private:
147 	int		fLevel;
148 	bool	fErrorOccurred;
149 	bool	fHasChildren;
150 };
151 
152 
153 int
154 command_dump(int argc, const char* const* argv)
155 {
156 	while (true) {
157 		static struct option sLongOptions[] = {
158 			{ "help", no_argument, 0, 'h' },
159 			{ 0, 0, 0, 0 }
160 		};
161 
162 		opterr = 0; // don't print errors
163 		int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL);
164 		if (c == -1)
165 			break;
166 
167 		switch (c) {
168 			case 'h':
169 				print_usage_and_exit(false);
170 				break;
171 
172 			default:
173 				print_usage_and_exit(true);
174 				break;
175 		}
176 	}
177 
178 	// One argument should remain -- the package file name.
179 	if (optind + 1 != argc)
180 		print_usage_and_exit(true);
181 
182 	const char* packageFileName = argv[optind++];
183 
184 	// open package
185 	BStandardErrorOutput errorOutput;
186 	BPackageReader packageReader(&errorOutput);
187 	status_t error = packageReader.Init(packageFileName);
188 	if (error != B_OK)
189 		return 1;
190 
191 	// list
192 	PackageContentDumpHandler handler;
193 	error = packageReader.ParseContent(&handler);
194 	if (error != B_OK)
195 		return 1;
196 
197 	return 0;
198 }
199