15fb1c6ffSOliver Tappe/*
26a89a36aSIngo Weinhold * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3884a0b23SOliver Tappe * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
45fb1c6ffSOliver Tappe * Distributed under the terms of the MIT License.
55fb1c6ffSOliver Tappe */
65fb1c6ffSOliver Tappe
75fb1c6ffSOliver Tappe
85fb1c6ffSOliver Tappe#include <package/hpkg/PackageReaderImpl.h>
95fb1c6ffSOliver Tappe
105fb1c6ffSOliver Tappe#include <errno.h>
115fb1c6ffSOliver Tappe#include <fcntl.h>
125fb1c6ffSOliver Tappe#include <stdio.h>
135fb1c6ffSOliver Tappe#include <stdlib.h>
145fb1c6ffSOliver Tappe#include <string.h>
155fb1c6ffSOliver Tappe#include <sys/stat.h>
165fb1c6ffSOliver Tappe#include <unistd.h>
175fb1c6ffSOliver Tappe
185fb1c6ffSOliver Tappe#include <algorithm>
195fb1c6ffSOliver Tappe#include <new>
205fb1c6ffSOliver Tappe
215fb1c6ffSOliver Tappe#include <ByteOrder.h>
225fb1c6ffSOliver Tappe
23e527b796SIngo Weinhold#include <FdIO.h>
24e527b796SIngo Weinhold
2533bc4425SOliver Tappe#include <package/hpkg/HPKGDefsPrivate.h>
265fb1c6ffSOliver Tappe
275fb1c6ffSOliver Tappe#include <package/hpkg/PackageData.h>
285fb1c6ffSOliver Tappe#include <package/hpkg/PackageEntry.h>
295fb1c6ffSOliver Tappe#include <package/hpkg/PackageEntryAttribute.h>
305fb1c6ffSOliver Tappe
315fb1c6ffSOliver Tappe
325fb1c6ffSOliver Tappenamespace BPackageKit {
335fb1c6ffSOliver Tappe
345fb1c6ffSOliver Tappenamespace BHPKG {
355fb1c6ffSOliver Tappe
365fb1c6ffSOliver Tappenamespace BPrivate {
375fb1c6ffSOliver Tappe
385fb1c6ffSOliver Tappe
395fb1c6ffSOliver Tappe//#define TRACE(format...)	printf(format)
405fb1c6ffSOliver Tappe#define TRACE(format...)	do {} while (false)
415fb1c6ffSOliver Tappe
425fb1c6ffSOliver Tappe
435fb1c6ffSOliver Tappe// maximum TOC size we support reading
446f0278cdSOliver Tappestatic const size_t kMaxTOCSize					= 64 * 1024 * 1024;
455fb1c6ffSOliver Tappe
466f0278cdSOliver Tappe// maximum package attributes size we support reading
476f0278cdSOliver Tappestatic const size_t kMaxPackageAttributesSize	= 1 * 1024 * 1024;
486f0278cdSOliver Tappe
495fb1c6ffSOliver Tappe
501f633814SIngo Weinholdstatic status_t
511f633814SIngo Weinholdset_package_data_from_attribute_value(const BPackageAttributeValue& value,
521f633814SIngo Weinhold	BPackageData& data)
531f633814SIngo Weinhold{
541f633814SIngo Weinhold	if (value.encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE)
551f633814SIngo Weinhold		data.SetData(value.data.size, value.data.raw);
561f633814SIngo Weinhold	else
571f633814SIngo Weinhold		data.SetData(value.data.size, value.data.offset);
581f633814SIngo Weinhold	return B_OK;
591f633814SIngo Weinhold}
605fb1c6ffSOliver Tappe
615fb1c6ffSOliver Tappe
62ad6a8dbeSOliver Tappe// #pragma mark - AttributeAttributeHandler
63ad6a8dbeSOliver Tappe
64ad6a8dbeSOliver Tappe
655fb1c6ffSOliver Tappestruct PackageReaderImpl::AttributeAttributeHandler : AttributeHandler {
665fb1c6ffSOliver Tappe	AttributeAttributeHandler(BPackageEntry* entry, const char* name)
675fb1c6ffSOliver Tappe		:
685fb1c6ffSOliver Tappe		fEntry(entry),
695fb1c6ffSOliver Tappe		fAttribute(name)
705fb1c6ffSOliver Tappe	{
715fb1c6ffSOliver Tappe	}
725fb1c6ffSOliver Tappe
7333bc4425SOliver Tappe	virtual status_t HandleAttribute(AttributeHandlerContext* context,
7433bc4425SOliver Tappe		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
755fb1c6ffSOliver Tappe	{
7633bc4425SOliver Tappe		switch (id) {
7733bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_DATA:
781f633814SIngo Weinhold				return set_package_data_from_attribute_value(value,
791f633814SIngo Weinhold					fAttribute.Data());
805fb1c6ffSOliver Tappe
8133bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE:
825fb1c6ffSOliver Tappe				fAttribute.SetType(value.unsignedInt);
835fb1c6ffSOliver Tappe				return B_OK;
845fb1c6ffSOliver Tappe		}
855fb1c6ffSOliver Tappe
8633bc4425SOliver Tappe		return AttributeHandler::HandleAttribute(context, id, value, _handler);
875fb1c6ffSOliver Tappe	}
885fb1c6ffSOliver Tappe
895fb1c6ffSOliver Tappe	virtual status_t Delete(AttributeHandlerContext* context)
905fb1c6ffSOliver Tappe	{
915fb1c6ffSOliver Tappe		status_t error = context->packageContentHandler->HandleEntryAttribute(
925fb1c6ffSOliver Tappe			fEntry, &fAttribute);
935fb1c6ffSOliver Tappe
945fb1c6ffSOliver Tappe		delete this;
955fb1c6ffSOliver Tappe		return error;
965fb1c6ffSOliver Tappe	}
975fb1c6ffSOliver Tappe
985fb1c6ffSOliver Tappeprivate:
995fb1c6ffSOliver Tappe	BPackageEntry*			fEntry;
1005fb1c6ffSOliver Tappe	BPackageEntryAttribute	fAttribute;
1015fb1c6ffSOliver Tappe};
1025fb1c6ffSOliver Tappe
1035fb1c6ffSOliver Tappe
104ad6a8dbeSOliver Tappe// #pragma mark - EntryAttributeHandler
105ad6a8dbeSOliver Tappe
106ad6a8dbeSOliver Tappe
1075fb1c6ffSOliver Tappestruct PackageReaderImpl::EntryAttributeHandler : AttributeHandler {
1085fb1c6ffSOliver Tappe	EntryAttributeHandler(AttributeHandlerContext* context,
1095fb1c6ffSOliver Tappe		BPackageEntry* parentEntry, const char* name)
1105fb1c6ffSOliver Tappe		:
1115fb1c6ffSOliver Tappe		fEntry(parentEntry, name),
1125fb1c6ffSOliver Tappe		fNotified(false)
1135fb1c6ffSOliver Tappe	{
1145fb1c6ffSOliver Tappe		_SetFileType(context, B_HPKG_DEFAULT_FILE_TYPE);
1155fb1c6ffSOliver Tappe	}
1165fb1c6ffSOliver Tappe
1175fb1c6ffSOliver Tappe	static status_t Create(AttributeHandlerContext* context,
1185fb1c6ffSOliver Tappe		BPackageEntry* parentEntry, const char* name,
1195fb1c6ffSOliver Tappe		AttributeHandler*& _handler)
1205fb1c6ffSOliver Tappe	{
1215fb1c6ffSOliver Tappe		// check name
1225fb1c6ffSOliver Tappe		if (name[0] == '\0' || strcmp(name, ".") == 0
1235fb1c6ffSOliver Tappe			|| strcmp(name, "..") == 0 || strchr(name, '/') != NULL) {
1245fb1c6ffSOliver Tappe			context->errorOutput->PrintError("Error: Invalid package: Invalid "
1255fb1c6ffSOliver Tappe				"entry name: \"%s\"\n", name);
1265fb1c6ffSOliver Tappe			return B_BAD_DATA;
1275fb1c6ffSOliver Tappe		}
1285fb1c6ffSOliver Tappe
1295fb1c6ffSOliver Tappe		// create handler
1305fb1c6ffSOliver Tappe		EntryAttributeHandler* handler = new(std::nothrow)
1315fb1c6ffSOliver Tappe			EntryAttributeHandler(context, parentEntry, name);
1325fb1c6ffSOliver Tappe		if (handler == NULL)
1335fb1c6ffSOliver Tappe			return B_NO_MEMORY;
1345fb1c6ffSOliver Tappe
1355fb1c6ffSOliver Tappe		_handler = handler;
1365fb1c6ffSOliver Tappe		return B_OK;
1375fb1c6ffSOliver Tappe	}
1385fb1c6ffSOliver Tappe
13933bc4425SOliver Tappe	virtual status_t HandleAttribute(AttributeHandlerContext* context,
14033bc4425SOliver Tappe		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
1415fb1c6ffSOliver Tappe	{
14233bc4425SOliver Tappe		switch (id) {
14333bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY:
1445fb1c6ffSOliver Tappe			{
1455fb1c6ffSOliver Tappe				status_t error = _Notify(context);
1465fb1c6ffSOliver Tappe				if (error != B_OK)
1475fb1c6ffSOliver Tappe					return error;
1485fb1c6ffSOliver Tappe
1495fb1c6ffSOliver Tappe//TRACE("%*sentry \"%s\"\n", fLevel * 2, "", value.string);
1505fb1c6ffSOliver Tappe				if (_handler != NULL) {
1515fb1c6ffSOliver Tappe					return EntryAttributeHandler::Create(context, &fEntry,
1525fb1c6ffSOliver Tappe						value.string, *_handler);
1535fb1c6ffSOliver Tappe				}
1545fb1c6ffSOliver Tappe				return B_OK;
1555fb1c6ffSOliver Tappe			}
1565fb1c6ffSOliver Tappe
15733bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_TYPE:
1585fb1c6ffSOliver Tappe				return _SetFileType(context, value.unsignedInt);
1595fb1c6ffSOliver Tappe
16033bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS:
1615fb1c6ffSOliver Tappe				fEntry.SetPermissions(value.unsignedInt);
1625fb1c6ffSOliver Tappe				return B_OK;
1635fb1c6ffSOliver Tappe
16433bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_USER:
16533bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_GROUP:
1665fb1c6ffSOliver Tappe				// TODO:...
1675fb1c6ffSOliver Tappe				break;
1685fb1c6ffSOliver Tappe
16933bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_ATIME:
1705fb1c6ffSOliver Tappe				fEntry.SetAccessTime(value.unsignedInt);
1715fb1c6ffSOliver Tappe				return B_OK;
1725fb1c6ffSOliver Tappe
17333bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_MTIME:
1745fb1c6ffSOliver Tappe				fEntry.SetModifiedTime(value.unsignedInt);
1755fb1c6ffSOliver Tappe				return B_OK;
1765fb1c6ffSOliver Tappe
17733bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_CRTIME:
1785fb1c6ffSOliver Tappe				fEntry.SetCreationTime(value.unsignedInt);
1795fb1c6ffSOliver Tappe				return B_OK;
1805fb1c6ffSOliver Tappe
18133bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_ATIME_NANOS:
1825fb1c6ffSOliver Tappe				fEntry.SetAccessTimeNanos(value.unsignedInt);
1835fb1c6ffSOliver Tappe				return B_OK;
1845fb1c6ffSOliver Tappe
18533bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_MTIME_NANOS:
1865fb1c6ffSOliver Tappe				fEntry.SetModifiedTimeNanos(value.unsignedInt);
1875fb1c6ffSOliver Tappe				return B_OK;
1885fb1c6ffSOliver Tappe
18933bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_CRTIM_NANOS:
1905fb1c6ffSOliver Tappe				fEntry.SetCreationTimeNanos(value.unsignedInt);
1915fb1c6ffSOliver Tappe				return B_OK;
1925fb1c6ffSOliver Tappe
19333bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE:
1945fb1c6ffSOliver Tappe			{
1955fb1c6ffSOliver Tappe				status_t error = _Notify(context);
1965fb1c6ffSOliver Tappe				if (error != B_OK)
1975fb1c6ffSOliver Tappe					return error;
1985fb1c6ffSOliver Tappe
1995fb1c6ffSOliver Tappe				if (_handler != NULL) {
2005fb1c6ffSOliver Tappe					*_handler = new(std::nothrow) AttributeAttributeHandler(
2015fb1c6ffSOliver Tappe						&fEntry, value.string);
2025fb1c6ffSOliver Tappe					if (*_handler == NULL)
2035fb1c6ffSOliver Tappe						return B_NO_MEMORY;
2045fb1c6ffSOliver Tappe					return B_OK;
2055fb1c6ffSOliver Tappe				} else {
2065fb1c6ffSOliver Tappe					BPackageEntryAttribute attribute(value.string);
2075fb1c6ffSOliver Tappe					return context->packageContentHandler->HandleEntryAttribute(
2085fb1c6ffSOliver Tappe						&fEntry, &attribute);
2095fb1c6ffSOliver Tappe				}
2105fb1c6ffSOliver Tappe			}
2115fb1c6ffSOliver Tappe
21233bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_DATA:
2131f633814SIngo Weinhold				return set_package_data_from_attribute_value(value,
2141f633814SIngo Weinhold					fEntry.Data());
2155fb1c6ffSOliver Tappe
21633bc4425SOliver Tappe			case B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH:
2175fb1c6ffSOliver Tappe				fEntry.SetSymlinkPath(value.string);
2185fb1c6ffSOliver Tappe				return B_OK;
2195fb1c6ffSOliver Tappe		}
2205fb1c6ffSOliver Tappe
22133bc4425SOliver Tappe		return AttributeHandler::HandleAttribute(context, id, value, _handler);
2225fb1c6ffSOliver Tappe	}
2235fb1c6ffSOliver Tappe
2245fb1c6ffSOliver Tappe	virtual status_t Delete(AttributeHandlerContext* context)
2255fb1c6ffSOliver Tappe	{
2265fb1c6ffSOliver Tappe		// notify if not done yet
2275fb1c6ffSOliver Tappe		status_t error = _Notify(context);
2285fb1c6ffSOliver Tappe
2295fb1c6ffSOliver Tappe		// notify done
2305fb1c6ffSOliver Tappe		if (error == B_OK)
2315fb1c6ffSOliver Tappe			error = context->packageContentHandler->HandleEntryDone(&fEntry);
2325fb1c6ffSOliver Tappe		else
2335fb1c6ffSOliver Tappe			context->packageContentHandler->HandleEntryDone(&fEntry);
2345fb1c6ffSOliver Tappe
2355fb1c6ffSOliver Tappe		delete this;
2365fb1c6ffSOliver Tappe		return error;
2375fb1c6ffSOliver Tappe	}
2385fb1c6ffSOliver Tappe
2395fb1c6ffSOliver Tappeprivate:
2405fb1c6ffSOliver Tappe	status_t _Notify(AttributeHandlerContext* context)
2415fb1c6ffSOliver Tappe	{
2425fb1c6ffSOliver Tappe		if (fNotified)
2435fb1c6ffSOliver Tappe			return B_OK;
2445fb1c6ffSOliver Tappe
2455fb1c6ffSOliver Tappe		fNotified = true;
2465fb1c6ffSOliver Tappe		return context->packageContentHandler->HandleEntry(&fEntry);
2475fb1c6ffSOliver Tappe	}
2485fb1c6ffSOliver Tappe
2495fb1c6ffSOliver Tappe	status_t _SetFileType(AttributeHandlerContext* context, uint64 fileType)
2505fb1c6ffSOliver Tappe	{
2515fb1c6ffSOliver Tappe		switch (fileType) {
2525fb1c6ffSOliver Tappe			case B_HPKG_FILE_TYPE_FILE:
2535fb1c6ffSOliver Tappe				fEntry.SetType(S_IFREG);
2545fb1c6ffSOliver Tappe				fEntry.SetPermissions(B_HPKG_DEFAULT_FILE_PERMISSIONS);
2555fb1c6ffSOliver Tappe				break;
25633bc4425SOliver Tappe
2575fb1c6ffSOliver Tappe			case B_HPKG_FILE_TYPE_DIRECTORY:
2585fb1c6ffSOliver Tappe				fEntry.SetType(S_IFDIR);
2595fb1c6ffSOliver Tappe				fEntry.SetPermissions(B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS);
2605fb1c6ffSOliver Tappe				break;
26133bc4425SOliver Tappe
2625fb1c6ffSOliver Tappe			case B_HPKG_FILE_TYPE_SYMLINK:
2635fb1c6ffSOliver Tappe				fEntry.SetType(S_IFLNK);
2645fb1c6ffSOliver Tappe				fEntry.SetPermissions(B_HPKG_DEFAULT_SYMLINK_PERMISSIONS);
2655fb1c6ffSOliver Tappe				break;
26633bc4425SOliver Tappe
2675fb1c6ffSOliver Tappe			default:
2685fb1c6ffSOliver Tappe				context->errorOutput->PrintError("Error: Invalid file type for "
2695fb1c6ffSOliver Tappe					"package entry (%llu)\n", fileType);
2705fb1c6ffSOliver Tappe				return B_BAD_DATA;
2715fb1c6ffSOliver Tappe		}
2725fb1c6ffSOliver Tappe		return B_OK;
2735fb1c6ffSOliver Tappe	}
2745fb1c6ffSOliver Tappe
2755fb1c6ffSOliver Tappeprivate:
27633bc4425SOliver Tappe	BPackageEntry	fEntry;
27733bc4425SOliver Tappe	bool			fNotified;
2785fb1c6ffSOliver Tappe};
2795fb1c6ffSOliver Tappe
2805fb1c6ffSOliver Tappe
281ad6a8dbeSOliver Tappe// #pragma mark - RootAttributeHandler
28233bc4425SOliver Tappe
28333bc4425SOliver Tappe
28433bc4425SOliver Tappestruct PackageReaderImpl::RootAttributeHandler : PackageAttributeHandler {
28533bc4425SOliver Tappe	typedef PackageAttributeHandler inherited;
28633bc4425SOliver Tappe
28733bc4425SOliver Tappe	virtual status_t HandleAttribute(AttributeHandlerContext* context,
28833bc4425SOliver Tappe		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
28933bc4425SOliver Tappe	{
29033bc4425SOliver Tappe		if (id == B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY) {
2915fb1c6ffSOliver Tappe			if (_handler != NULL) {
2925fb1c6ffSOliver Tappe				return EntryAttributeHandler::Create(context, NULL,
2935fb1c6ffSOliver Tappe					value.string, *_handler);
2945fb1c6ffSOliver Tappe			}
2955fb1c6ffSOliver Tappe			return B_OK;
2965fb1c6ffSOliver Tappe		}
2975fb1c6ffSOliver Tappe
29833bc4425SOliver Tappe		return inherited::HandleAttribute(context, id, value, _handler);
2995fb1c6ffSOliver Tappe	}
3005fb1c6ffSOliver Tappe};
3015fb1c6ffSOliver Tappe
3025fb1c6ffSOliver Tappe
3035fb1c6ffSOliver Tappe// #pragma mark - PackageReaderImpl
3045fb1c6ffSOliver Tappe
3055fb1c6ffSOliver Tappe
3065fb1c6ffSOliver TappePackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput)
3075fb1c6ffSOliver Tappe	:
3081f633814SIngo Weinhold	inherited("package", errorOutput),
309ad6a8dbeSOliver Tappe	fTOCSection("TOC")
3105fb1c6ffSOliver Tappe{
3115fb1c6ffSOliver Tappe}
3125fb1c6ffSOliver Tappe
3135fb1c6ffSOliver Tappe
3145fb1c6ffSOliver TappePackageReaderImpl::~PackageReaderImpl()
3155fb1c6ffSOliver Tappe{
3165fb1c6ffSOliver Tappe}
3175fb1c6ffSOliver Tappe
3185fb1c6ffSOliver Tappe
3195fb1c6ffSOliver Tappestatus_t
320d59e0febSIngo WeinholdPackageReaderImpl::Init(const char* fileName, uint32 flags)
3215fb1c6ffSOliver Tappe{
3225fb1c6ffSOliver Tappe	// open file
3235fb1c6ffSOliver Tappe	int fd = open(fileName, O_RDONLY);
3245fb1c6ffSOliver Tappe	if (fd < 0) {
325ad6a8dbeSOliver Tappe		ErrorOutput()->PrintError("Error: Failed to open package file \"%s\": "
3265fb1c6ffSOliver Tappe			"%s\n", fileName, strerror(errno));
3275fb1c6ffSOliver Tappe		return errno;
3285fb1c6ffSOliver Tappe	}
3295fb1c6ffSOliver Tappe
330d59e0febSIngo Weinhold	return Init(fd, true, flags);
3315fb1c6ffSOliver Tappe}
3325fb1c6ffSOliver Tappe
3335fb1c6ffSOliver Tappe
3345fb1c6ffSOliver Tappestatus_t
335d59e0febSIngo WeinholdPackageReaderImpl::Init(int fd, bool keepFD, uint32 flags)
336e527b796SIngo Weinhold{
337e527b796SIngo Weinhold	BFdIO* file = new(std::nothrow) BFdIO(fd, keepFD);
338e527b796SIngo Weinhold	if (file == NULL) {
339e527b796SIngo Weinhold		if (keepFD && fd >= 0)
340e527b796SIngo Weinhold			close(fd);
341e527b796SIngo Weinhold		return B_NO_MEMORY;
342e527b796SIngo Weinhold	}
343e527b796SIngo Weinhold
344e527b796SIngo Weinhold	return Init(file, true, flags);
345e527b796SIngo Weinhold}
346e527b796SIngo Weinhold
347e527b796SIngo Weinhold
348e527b796SIngo Weinholdstatus_t
3498f5130edSIngo WeinholdPackageReaderImpl::Init(BPositionIO* file, bool keepFile, uint32 flags,
3508f5130edSIngo Weinhold	hpkg_header* _header)
3515fb1c6ffSOliver Tappe{
3525fb1c6ffSOliver Tappe	hpkg_header header;
35379d5ddb7SIngo Weinhold	status_t error = inherited::Init<hpkg_header, B_HPKG_MAGIC, B_HPKG_VERSION,
354e527b796SIngo Weinhold		B_HPKG_MINOR_VERSION>(file, keepFile, header, flags);
3551f633814SIngo Weinhold	if (error != B_OK)
3565fb1c6ffSOliver Tappe		return error;
35746122852SIngo Weinhold	fHeapSize = UncompressedHeapSize();
3581f633814SIngo Weinhold
3591f633814SIngo Weinhold	// init package attributes section
3601f633814SIngo Weinhold	error = InitSection(fPackageAttributesSection, fHeapSize,
3611f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT32(header.attributes_length),
3621f633814SIngo Weinhold		kMaxPackageAttributesSize,
3631f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT32(header.attributes_strings_length),
3641f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT32(header.attributes_strings_count));
3655fb1c6ffSOliver Tappe	if (error != B_OK)
3665fb1c6ffSOliver Tappe		return error;
3675fb1c6ffSOliver Tappe
3681f633814SIngo Weinhold	// init TOC section
3691f633814SIngo Weinhold	error = InitSection(fTOCSection, fPackageAttributesSection.offset,
3701f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT64(header.toc_length), kMaxTOCSize,
3711f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT64(header.toc_strings_length),
3721f633814SIngo Weinhold		B_BENDIAN_TO_HOST_INT64(header.toc_strings_count));
3736f0278cdSOliver Tappe	if (error != B_OK)
3746f0278cdSOliver Tappe		return error;
3756f0278cdSOliver Tappe
3768f5130edSIngo Weinhold	if (_header != NULL)
3778f5130edSIngo Weinhold		*_header = header;
3788f5130edSIngo Weinhold
3795fb1c6ffSOliver Tappe	return B_OK;
3805fb1c6ffSOliver Tappe}
3815fb1c6ffSOliver Tappe
3825fb1c6ffSOliver Tappe
3835fb1c6ffSOliver Tappestatus_t
3845fb1c6ffSOliver TappePackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler)
3855fb1c6ffSOliver Tappe{
38643a6b92cSIngo Weinhold	status_t error = _PrepareSections();
38743a6b92cSIngo Weinhold	if (error != B_OK)
38843a6b92cSIngo Weinhold		return error;
38943a6b92cSIngo Weinhold
39097aabbedSIngo Weinhold	AttributeHandlerContext context(ErrorOutput(), contentHandler,
39147039b85SIngo Weinhold		B_HPKG_SECTION_PACKAGE_ATTRIBUTES,
39247039b85SIngo Weinhold		MinorFormatVersion() > B_HPKG_MINOR_VERSION);
3935fb1c6ffSOliver Tappe	RootAttributeHandler rootAttributeHandler;
39497aabbedSIngo Weinhold
39543a6b92cSIngo Weinhold	error = ParsePackageAttributesSection(&context, &rootAttributeHandler);
39697aabbedSIngo Weinhold
39797aabbedSIngo Weinhold	if (error == B_OK) {
39897aabbedSIngo Weinhold		context.section = B_HPKG_SECTION_PACKAGE_TOC;
39936d702ecSOliver Tappe		error = _ParseTOC(&context, &rootAttributeHandler);
40097aabbedSIngo Weinhold	}
40197aabbedSIngo Weinhold
402ad6a8dbeSOliver Tappe	return error;
4035fb1c6ffSOliver Tappe}
4045fb1c6ffSOliver Tappe
4055fb1c6ffSOliver Tappe
4065fb1c6ffSOliver Tappestatus_t
4075fb1c6ffSOliver TappePackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler)
4085fb1c6ffSOliver Tappe{
40943a6b92cSIngo Weinhold	status_t error = _PrepareSections();
41043a6b92cSIngo Weinhold	if (error != B_OK)
41143a6b92cSIngo Weinhold		return error;
41243a6b92cSIngo Weinhold
41397aabbedSIngo Weinhold	AttributeHandlerContext context(ErrorOutput(), contentHandler,
41447039b85SIngo Weinhold		B_HPKG_SECTION_PACKAGE_ATTRIBUTES,
41547039b85SIngo Weinhold		MinorFormatVersion() > B_HPKG_MINOR_VERSION);
41633bc4425SOliver Tappe	LowLevelAttributeHandler rootAttributeHandler;
41797aabbedSIngo Weinhold
41843a6b92cSIngo Weinhold	error = ParsePackageAttributesSection(&context, &rootAttributeHandler);
41997aabbedSIngo Weinhold
42097aabbedSIngo Weinhold	if (error == B_OK) {
42197aabbedSIngo Weinhold		context.section = B_HPKG_SECTION_PACKAGE_TOC;
42236d702ecSOliver Tappe		error = _ParseTOC(&context, &rootAttributeHandler);
42397aabbedSIngo Weinhold	}
42497aabbedSIngo Weinhold
425ad6a8dbeSOliver Tappe	return error;
4265fb1c6ffSOliver Tappe}
4275fb1c6ffSOliver Tappe
4285fb1c6ffSOliver Tappe
42943a6b92cSIngo Weinholdstatus_t
43043a6b92cSIngo WeinholdPackageReaderImpl::_PrepareSections()
43143a6b92cSIngo Weinhold{
43243a6b92cSIngo Weinhold	status_t error = PrepareSection(fTOCSection);
43343a6b92cSIngo Weinhold	if (error != B_OK)
43443a6b92cSIngo Weinhold		return error;
43543a6b92cSIngo Weinhold
43643a6b92cSIngo Weinhold	error = PrepareSection(fPackageAttributesSection);
43743a6b92cSIngo Weinhold	if (error != B_OK)
43843a6b92cSIngo Weinhold		return error;
43943a6b92cSIngo Weinhold
44043a6b92cSIngo Weinhold	return B_OK;
44143a6b92cSIngo Weinhold}
44243a6b92cSIngo Weinhold
44343a6b92cSIngo Weinhold
4445fb1c6ffSOliver Tappestatus_t
445ad6a8dbeSOliver TappePackageReaderImpl::_ParseTOC(AttributeHandlerContext* context,
4465fb1c6ffSOliver Tappe	AttributeHandler* rootAttributeHandler)
4475fb1c6ffSOliver Tappe{
4485fb1c6ffSOliver Tappe	// parse the TOC
44933bc4425SOliver Tappe	fTOCSection.currentOffset = fTOCSection.stringsLength;
450ad6a8dbeSOliver Tappe	SetCurrentSection(&fTOCSection);
4515fb1c6ffSOliver Tappe
4525fb1c6ffSOliver Tappe	// init the attribute handler stack
4535fb1c6ffSOliver Tappe	rootAttributeHandler->SetLevel(0);
454ad6a8dbeSOliver Tappe	ClearAttributeHandlerStack();
455ad6a8dbeSOliver Tappe	PushAttributeHandler(rootAttributeHandler);
4565fb1c6ffSOliver Tappe
45797aabbedSIngo Weinhold	bool sectionHandled;
45897aabbedSIngo Weinhold	status_t error = ParseAttributeTree(context, sectionHandled);
45997aabbedSIngo Weinhold	if (error == B_OK && sectionHandled) {
460884a0b23SOliver Tappe		if (fTOCSection.currentOffset < fTOCSection.uncompressedLength) {
461ad6a8dbeSOliver Tappe			ErrorOutput()->PrintError("Error: %llu excess byte(s) in TOC "
462884a0b23SOliver Tappe				"section\n",
463884a0b23SOliver Tappe				fTOCSection.uncompressedLength - fTOCSection.currentOffset);
4645fb1c6ffSOliver Tappe			error = B_BAD_DATA;
4655fb1c6ffSOliver Tappe		}
4665fb1c6ffSOliver Tappe	}
4675fb1c6ffSOliver Tappe
4685fb1c6ffSOliver Tappe	// clean up on error
4695fb1c6ffSOliver Tappe	if (error != B_OK) {
4705fb1c6ffSOliver Tappe		context->ErrorOccurred();
471ad6a8dbeSOliver Tappe		while (AttributeHandler* handler = PopAttributeHandler()) {
4725fb1c6ffSOliver Tappe			if (handler != rootAttributeHandler)
4735fb1c6ffSOliver Tappe				handler->Delete(context);
4745fb1c6ffSOliver Tappe		}
4755fb1c6ffSOliver Tappe		return error;
4765fb1c6ffSOliver Tappe	}
4775fb1c6ffSOliver Tappe
4785fb1c6ffSOliver Tappe	return B_OK;
4795fb1c6ffSOliver Tappe}
4805fb1c6ffSOliver Tappe
4815fb1c6ffSOliver Tappe
4825fb1c6ffSOliver Tappestatus_t
483ad6a8dbeSOliver TappePackageReaderImpl::ReadAttributeValue(uint8 type, uint8 encoding,
4845fb1c6ffSOliver Tappe	AttributeValue& _value)
4855fb1c6ffSOliver Tappe{
4865fb1c6ffSOliver Tappe	switch (type) {
4875fb1c6ffSOliver Tappe		case B_HPKG_ATTRIBUTE_TYPE_RAW:
4885fb1c6ffSOliver Tappe		{
4895fb1c6ffSOliver Tappe			uint64 size;
490ad6a8dbeSOliver Tappe			status_t error = ReadUnsignedLEB128(size);
4915fb1c6ffSOliver Tappe			if (error != B_OK)
4925fb1c6ffSOliver Tappe				return error;
4935fb1c6ffSOliver Tappe
4945fb1c6ffSOliver Tappe			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP) {
4955fb1c6ffSOliver Tappe				uint64 offset;
496ad6a8dbeSOliver Tappe				error = ReadUnsignedLEB128(offset);
4975fb1c6ffSOliver Tappe				if (error != B_OK)
4985fb1c6ffSOliver Tappe					return error;
4995fb1c6ffSOliver Tappe
5005fb1c6ffSOliver Tappe				if (offset > fHeapSize || size > fHeapSize - offset) {
501ad6a8dbeSOliver Tappe					ErrorOutput()->PrintError("Error: Invalid %s section: "
502ad6a8dbeSOliver Tappe						"invalid data reference\n", CurrentSection()->name);
5035fb1c6ffSOliver Tappe					return B_BAD_DATA;
5045fb1c6ffSOliver Tappe				}
5055fb1c6ffSOliver Tappe
5061f633814SIngo Weinhold				_value.SetToData(size, offset);
5075fb1c6ffSOliver Tappe			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE) {
5085fb1c6ffSOliver Tappe				if (size > B_HPKG_MAX_INLINE_DATA_SIZE) {
509ad6a8dbeSOliver Tappe					ErrorOutput()->PrintError("Error: Invalid %s section: "
510ad6a8dbeSOliver Tappe						"inline data too long\n", CurrentSection()->name);
5115fb1c6ffSOliver Tappe					return B_BAD_DATA;
5125fb1c6ffSOliver Tappe				}
5135fb1c6ffSOliver Tappe
5145fb1c6ffSOliver Tappe				const void* buffer;
5155fb1c6ffSOliver Tappe				error = _GetTOCBuffer(size, buffer);
5165fb1c6ffSOliver Tappe				if (error != B_OK)
5175fb1c6ffSOliver Tappe					return error;
5185fb1c6ffSOliver Tappe				_value.SetToData(size, buffer);
5195fb1c6ffSOliver Tappe			} else {
520ad6a8dbeSOliver Tappe				ErrorOutput()->PrintError("Error: Invalid %s section: invalid "
521ad6a8dbeSOliver Tappe					"raw encoding (%u)\n", CurrentSection()->name, encoding);
5225fb1c6ffSOliver Tappe				return B_BAD_DATA;
5235fb1c6ffSOliver Tappe			}
5245fb1c6ffSOliver Tappe
5255fb1c6ffSOliver Tappe			return B_OK;
5265fb1c6ffSOliver Tappe		}
5275fb1c6ffSOliver Tappe
5285fb1c6ffSOliver Tappe		default:
529ad6a8dbeSOliver Tappe			return inherited::ReadAttributeValue(type, encoding, _value);
5305fb1c6ffSOliver Tappe	}
5315fb1c6ffSOliver Tappe}
5325fb1c6ffSOliver Tappe
5335fb1c6ffSOliver Tappe
5345fb1c6ffSOliver Tappestatus_t
5355fb1c6ffSOliver TappePackageReaderImpl::_GetTOCBuffer(size_t size, const void*& _buffer)
5365fb1c6ffSOliver Tappe{
537884a0b23SOliver Tappe	if (size > fTOCSection.uncompressedLength - fTOCSection.currentOffset) {
538ad6a8dbeSOliver Tappe		ErrorOutput()->PrintError("_GetTOCBuffer(%lu): read beyond TOC end\n",
5395fb1c6ffSOliver Tappe			size);
5405fb1c6ffSOliver Tappe		return B_BAD_DATA;
5415fb1c6ffSOliver Tappe	}
5425fb1c6ffSOliver Tappe
543884a0b23SOliver Tappe	_buffer = fTOCSection.data + fTOCSection.currentOffset;
544884a0b23SOliver Tappe	fTOCSection.currentOffset += size;
5455fb1c6ffSOliver Tappe	return B_OK;
5465fb1c6ffSOliver Tappe}
5475fb1c6ffSOliver Tappe
5485fb1c6ffSOliver Tappe
5495fb1c6ffSOliver Tappe}	// namespace BPrivate
5505fb1c6ffSOliver Tappe
5515fb1c6ffSOliver Tappe}	// namespace BHPKG
5525fb1c6ffSOliver Tappe
5535fb1c6ffSOliver Tappe}	// namespace BPackageKit
554