1050aa61bSIngo Weinhold/*
21f633814SIngo Weinhold * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3050aa61bSIngo Weinhold * Distributed under the terms of the MIT License.
4050aa61bSIngo Weinhold */
5050aa61bSIngo Weinhold
6050aa61bSIngo Weinhold
7050aa61bSIngo Weinhold#include <ctype.h>
8050aa61bSIngo Weinhold#include <errno.h>
9050aa61bSIngo Weinhold#include <getopt.h>
10050aa61bSIngo Weinhold#include <stdio.h>
11050aa61bSIngo Weinhold#include <stdlib.h>
12050aa61bSIngo Weinhold#include <string.h>
13050aa61bSIngo Weinhold
145fb1c6ffSOliver Tappe#include <package/hpkg/HPKGDefs.h>
155fb1c6ffSOliver Tappe#include <package/hpkg/PackageAttributeValue.h>
165fb1c6ffSOliver Tappe#include <package/hpkg/PackageContentHandler.h>
170d6b3b20SOliver Tappe#include <package/hpkg/PackageEntry.h>
180d6b3b20SOliver Tappe#include <package/hpkg/PackageEntryAttribute.h>
190d6b3b20SOliver Tappe#include <package/hpkg/PackageReader.h>
200816749eSIngo Weinhold#include <package/hpkg/StandardErrorOutput.h>
210d6b3b20SOliver Tappe
22050aa61bSIngo Weinhold#include "package.h"
23050aa61bSIngo Weinhold
24050aa61bSIngo Weinhold
255fb1c6ffSOliver Tappeusing namespace BPackageKit::BHPKG;
260d6b3b20SOliver Tappe
270d6b3b20SOliver Tappe
285fb1c6ffSOliver Tappestruct PackageContentDumpHandler : BLowLevelPackageContentHandler {
29050aa61bSIngo Weinhold	PackageContentDumpHandler()
30050aa61bSIngo Weinhold		:
31050aa61bSIngo Weinhold		fLevel(0),
32050aa61bSIngo Weinhold		fErrorOccurred(false),
33050aa61bSIngo Weinhold		fHasChildren(false)
34050aa61bSIngo Weinhold	{
35050aa61bSIngo Weinhold	}
36050aa61bSIngo Weinhold
3797aabbedSIngo Weinhold	virtual status_t HandleSectionStart(BHPKGPackageSectionID sectionID,
3897aabbedSIngo Weinhold		bool& _handleSection)
3997aabbedSIngo Weinhold	{
4097aabbedSIngo Weinhold		const char* sectionName;
4197aabbedSIngo Weinhold
4297aabbedSIngo Weinhold		switch (sectionID) {
4397aabbedSIngo Weinhold			case B_HPKG_SECTION_HEADER:
4497aabbedSIngo Weinhold				sectionName = "header";
4597aabbedSIngo Weinhold				break;
4697aabbedSIngo Weinhold			case B_HPKG_SECTION_HEAP:
4797aabbedSIngo Weinhold				sectionName = "heap";
4897aabbedSIngo Weinhold				break;
4997aabbedSIngo Weinhold			case B_HPKG_SECTION_PACKAGE_TOC:
5097aabbedSIngo Weinhold				sectionName = "TOC";
5197aabbedSIngo Weinhold				break;
5297aabbedSIngo Weinhold			case B_HPKG_SECTION_PACKAGE_ATTRIBUTES:
5397aabbedSIngo Weinhold				sectionName = "package attributes";
5497aabbedSIngo Weinhold				break;
5597aabbedSIngo Weinhold			case B_HPKG_SECTION_REPOSITORY_INFO:
5697aabbedSIngo Weinhold				sectionName = "repository info";
5797aabbedSIngo Weinhold				break;
5897aabbedSIngo Weinhold			default:
5997aabbedSIngo Weinhold				sectionName = "<unknown section>";
6097aabbedSIngo Weinhold				break;
6197aabbedSIngo Weinhold		}
6297aabbedSIngo Weinhold
6397aabbedSIngo Weinhold		printf("\n====  SECTION: %s ====\n", sectionName);
6497aabbedSIngo Weinhold
6597aabbedSIngo Weinhold		_handleSection = true;
6697aabbedSIngo Weinhold		return B_OK;
6797aabbedSIngo Weinhold	}
6897aabbedSIngo Weinhold
6997aabbedSIngo Weinhold	virtual status_t HandleSectionEnd(BHPKGPackageSectionID sectionID)
7097aabbedSIngo Weinhold	{
7197aabbedSIngo Weinhold		return B_OK;
7297aabbedSIngo Weinhold	}
7397aabbedSIngo Weinhold
7433bc4425SOliver Tappe	virtual status_t HandleAttribute(BHPKGAttributeID attributeID,
755fb1c6ffSOliver Tappe		const BPackageAttributeValue& value, void* parentToken, void*& _token)
76050aa61bSIngo Weinhold	{
77050aa61bSIngo Weinhold		if (fErrorOccurred)
78050aa61bSIngo Weinhold			return B_OK;
79050aa61bSIngo Weinhold
8033bc4425SOliver Tappe		printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID));
81050aa61bSIngo Weinhold		_PrintValue(value);
82050aa61bSIngo Weinhold		printf("\n");
83050aa61bSIngo Weinhold
84050aa61bSIngo Weinhold		fHasChildren = false;
85050aa61bSIngo Weinhold		fLevel++;
86050aa61bSIngo Weinhold		return B_OK;
87050aa61bSIngo Weinhold	}
88050aa61bSIngo Weinhold
8933bc4425SOliver Tappe	virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID,
90697b9545SIngo Weinhold		const BPackageAttributeValue& value, void* parentToken, void* token)
91050aa61bSIngo Weinhold	{
92050aa61bSIngo Weinhold		if (fErrorOccurred)
93050aa61bSIngo Weinhold			return B_OK;
94050aa61bSIngo Weinhold
95050aa61bSIngo Weinhold		fLevel--;
96050aa61bSIngo Weinhold
97050aa61bSIngo Weinhold		if (fHasChildren)
9833bc4425SOliver Tappe			printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID));
99050aa61bSIngo Weinhold
100050aa61bSIngo Weinhold		fHasChildren = true;
101050aa61bSIngo Weinhold		return B_OK;
102050aa61bSIngo Weinhold	}
103050aa61bSIngo Weinhold
104050aa61bSIngo Weinhold	virtual void HandleErrorOccurred()
105050aa61bSIngo Weinhold	{
106050aa61bSIngo Weinhold		fErrorOccurred = true;
107050aa61bSIngo Weinhold	}
108050aa61bSIngo Weinhold
109050aa61bSIngo Weinholdprivate:
1105fb1c6ffSOliver Tappe	void _PrintValue(const BPackageAttributeValue& value)
111050aa61bSIngo Weinhold	{
112050aa61bSIngo Weinhold		switch (value.type) {
113050aa61bSIngo Weinhold			case B_HPKG_ATTRIBUTE_TYPE_INT:
11442ae6444SIngo Weinhold				printf("%lld (%#llx)", (long long)value.signedInt,
11542ae6444SIngo Weinhold					(long long)value.signedInt);
116050aa61bSIngo Weinhold				break;
117050aa61bSIngo Weinhold			case B_HPKG_ATTRIBUTE_TYPE_UINT:
11842ae6444SIngo Weinhold				printf("%llu (%#llx)", (unsigned long long)value.unsignedInt,
11942ae6444SIngo Weinhold					(unsigned long long)value.unsignedInt);
120050aa61bSIngo Weinhold				break;
121050aa61bSIngo Weinhold			case B_HPKG_ATTRIBUTE_TYPE_STRING:
122050aa61bSIngo Weinhold				printf("\"%s\"", value.string);
123050aa61bSIngo Weinhold				break;
124050aa61bSIngo Weinhold			case B_HPKG_ATTRIBUTE_TYPE_RAW:
125050aa61bSIngo Weinhold				switch (value.encoding) {
126050aa61bSIngo Weinhold					case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE:
12742ae6444SIngo Weinhold						printf("data: size: %llu, inline",
12842ae6444SIngo Weinhold							(unsigned long long)value.data.size);
129050aa61bSIngo Weinhold						// TODO: Print the data bytes!
130050aa61bSIngo Weinhold						break;
131050aa61bSIngo Weinhold					case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP:
132050aa61bSIngo Weinhold						printf("data: size: %llu, offset: %llu",
13342ae6444SIngo Weinhold							(unsigned long long)value.data.size,
13442ae6444SIngo Weinhold							(unsigned long long)value.data.offset);
135050aa61bSIngo Weinhold						break;
136050aa61bSIngo Weinhold					default:
137050aa61bSIngo Weinhold						break;
138050aa61bSIngo Weinhold				}
139050aa61bSIngo Weinhold				break;
140050aa61bSIngo Weinhold			default:
141050aa61bSIngo Weinhold				printf("<unknown type %u>\n", value.type);
142050aa61bSIngo Weinhold				break;
143050aa61bSIngo Weinhold		}
144050aa61bSIngo Weinhold	}
145050aa61bSIngo Weinhold
146050aa61bSIngo Weinholdprivate:
147050aa61bSIngo Weinhold	int		fLevel;
148050aa61bSIngo Weinhold	bool	fErrorOccurred;
149050aa61bSIngo Weinhold	bool	fHasChildren;
150050aa61bSIngo Weinhold};
151050aa61bSIngo Weinhold
152050aa61bSIngo Weinhold
153050aa61bSIngo Weinholdint
154050aa61bSIngo Weinholdcommand_dump(int argc, const char* const* argv)
155050aa61bSIngo Weinhold{
156050aa61bSIngo Weinhold	while (true) {
157050aa61bSIngo Weinhold		static struct option sLongOptions[] = {
158050aa61bSIngo Weinhold			{ "help", no_argument, 0, 'h' },
159050aa61bSIngo Weinhold			{ 0, 0, 0, 0 }
160050aa61bSIngo Weinhold		};
161050aa61bSIngo Weinhold
162050aa61bSIngo Weinhold		opterr = 0; // don't print errors
163050aa61bSIngo Weinhold		int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL);
164050aa61bSIngo Weinhold		if (c == -1)
165050aa61bSIngo Weinhold			break;
166050aa61bSIngo Weinhold
167050aa61bSIngo Weinhold		switch (c) {
168050aa61bSIngo Weinhold			case 'h':
169050aa61bSIngo Weinhold				print_usage_and_exit(false);
170050aa61bSIngo Weinhold				break;
171050aa61bSIngo Weinhold
172050aa61bSIngo Weinhold			default:
173050aa61bSIngo Weinhold				print_usage_and_exit(true);
174050aa61bSIngo Weinhold				break;
175050aa61bSIngo Weinhold		}
176050aa61bSIngo Weinhold	}
177050aa61bSIngo Weinhold
178050aa61bSIngo Weinhold	// One argument should remain -- the package file name.
179050aa61bSIngo Weinhold	if (optind + 1 != argc)
180050aa61bSIngo Weinhold		print_usage_and_exit(true);
181050aa61bSIngo Weinhold
182050aa61bSIngo Weinhold	const char* packageFileName = argv[optind++];
183050aa61bSIngo Weinhold
184050aa61bSIngo Weinhold	// open package
1850816749eSIngo Weinhold	BStandardErrorOutput errorOutput;
1865fb1c6ffSOliver Tappe	BPackageReader packageReader(&errorOutput);
187050aa61bSIngo Weinhold	status_t error = packageReader.Init(packageFileName);
188050aa61bSIngo Weinhold	if (error != B_OK)
189050aa61bSIngo Weinhold		return 1;
190050aa61bSIngo Weinhold
191050aa61bSIngo Weinhold	// list
192050aa61bSIngo Weinhold	PackageContentDumpHandler handler;
193050aa61bSIngo Weinhold	error = packageReader.ParseContent(&handler);
194050aa61bSIngo Weinhold	if (error != B_OK)
195050aa61bSIngo Weinhold		return 1;
196050aa61bSIngo Weinhold
197050aa61bSIngo Weinhold	return 0;
198050aa61bSIngo Weinhold}
199