xref: /haiku/src/kits/package/hpkg/v1/PackageReaderImplV1.cpp (revision 6a89a36aa0ce6a53f9758ba767863ac6b4c6156c)
17575abbcSIngo Weinhold /*
2*32832cbeSIngo Weinhold  * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
37575abbcSIngo Weinhold  * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
47575abbcSIngo Weinhold  * Distributed under the terms of the MIT License.
57575abbcSIngo Weinhold  */
67575abbcSIngo Weinhold 
77575abbcSIngo Weinhold 
87575abbcSIngo Weinhold #include <package/hpkg/v1/PackageReaderImpl.h>
97575abbcSIngo Weinhold 
107575abbcSIngo Weinhold #include <errno.h>
117575abbcSIngo Weinhold #include <fcntl.h>
127575abbcSIngo Weinhold #include <stdio.h>
137575abbcSIngo Weinhold #include <stdlib.h>
147575abbcSIngo Weinhold #include <string.h>
157575abbcSIngo Weinhold #include <sys/stat.h>
167575abbcSIngo Weinhold #include <unistd.h>
177575abbcSIngo Weinhold 
187575abbcSIngo Weinhold #include <algorithm>
197575abbcSIngo Weinhold #include <new>
207575abbcSIngo Weinhold 
217575abbcSIngo Weinhold #include <ByteOrder.h>
227575abbcSIngo Weinhold 
237575abbcSIngo Weinhold #include <package/hpkg/v1/HPKGDefsPrivate.h>
247575abbcSIngo Weinhold 
257575abbcSIngo Weinhold #include <package/hpkg/ErrorOutput.h>
267575abbcSIngo Weinhold #include <package/hpkg/v1/PackageData.h>
277575abbcSIngo Weinhold #include <package/hpkg/v1/PackageEntry.h>
287575abbcSIngo Weinhold #include <package/hpkg/v1/PackageEntryAttribute.h>
297575abbcSIngo Weinhold 
307575abbcSIngo Weinhold 
317575abbcSIngo Weinhold namespace BPackageKit {
327575abbcSIngo Weinhold 
337575abbcSIngo Weinhold namespace BHPKG {
347575abbcSIngo Weinhold 
357575abbcSIngo Weinhold namespace V1 {
367575abbcSIngo Weinhold 
377575abbcSIngo Weinhold namespace BPrivate {
387575abbcSIngo Weinhold 
397575abbcSIngo Weinhold 
407575abbcSIngo Weinhold //#define TRACE(format...)	printf(format)
417575abbcSIngo Weinhold #define TRACE(format...)	do {} while (false)
427575abbcSIngo Weinhold 
437575abbcSIngo Weinhold 
447575abbcSIngo Weinhold // maximum TOC size we support reading
457575abbcSIngo Weinhold static const size_t kMaxTOCSize					= 64 * 1024 * 1024;
467575abbcSIngo Weinhold 
477575abbcSIngo Weinhold // maximum package attributes size we support reading
487575abbcSIngo Weinhold static const size_t kMaxPackageAttributesSize	= 1 * 1024 * 1024;
497575abbcSIngo Weinhold 
507575abbcSIngo Weinhold 
517575abbcSIngo Weinhold // #pragma mark - DataAttributeHandler
527575abbcSIngo Weinhold 
537575abbcSIngo Weinhold 
547575abbcSIngo Weinhold struct PackageReaderImpl::DataAttributeHandler : AttributeHandler {
DataAttributeHandlerBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::DataAttributeHandler557575abbcSIngo Weinhold 	DataAttributeHandler(BPackageData* data)
567575abbcSIngo Weinhold 		:
577575abbcSIngo Weinhold 		fData(data)
587575abbcSIngo Weinhold 	{
597575abbcSIngo Weinhold 	}
607575abbcSIngo Weinhold 
InitDataBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::DataAttributeHandler617575abbcSIngo Weinhold 	static status_t InitData(AttributeHandlerContext* context,
627575abbcSIngo Weinhold 		BPackageData* data, const AttributeValue& value)
637575abbcSIngo Weinhold 	{
647575abbcSIngo Weinhold 		if (value.encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE)
657575abbcSIngo Weinhold 			data->SetData(value.data.size, value.data.raw);
667575abbcSIngo Weinhold 		else
677575abbcSIngo Weinhold 			data->SetData(value.data.size, value.data.offset);
687575abbcSIngo Weinhold 
697575abbcSIngo Weinhold 		data->SetUncompressedSize(value.data.size);
707575abbcSIngo Weinhold 
717575abbcSIngo Weinhold 		return B_OK;
727575abbcSIngo Weinhold 	}
737575abbcSIngo Weinhold 
CreateBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::DataAttributeHandler747575abbcSIngo Weinhold 	static status_t Create(AttributeHandlerContext* context,
757575abbcSIngo Weinhold 		BPackageData* data, const AttributeValue& value,
767575abbcSIngo Weinhold 		AttributeHandler*& _handler)
777575abbcSIngo Weinhold 	{
787575abbcSIngo Weinhold 		DataAttributeHandler* handler = new(std::nothrow) DataAttributeHandler(
797575abbcSIngo Weinhold 			data);
807575abbcSIngo Weinhold 		if (handler == NULL)
817575abbcSIngo Weinhold 			return B_NO_MEMORY;
827575abbcSIngo Weinhold 
837575abbcSIngo Weinhold 		InitData(context, data, value);
847575abbcSIngo Weinhold 
857575abbcSIngo Weinhold 		_handler = handler;
867575abbcSIngo Weinhold 		return B_OK;
877575abbcSIngo Weinhold 	}
887575abbcSIngo Weinhold 
HandleAttributeBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::DataAttributeHandler897575abbcSIngo Weinhold 	virtual status_t HandleAttribute(AttributeHandlerContext* context,
907575abbcSIngo Weinhold 		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
917575abbcSIngo Weinhold 	{
927575abbcSIngo Weinhold 		switch (id) {
937575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DATA_SIZE:
947575abbcSIngo Weinhold 				fData->SetUncompressedSize(value.unsignedInt);
957575abbcSIngo Weinhold 				return B_OK;
967575abbcSIngo Weinhold 
977575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DATA_COMPRESSION:
987575abbcSIngo Weinhold 			{
997575abbcSIngo Weinhold 				switch (value.unsignedInt) {
1007575abbcSIngo Weinhold 					case B_HPKG_COMPRESSION_NONE:
1017575abbcSIngo Weinhold 					case B_HPKG_COMPRESSION_ZLIB:
1027575abbcSIngo Weinhold 						break;
1037575abbcSIngo Weinhold 					default:
1047575abbcSIngo Weinhold 						context->errorOutput->PrintError("Error: Invalid "
1057575abbcSIngo Weinhold 							"compression type for data (%llu)\n",
1067575abbcSIngo Weinhold 							value.unsignedInt);
1077575abbcSIngo Weinhold 						return B_BAD_DATA;
1087575abbcSIngo Weinhold 				}
1097575abbcSIngo Weinhold 
1107575abbcSIngo Weinhold 				fData->SetCompression(value.unsignedInt);
1117575abbcSIngo Weinhold 				return B_OK;
1127575abbcSIngo Weinhold 			}
1137575abbcSIngo Weinhold 
1147575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DATA_CHUNK_SIZE:
1157575abbcSIngo Weinhold 				fData->SetChunkSize(value.unsignedInt);
1167575abbcSIngo Weinhold 				return B_OK;
1177575abbcSIngo Weinhold 		}
1187575abbcSIngo Weinhold 
1197575abbcSIngo Weinhold 		return AttributeHandler::HandleAttribute(context, id, value, _handler);
1207575abbcSIngo Weinhold 	}
1217575abbcSIngo Weinhold 
1227575abbcSIngo Weinhold private:
1237575abbcSIngo Weinhold 	BPackageData*	fData;
1247575abbcSIngo Weinhold };
1257575abbcSIngo Weinhold 
1267575abbcSIngo Weinhold 
1277575abbcSIngo Weinhold // #pragma mark - AttributeAttributeHandler
1287575abbcSIngo Weinhold 
1297575abbcSIngo Weinhold 
1307575abbcSIngo Weinhold struct PackageReaderImpl::AttributeAttributeHandler : AttributeHandler {
AttributeAttributeHandlerBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::AttributeAttributeHandler1317575abbcSIngo Weinhold 	AttributeAttributeHandler(BPackageEntry* entry, const char* name)
1327575abbcSIngo Weinhold 		:
1337575abbcSIngo Weinhold 		fEntry(entry),
1347575abbcSIngo Weinhold 		fAttribute(name)
1357575abbcSIngo Weinhold 	{
1367575abbcSIngo Weinhold 	}
1377575abbcSIngo Weinhold 
HandleAttributeBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::AttributeAttributeHandler1387575abbcSIngo Weinhold 	virtual status_t HandleAttribute(AttributeHandlerContext* context,
1397575abbcSIngo Weinhold 		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
1407575abbcSIngo Weinhold 	{
1417575abbcSIngo Weinhold 		switch (id) {
1427575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DATA:
1437575abbcSIngo Weinhold 				if (_handler != NULL) {
1447575abbcSIngo Weinhold 					return DataAttributeHandler::Create(context,
1457575abbcSIngo Weinhold 						&fAttribute.Data(), value, *_handler);
1467575abbcSIngo Weinhold 				}
1477575abbcSIngo Weinhold 				return DataAttributeHandler::InitData(context,
1487575abbcSIngo Weinhold 					&fAttribute.Data(), value);
1497575abbcSIngo Weinhold 
1507575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE_TYPE:
1517575abbcSIngo Weinhold 				fAttribute.SetType(value.unsignedInt);
1527575abbcSIngo Weinhold 				return B_OK;
1537575abbcSIngo Weinhold 		}
1547575abbcSIngo Weinhold 
1557575abbcSIngo Weinhold 		return AttributeHandler::HandleAttribute(context, id, value, _handler);
1567575abbcSIngo Weinhold 	}
1577575abbcSIngo Weinhold 
DeleteBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::AttributeAttributeHandler1587575abbcSIngo Weinhold 	virtual status_t Delete(AttributeHandlerContext* context)
1597575abbcSIngo Weinhold 	{
1607575abbcSIngo Weinhold 		status_t error = context->packageContentHandler->HandleEntryAttribute(
1617575abbcSIngo Weinhold 			fEntry, &fAttribute);
1627575abbcSIngo Weinhold 
1637575abbcSIngo Weinhold 		delete this;
1647575abbcSIngo Weinhold 		return error;
1657575abbcSIngo Weinhold 	}
1667575abbcSIngo Weinhold 
1677575abbcSIngo Weinhold private:
1687575abbcSIngo Weinhold 	BPackageEntry*			fEntry;
1697575abbcSIngo Weinhold 	BPackageEntryAttribute	fAttribute;
1707575abbcSIngo Weinhold };
1717575abbcSIngo Weinhold 
1727575abbcSIngo Weinhold 
1737575abbcSIngo Weinhold // #pragma mark - EntryAttributeHandler
1747575abbcSIngo Weinhold 
1757575abbcSIngo Weinhold 
1767575abbcSIngo Weinhold struct PackageReaderImpl::EntryAttributeHandler : AttributeHandler {
EntryAttributeHandlerBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler1777575abbcSIngo Weinhold 	EntryAttributeHandler(AttributeHandlerContext* context,
1787575abbcSIngo Weinhold 		BPackageEntry* parentEntry, const char* name)
1797575abbcSIngo Weinhold 		:
1807575abbcSIngo Weinhold 		fEntry(parentEntry, name),
1817575abbcSIngo Weinhold 		fNotified(false)
1827575abbcSIngo Weinhold 	{
1837575abbcSIngo Weinhold 		_SetFileType(context, B_HPKG_DEFAULT_FILE_TYPE);
1847575abbcSIngo Weinhold 	}
1857575abbcSIngo Weinhold 
CreateBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler1867575abbcSIngo Weinhold 	static status_t Create(AttributeHandlerContext* context,
1877575abbcSIngo Weinhold 		BPackageEntry* parentEntry, const char* name,
1887575abbcSIngo Weinhold 		AttributeHandler*& _handler)
1897575abbcSIngo Weinhold 	{
1907575abbcSIngo Weinhold 		// check name
1917575abbcSIngo Weinhold 		if (name[0] == '\0' || strcmp(name, ".") == 0
1927575abbcSIngo Weinhold 			|| strcmp(name, "..") == 0 || strchr(name, '/') != NULL) {
1937575abbcSIngo Weinhold 			context->errorOutput->PrintError("Error: Invalid package: Invalid "
1947575abbcSIngo Weinhold 				"entry name: \"%s\"\n", name);
1957575abbcSIngo Weinhold 			return B_BAD_DATA;
1967575abbcSIngo Weinhold 		}
1977575abbcSIngo Weinhold 
1987575abbcSIngo Weinhold 		// create handler
1997575abbcSIngo Weinhold 		EntryAttributeHandler* handler = new(std::nothrow)
2007575abbcSIngo Weinhold 			EntryAttributeHandler(context, parentEntry, name);
2017575abbcSIngo Weinhold 		if (handler == NULL)
2027575abbcSIngo Weinhold 			return B_NO_MEMORY;
2037575abbcSIngo Weinhold 
2047575abbcSIngo Weinhold 		_handler = handler;
2057575abbcSIngo Weinhold 		return B_OK;
2067575abbcSIngo Weinhold 	}
2077575abbcSIngo Weinhold 
HandleAttributeBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler2087575abbcSIngo Weinhold 	virtual status_t HandleAttribute(AttributeHandlerContext* context,
2097575abbcSIngo Weinhold 		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
2107575abbcSIngo Weinhold 	{
2117575abbcSIngo Weinhold 		switch (id) {
2127575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY:
2137575abbcSIngo Weinhold 			{
2147575abbcSIngo Weinhold 				status_t error = _Notify(context);
2157575abbcSIngo Weinhold 				if (error != B_OK)
2167575abbcSIngo Weinhold 					return error;
2177575abbcSIngo Weinhold 
2187575abbcSIngo Weinhold //TRACE("%*sentry \"%s\"\n", fLevel * 2, "", value.string);
2197575abbcSIngo Weinhold 				if (_handler != NULL) {
2207575abbcSIngo Weinhold 					return EntryAttributeHandler::Create(context, &fEntry,
2217575abbcSIngo Weinhold 						value.string, *_handler);
2227575abbcSIngo Weinhold 				}
2237575abbcSIngo Weinhold 				return B_OK;
2247575abbcSIngo Weinhold 			}
2257575abbcSIngo Weinhold 
2267575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_TYPE:
2277575abbcSIngo Weinhold 				return _SetFileType(context, value.unsignedInt);
2287575abbcSIngo Weinhold 
2297575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_PERMISSIONS:
2307575abbcSIngo Weinhold 				fEntry.SetPermissions(value.unsignedInt);
2317575abbcSIngo Weinhold 				return B_OK;
2327575abbcSIngo Weinhold 
2337575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_USER:
2347575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_GROUP:
2357575abbcSIngo Weinhold 				// TODO:...
2367575abbcSIngo Weinhold 				break;
2377575abbcSIngo Weinhold 
2387575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_ATIME:
2397575abbcSIngo Weinhold 				fEntry.SetAccessTime(value.unsignedInt);
2407575abbcSIngo Weinhold 				return B_OK;
2417575abbcSIngo Weinhold 
2427575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_MTIME:
2437575abbcSIngo Weinhold 				fEntry.SetModifiedTime(value.unsignedInt);
2447575abbcSIngo Weinhold 				return B_OK;
2457575abbcSIngo Weinhold 
2467575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_CRTIME:
2477575abbcSIngo Weinhold 				fEntry.SetCreationTime(value.unsignedInt);
2487575abbcSIngo Weinhold 				return B_OK;
2497575abbcSIngo Weinhold 
2507575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_ATIME_NANOS:
2517575abbcSIngo Weinhold 				fEntry.SetAccessTimeNanos(value.unsignedInt);
2527575abbcSIngo Weinhold 				return B_OK;
2537575abbcSIngo Weinhold 
2547575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_MTIME_NANOS:
2557575abbcSIngo Weinhold 				fEntry.SetModifiedTimeNanos(value.unsignedInt);
2567575abbcSIngo Weinhold 				return B_OK;
2577575abbcSIngo Weinhold 
2587575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_CRTIM_NANOS:
2597575abbcSIngo Weinhold 				fEntry.SetCreationTimeNanos(value.unsignedInt);
2607575abbcSIngo Weinhold 				return B_OK;
2617575abbcSIngo Weinhold 
2627575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_FILE_ATTRIBUTE:
2637575abbcSIngo Weinhold 			{
2647575abbcSIngo Weinhold 				status_t error = _Notify(context);
2657575abbcSIngo Weinhold 				if (error != B_OK)
2667575abbcSIngo Weinhold 					return error;
2677575abbcSIngo Weinhold 
2687575abbcSIngo Weinhold 				if (_handler != NULL) {
2697575abbcSIngo Weinhold 					*_handler = new(std::nothrow) AttributeAttributeHandler(
2707575abbcSIngo Weinhold 						&fEntry, value.string);
2717575abbcSIngo Weinhold 					if (*_handler == NULL)
2727575abbcSIngo Weinhold 						return B_NO_MEMORY;
2737575abbcSIngo Weinhold 					return B_OK;
2747575abbcSIngo Weinhold 				} else {
2757575abbcSIngo Weinhold 					BPackageEntryAttribute attribute(value.string);
2767575abbcSIngo Weinhold 					return context->packageContentHandler->HandleEntryAttribute(
2777575abbcSIngo Weinhold 						&fEntry, &attribute);
2787575abbcSIngo Weinhold 				}
2797575abbcSIngo Weinhold 			}
2807575abbcSIngo Weinhold 
2817575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_DATA:
2827575abbcSIngo Weinhold 				if (_handler != NULL) {
2837575abbcSIngo Weinhold 					return DataAttributeHandler::Create(context, &fEntry.Data(),
2847575abbcSIngo Weinhold 						value, *_handler);
2857575abbcSIngo Weinhold 				}
2867575abbcSIngo Weinhold 				return DataAttributeHandler::InitData(context, &fEntry.Data(),
2877575abbcSIngo Weinhold 					value);
2887575abbcSIngo Weinhold 
2897575abbcSIngo Weinhold 			case B_HPKG_ATTRIBUTE_ID_SYMLINK_PATH:
2907575abbcSIngo Weinhold 				fEntry.SetSymlinkPath(value.string);
2917575abbcSIngo Weinhold 				return B_OK;
2927575abbcSIngo Weinhold 		}
2937575abbcSIngo Weinhold 
2947575abbcSIngo Weinhold 		return AttributeHandler::HandleAttribute(context, id, value, _handler);
2957575abbcSIngo Weinhold 	}
2967575abbcSIngo Weinhold 
DeleteBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler2977575abbcSIngo Weinhold 	virtual status_t Delete(AttributeHandlerContext* context)
2987575abbcSIngo Weinhold 	{
2997575abbcSIngo Weinhold 		// notify if not done yet
3007575abbcSIngo Weinhold 		status_t error = _Notify(context);
3017575abbcSIngo Weinhold 
3027575abbcSIngo Weinhold 		// notify done
3037575abbcSIngo Weinhold 		if (error == B_OK)
3047575abbcSIngo Weinhold 			error = context->packageContentHandler->HandleEntryDone(&fEntry);
3057575abbcSIngo Weinhold 		else
3067575abbcSIngo Weinhold 			context->packageContentHandler->HandleEntryDone(&fEntry);
3077575abbcSIngo Weinhold 
3087575abbcSIngo Weinhold 		delete this;
3097575abbcSIngo Weinhold 		return error;
3107575abbcSIngo Weinhold 	}
3117575abbcSIngo Weinhold 
3127575abbcSIngo Weinhold private:
_NotifyBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler3137575abbcSIngo Weinhold 	status_t _Notify(AttributeHandlerContext* context)
3147575abbcSIngo Weinhold 	{
3157575abbcSIngo Weinhold 		if (fNotified)
3167575abbcSIngo Weinhold 			return B_OK;
3177575abbcSIngo Weinhold 
3187575abbcSIngo Weinhold 		fNotified = true;
3197575abbcSIngo Weinhold 		return context->packageContentHandler->HandleEntry(&fEntry);
3207575abbcSIngo Weinhold 	}
3217575abbcSIngo Weinhold 
_SetFileTypeBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::EntryAttributeHandler3227575abbcSIngo Weinhold 	status_t _SetFileType(AttributeHandlerContext* context, uint64 fileType)
3237575abbcSIngo Weinhold 	{
3247575abbcSIngo Weinhold 		switch (fileType) {
3257575abbcSIngo Weinhold 			case B_HPKG_FILE_TYPE_FILE:
3267575abbcSIngo Weinhold 				fEntry.SetType(S_IFREG);
3277575abbcSIngo Weinhold 				fEntry.SetPermissions(B_HPKG_DEFAULT_FILE_PERMISSIONS);
3287575abbcSIngo Weinhold 				break;
3297575abbcSIngo Weinhold 
3307575abbcSIngo Weinhold 			case B_HPKG_FILE_TYPE_DIRECTORY:
3317575abbcSIngo Weinhold 				fEntry.SetType(S_IFDIR);
3327575abbcSIngo Weinhold 				fEntry.SetPermissions(B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS);
3337575abbcSIngo Weinhold 				break;
3347575abbcSIngo Weinhold 
3357575abbcSIngo Weinhold 			case B_HPKG_FILE_TYPE_SYMLINK:
3367575abbcSIngo Weinhold 				fEntry.SetType(S_IFLNK);
3377575abbcSIngo Weinhold 				fEntry.SetPermissions(B_HPKG_DEFAULT_SYMLINK_PERMISSIONS);
3387575abbcSIngo Weinhold 				break;
3397575abbcSIngo Weinhold 
3407575abbcSIngo Weinhold 			default:
3417575abbcSIngo Weinhold 				context->errorOutput->PrintError("Error: Invalid file type for "
3427575abbcSIngo Weinhold 					"package entry (%llu)\n", fileType);
3437575abbcSIngo Weinhold 				return B_BAD_DATA;
3447575abbcSIngo Weinhold 		}
3457575abbcSIngo Weinhold 		return B_OK;
3467575abbcSIngo Weinhold 	}
3477575abbcSIngo Weinhold 
3487575abbcSIngo Weinhold private:
3497575abbcSIngo Weinhold 	BPackageEntry	fEntry;
3507575abbcSIngo Weinhold 	bool			fNotified;
3517575abbcSIngo Weinhold };
3527575abbcSIngo Weinhold 
3537575abbcSIngo Weinhold 
3547575abbcSIngo Weinhold // #pragma mark - RootAttributeHandler
3557575abbcSIngo Weinhold 
3567575abbcSIngo Weinhold 
3577575abbcSIngo Weinhold struct PackageReaderImpl::RootAttributeHandler : PackageAttributeHandler {
3587575abbcSIngo Weinhold 	typedef PackageAttributeHandler inherited;
3597575abbcSIngo Weinhold 
HandleAttributeBPackageKit::BHPKG::V1::BPrivate::PackageReaderImpl::RootAttributeHandler3607575abbcSIngo Weinhold 	virtual status_t HandleAttribute(AttributeHandlerContext* context,
3617575abbcSIngo Weinhold 		uint8 id, const AttributeValue& value, AttributeHandler** _handler)
3627575abbcSIngo Weinhold 	{
3637575abbcSIngo Weinhold 		if (id == B_HPKG_ATTRIBUTE_ID_DIRECTORY_ENTRY) {
3647575abbcSIngo Weinhold 			if (_handler != NULL) {
3657575abbcSIngo Weinhold 				return EntryAttributeHandler::Create(context, NULL,
3667575abbcSIngo Weinhold 					value.string, *_handler);
3677575abbcSIngo Weinhold 			}
3687575abbcSIngo Weinhold 			return B_OK;
3697575abbcSIngo Weinhold 		}
3707575abbcSIngo Weinhold 
3717575abbcSIngo Weinhold 		return inherited::HandleAttribute(context, id, value, _handler);
3727575abbcSIngo Weinhold 	}
3737575abbcSIngo Weinhold };
3747575abbcSIngo Weinhold 
3757575abbcSIngo Weinhold 
3767575abbcSIngo Weinhold // #pragma mark - PackageReaderImpl
3777575abbcSIngo Weinhold 
3787575abbcSIngo Weinhold 
PackageReaderImpl(BErrorOutput * errorOutput)3797575abbcSIngo Weinhold PackageReaderImpl::PackageReaderImpl(BErrorOutput* errorOutput)
3807575abbcSIngo Weinhold 	:
3817575abbcSIngo Weinhold 	inherited(errorOutput),
3827575abbcSIngo Weinhold 	fTOCSection("TOC")
3837575abbcSIngo Weinhold {
3847575abbcSIngo Weinhold }
3857575abbcSIngo Weinhold 
3867575abbcSIngo Weinhold 
~PackageReaderImpl()3877575abbcSIngo Weinhold PackageReaderImpl::~PackageReaderImpl()
3887575abbcSIngo Weinhold {
3897575abbcSIngo Weinhold }
3907575abbcSIngo Weinhold 
3917575abbcSIngo Weinhold 
3927575abbcSIngo Weinhold status_t
Init(const char * fileName)3937575abbcSIngo Weinhold PackageReaderImpl::Init(const char* fileName)
3947575abbcSIngo Weinhold {
3957575abbcSIngo Weinhold 	// open file
3967575abbcSIngo Weinhold 	int fd = open(fileName, O_RDONLY);
3977575abbcSIngo Weinhold 	if (fd < 0) {
3987575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Failed to open package file \"%s\": "
3997575abbcSIngo Weinhold 			"%s\n", fileName, strerror(errno));
4007575abbcSIngo Weinhold 		return errno;
4017575abbcSIngo Weinhold 	}
4027575abbcSIngo Weinhold 
4037575abbcSIngo Weinhold 	return Init(fd, true);
4047575abbcSIngo Weinhold }
4057575abbcSIngo Weinhold 
4067575abbcSIngo Weinhold 
4077575abbcSIngo Weinhold status_t
Init(int fd,bool keepFD)4087575abbcSIngo Weinhold PackageReaderImpl::Init(int fd, bool keepFD)
4097575abbcSIngo Weinhold {
4107575abbcSIngo Weinhold 	status_t error = inherited::Init(fd, keepFD);
4117575abbcSIngo Weinhold 	if (error != B_OK)
4127575abbcSIngo Weinhold 		return error;
4137575abbcSIngo Weinhold 
4147575abbcSIngo Weinhold 	// stat it
4157575abbcSIngo Weinhold 	struct stat st;
4167575abbcSIngo Weinhold 	if (fstat(FD(), &st) < 0) {
4177575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Failed to access package file: %s\n",
4187575abbcSIngo Weinhold 			strerror(errno));
4197575abbcSIngo Weinhold 		return errno;
4207575abbcSIngo Weinhold 	}
4217575abbcSIngo Weinhold 
4227575abbcSIngo Weinhold 	// read the header
4237575abbcSIngo Weinhold 	hpkg_header header;
4247575abbcSIngo Weinhold 	if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK)
4257575abbcSIngo Weinhold 		return error;
4267575abbcSIngo Weinhold 
4277575abbcSIngo Weinhold 	// check the header
4287575abbcSIngo Weinhold 
4297575abbcSIngo Weinhold 	// magic
4307575abbcSIngo Weinhold 	if (B_BENDIAN_TO_HOST_INT32(header.magic) != B_HPKG_MAGIC) {
4317575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: Invalid "
4327575abbcSIngo Weinhold 			"magic\n");
4337575abbcSIngo Weinhold 		return B_BAD_DATA;
4347575abbcSIngo Weinhold 	}
4357575abbcSIngo Weinhold 
4367575abbcSIngo Weinhold 	// version
4377575abbcSIngo Weinhold 	if (B_BENDIAN_TO_HOST_INT16(header.version) != B_HPKG_VERSION) {
4387575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid/unsupported package file "
4397575abbcSIngo Weinhold 			"version (%d)\n", B_BENDIAN_TO_HOST_INT16(header.version));
4407575abbcSIngo Weinhold 		return B_MISMATCHED_VALUES;
4417575abbcSIngo Weinhold 	}
4427575abbcSIngo Weinhold 
4437575abbcSIngo Weinhold 	// header size
4447575abbcSIngo Weinhold 	fHeapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
4457575abbcSIngo Weinhold 	if ((size_t)fHeapOffset < sizeof(hpkg_header)) {
4467575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: Invalid header "
4477575abbcSIngo Weinhold 			"size (%llu)\n", fHeapOffset);
4487575abbcSIngo Weinhold 		return B_BAD_DATA;
4497575abbcSIngo Weinhold 	}
4507575abbcSIngo Weinhold 
4517575abbcSIngo Weinhold 	// total size
4527575abbcSIngo Weinhold 	fTotalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
4537575abbcSIngo Weinhold 	if (fTotalSize != (uint64)st.st_size) {
4547575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: Total size in "
4557575abbcSIngo Weinhold 			"header (%llu) doesn't agree with total file size (%lld)\n",
4567575abbcSIngo Weinhold 			fTotalSize, st.st_size);
4577575abbcSIngo Weinhold 		return B_BAD_DATA;
4587575abbcSIngo Weinhold 	}
4597575abbcSIngo Weinhold 
4607575abbcSIngo Weinhold 	// package attributes length and compression
4617575abbcSIngo Weinhold 	fPackageAttributesSection.compression
4627575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT32(header.attributes_compression);
4637575abbcSIngo Weinhold 	fPackageAttributesSection.compressedLength
4647575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT32(header.attributes_length_compressed);
4657575abbcSIngo Weinhold 	fPackageAttributesSection.uncompressedLength
4667575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT32(header.attributes_length_uncompressed);
4677575abbcSIngo Weinhold 	fPackageAttributesSection.stringsLength
4687575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT32(header.attributes_strings_length);
4697575abbcSIngo Weinhold 	fPackageAttributesSection.stringsCount
4707575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT32(header.attributes_strings_count);
4717575abbcSIngo Weinhold 
4727575abbcSIngo Weinhold 	if (const char* errorString = CheckCompression(
4737575abbcSIngo Weinhold 		fPackageAttributesSection)) {
4747575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: package "
4757575abbcSIngo Weinhold 			"attributes section: %s\n", errorString);
4767575abbcSIngo Weinhold 		return B_BAD_DATA;
4777575abbcSIngo Weinhold 	}
4787575abbcSIngo Weinhold 
4797575abbcSIngo Weinhold 	// TOC length and compression
4807575abbcSIngo Weinhold 	fTOCSection.compression = B_BENDIAN_TO_HOST_INT32(header.toc_compression);
4817575abbcSIngo Weinhold 	fTOCSection.compressedLength
4827575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT64(header.toc_length_compressed);
4837575abbcSIngo Weinhold 	fTOCSection.uncompressedLength
4847575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT64(header.toc_length_uncompressed);
4857575abbcSIngo Weinhold 
4867575abbcSIngo Weinhold 	if (const char* errorString = CheckCompression(fTOCSection)) {
4877575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: TOC section: "
4887575abbcSIngo Weinhold 			"%s\n", errorString);
4897575abbcSIngo Weinhold 		return B_BAD_DATA;
4907575abbcSIngo Weinhold 	}
4917575abbcSIngo Weinhold 
4927575abbcSIngo Weinhold 	// TOC subsections
4937575abbcSIngo Weinhold 	fTOCSection.stringsLength
4947575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT64(header.toc_strings_length);
4957575abbcSIngo Weinhold 	fTOCSection.stringsCount
4967575abbcSIngo Weinhold 		= B_BENDIAN_TO_HOST_INT64(header.toc_strings_count);
4977575abbcSIngo Weinhold 
4987575abbcSIngo Weinhold 	if (fTOCSection.stringsLength > fTOCSection.uncompressedLength
4997575abbcSIngo Weinhold 		|| fTOCSection.stringsCount > fTOCSection.stringsLength) {
5007575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: Invalid TOC "
5017575abbcSIngo Weinhold 			"subsections description\n");
5027575abbcSIngo Weinhold 		return B_BAD_DATA;
5037575abbcSIngo Weinhold 	}
5047575abbcSIngo Weinhold 
5057575abbcSIngo Weinhold 	// check whether the sections fit together
5067575abbcSIngo Weinhold 	if (fPackageAttributesSection.compressedLength > fTotalSize
5077575abbcSIngo Weinhold 		|| fTOCSection.compressedLength
5087575abbcSIngo Weinhold 			> fTotalSize - fPackageAttributesSection.compressedLength
5097575abbcSIngo Weinhold 		|| fHeapOffset
5107575abbcSIngo Weinhold 			> fTotalSize - fPackageAttributesSection.compressedLength
5117575abbcSIngo Weinhold 				- fTOCSection.compressedLength) {
5127575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Invalid package file: The sum of the "
5137575abbcSIngo Weinhold 			"sections sizes is greater than the package size\n");
5147575abbcSIngo Weinhold 		return B_BAD_DATA;
5157575abbcSIngo Weinhold 	}
5167575abbcSIngo Weinhold 
5177575abbcSIngo Weinhold 	fPackageAttributesSection.offset
5187575abbcSIngo Weinhold 		= fTotalSize - fPackageAttributesSection.compressedLength;
5197575abbcSIngo Weinhold 	fTOCSection.offset = fPackageAttributesSection.offset
5207575abbcSIngo Weinhold 		- fTOCSection.compressedLength;
5217575abbcSIngo Weinhold 	fHeapSize = fTOCSection.offset - fHeapOffset;
5227575abbcSIngo Weinhold 
5237575abbcSIngo Weinhold 	// TOC size sanity check
5247575abbcSIngo Weinhold 	if (fTOCSection.uncompressedLength > kMaxTOCSize) {
5257575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Package file TOC section size "
5267575abbcSIngo Weinhold 			"is %llu bytes. This is beyond the reader's sanity limit\n",
5277575abbcSIngo Weinhold 			fTOCSection.uncompressedLength);
5287575abbcSIngo Weinhold 		return B_UNSUPPORTED;
5297575abbcSIngo Weinhold 	}
5307575abbcSIngo Weinhold 
5317575abbcSIngo Weinhold 	// package attributes size sanity check
5327575abbcSIngo Weinhold 	if (fPackageAttributesSection.uncompressedLength
5337575abbcSIngo Weinhold 			> kMaxPackageAttributesSize) {
5347575abbcSIngo Weinhold 		ErrorOutput()->PrintError(
5357575abbcSIngo Weinhold 			"Error: Package file package attributes section size "
5367575abbcSIngo Weinhold 			"is %llu bytes. This is beyond the reader's sanity limit\n",
5377575abbcSIngo Weinhold 			fPackageAttributesSection.uncompressedLength);
5387575abbcSIngo Weinhold 		return B_UNSUPPORTED;
5397575abbcSIngo Weinhold 	}
5407575abbcSIngo Weinhold 
5417575abbcSIngo Weinhold 	// read in the complete TOC
5427575abbcSIngo Weinhold 	fTOCSection.data
5437575abbcSIngo Weinhold 		= new(std::nothrow) uint8[fTOCSection.uncompressedLength];
5447575abbcSIngo Weinhold 	if (fTOCSection.data == NULL) {
5457575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Out of memory!\n");
5467575abbcSIngo Weinhold 		return B_NO_MEMORY;
5477575abbcSIngo Weinhold 	}
5487575abbcSIngo Weinhold 	error = ReadCompressedBuffer(fTOCSection);
5497575abbcSIngo Weinhold 	if (error != B_OK)
5507575abbcSIngo Weinhold 		return error;
5517575abbcSIngo Weinhold 
5527575abbcSIngo Weinhold 	// read in the complete package attributes section
5537575abbcSIngo Weinhold 	fPackageAttributesSection.data
5547575abbcSIngo Weinhold 		= new(std::nothrow) uint8[fPackageAttributesSection.uncompressedLength];
5557575abbcSIngo Weinhold 	if (fPackageAttributesSection.data == NULL) {
5567575abbcSIngo Weinhold 		ErrorOutput()->PrintError("Error: Out of memory!\n");
5577575abbcSIngo Weinhold 		return B_NO_MEMORY;
5587575abbcSIngo Weinhold 	}
5597575abbcSIngo Weinhold 	error = ReadCompressedBuffer(fPackageAttributesSection);
5607575abbcSIngo Weinhold 	if (error != B_OK)
5617575abbcSIngo Weinhold 		return error;
5627575abbcSIngo Weinhold 
5637575abbcSIngo Weinhold 	// start parsing the TOC
5647575abbcSIngo Weinhold 	fTOCSection.currentOffset = 0;
5657575abbcSIngo Weinhold 	SetCurrentSection(&fTOCSection);
5667575abbcSIngo Weinhold 
5677575abbcSIngo Weinhold 	// strings
5687575abbcSIngo Weinhold 	error = ParseStrings();
5697575abbcSIngo Weinhold 	if (error != B_OK)
5707575abbcSIngo Weinhold 		return error;
5717575abbcSIngo Weinhold 
5727575abbcSIngo Weinhold 	// parse strings from package attributes section
5737575abbcSIngo Weinhold 	fPackageAttributesSection.currentOffset = 0;
5747575abbcSIngo Weinhold 	SetCurrentSection(&fPackageAttributesSection);
5757575abbcSIngo Weinhold 
5767575abbcSIngo Weinhold 	// strings
5777575abbcSIngo Weinhold 	error = ParseStrings();
5787575abbcSIngo Weinhold 	if (error != B_OK)
5797575abbcSIngo Weinhold 		return error;
5807575abbcSIngo Weinhold 
5817575abbcSIngo Weinhold 	SetCurrentSection(NULL);
5827575abbcSIngo Weinhold 
5837575abbcSIngo Weinhold 	return B_OK;
5847575abbcSIngo Weinhold }
5857575abbcSIngo Weinhold 
5867575abbcSIngo Weinhold 
5877575abbcSIngo Weinhold status_t
ParseContent(BPackageContentHandler * contentHandler)5887575abbcSIngo Weinhold PackageReaderImpl::ParseContent(BPackageContentHandler* contentHandler)
5897575abbcSIngo Weinhold {
5907575abbcSIngo Weinhold 	AttributeHandlerContext context(ErrorOutput(), contentHandler,
5917575abbcSIngo Weinhold 		B_HPKG_SECTION_PACKAGE_ATTRIBUTES);
5927575abbcSIngo Weinhold 	RootAttributeHandler rootAttributeHandler;
5937575abbcSIngo Weinhold 
5947575abbcSIngo Weinhold 	status_t error
5957575abbcSIngo Weinhold 		= ParsePackageAttributesSection(&context, &rootAttributeHandler);
5967575abbcSIngo Weinhold 
5977575abbcSIngo Weinhold 	if (error == B_OK) {
5987575abbcSIngo Weinhold 		context.section = B_HPKG_SECTION_PACKAGE_TOC;
5997575abbcSIngo Weinhold 		error = _ParseTOC(&context, &rootAttributeHandler);
6007575abbcSIngo Weinhold 	}
6017575abbcSIngo Weinhold 
6027575abbcSIngo Weinhold 	return error;
6037575abbcSIngo Weinhold }
6047575abbcSIngo Weinhold 
6057575abbcSIngo Weinhold 
6067575abbcSIngo Weinhold status_t
ParseContent(BLowLevelPackageContentHandler * contentHandler)6077575abbcSIngo Weinhold PackageReaderImpl::ParseContent(BLowLevelPackageContentHandler* contentHandler)
6087575abbcSIngo Weinhold {
6097575abbcSIngo Weinhold 	AttributeHandlerContext context(ErrorOutput(), contentHandler,
6107575abbcSIngo Weinhold 		B_HPKG_SECTION_PACKAGE_ATTRIBUTES);
6117575abbcSIngo Weinhold 	LowLevelAttributeHandler rootAttributeHandler;
6127575abbcSIngo Weinhold 
6137575abbcSIngo Weinhold 	status_t error
6147575abbcSIngo Weinhold 		= ParsePackageAttributesSection(&context, &rootAttributeHandler);
6157575abbcSIngo Weinhold 
6167575abbcSIngo Weinhold 	if (error == B_OK) {
6177575abbcSIngo Weinhold 		context.section = B_HPKG_SECTION_PACKAGE_TOC;
6187575abbcSIngo Weinhold 		error = _ParseTOC(&context, &rootAttributeHandler);
6197575abbcSIngo Weinhold 	}
6207575abbcSIngo Weinhold 
6217575abbcSIngo Weinhold 	return error;
6227575abbcSIngo Weinhold }
6237575abbcSIngo Weinhold 
6247575abbcSIngo Weinhold 
6257575abbcSIngo Weinhold status_t
_ParseTOC(AttributeHandlerContext * context,AttributeHandler * rootAttributeHandler)6267575abbcSIngo Weinhold PackageReaderImpl::_ParseTOC(AttributeHandlerContext* context,
6277575abbcSIngo Weinhold 	AttributeHandler* rootAttributeHandler)
6287575abbcSIngo Weinhold {
6297575abbcSIngo Weinhold 	// parse the TOC
6307575abbcSIngo Weinhold 	fTOCSection.currentOffset = fTOCSection.stringsLength;
6317575abbcSIngo Weinhold 	SetCurrentSection(&fTOCSection);
6327575abbcSIngo Weinhold 
6337575abbcSIngo Weinhold 	// prepare attribute handler context
6347575abbcSIngo Weinhold 	context->heapOffset = fHeapOffset;
6357575abbcSIngo Weinhold 	context->heapSize = fHeapSize;
6367575abbcSIngo Weinhold 
6377575abbcSIngo Weinhold 	// init the attribute handler stack
6387575abbcSIngo Weinhold 	rootAttributeHandler->SetLevel(0);
6397575abbcSIngo Weinhold 	ClearAttributeHandlerStack();
6407575abbcSIngo Weinhold 	PushAttributeHandler(rootAttributeHandler);
6417575abbcSIngo Weinhold 
6427575abbcSIngo Weinhold 	bool sectionHandled;
6437575abbcSIngo Weinhold 	status_t error = ParseAttributeTree(context, sectionHandled);
6447575abbcSIngo Weinhold 	if (error == B_OK && sectionHandled) {
6457575abbcSIngo Weinhold 		if (fTOCSection.currentOffset < fTOCSection.uncompressedLength) {
6467575abbcSIngo Weinhold 			ErrorOutput()->PrintError("Error: %llu excess byte(s) in TOC "
6477575abbcSIngo Weinhold 				"section\n",
6487575abbcSIngo Weinhold 				fTOCSection.uncompressedLength - fTOCSection.currentOffset);
6497575abbcSIngo Weinhold 			error = B_BAD_DATA;
6507575abbcSIngo Weinhold 		}
6517575abbcSIngo Weinhold 	}
6527575abbcSIngo Weinhold 
6537575abbcSIngo Weinhold 	// clean up on error
6547575abbcSIngo Weinhold 	if (error != B_OK) {
6557575abbcSIngo Weinhold 		context->ErrorOccurred();
6567575abbcSIngo Weinhold 		while (AttributeHandler* handler = PopAttributeHandler()) {
6577575abbcSIngo Weinhold 			if (handler != rootAttributeHandler)
6587575abbcSIngo Weinhold 				handler->Delete(context);
6597575abbcSIngo Weinhold 		}
6607575abbcSIngo Weinhold 		return error;
6617575abbcSIngo Weinhold 	}
6627575abbcSIngo Weinhold 
6637575abbcSIngo Weinhold 	return B_OK;
6647575abbcSIngo Weinhold }
6657575abbcSIngo Weinhold 
6667575abbcSIngo Weinhold 
6677575abbcSIngo Weinhold status_t
ReadAttributeValue(uint8 type,uint8 encoding,AttributeValue & _value)6687575abbcSIngo Weinhold PackageReaderImpl::ReadAttributeValue(uint8 type, uint8 encoding,
6697575abbcSIngo Weinhold 	AttributeValue& _value)
6707575abbcSIngo Weinhold {
6717575abbcSIngo Weinhold 	switch (type) {
6727575abbcSIngo Weinhold 		case B_HPKG_ATTRIBUTE_TYPE_RAW:
6737575abbcSIngo Weinhold 		{
6747575abbcSIngo Weinhold 			uint64 size;
6757575abbcSIngo Weinhold 			status_t error = ReadUnsignedLEB128(size);
6767575abbcSIngo Weinhold 			if (error != B_OK)
6777575abbcSIngo Weinhold 				return error;
6787575abbcSIngo Weinhold 
6797575abbcSIngo Weinhold 			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP) {
6807575abbcSIngo Weinhold 				uint64 offset;
6817575abbcSIngo Weinhold 				error = ReadUnsignedLEB128(offset);
6827575abbcSIngo Weinhold 				if (error != B_OK)
6837575abbcSIngo Weinhold 					return error;
6847575abbcSIngo Weinhold 
6857575abbcSIngo Weinhold 				if (offset > fHeapSize || size > fHeapSize - offset) {
6867575abbcSIngo Weinhold 					ErrorOutput()->PrintError("Error: Invalid %s section: "
6877575abbcSIngo Weinhold 						"invalid data reference\n", CurrentSection()->name);
6887575abbcSIngo Weinhold 					return B_BAD_DATA;
6897575abbcSIngo Weinhold 				}
6907575abbcSIngo Weinhold 
6917575abbcSIngo Weinhold 				_value.SetToData(size, fHeapOffset + offset);
6927575abbcSIngo Weinhold 			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE) {
6937575abbcSIngo Weinhold 				if (size > B_HPKG_MAX_INLINE_DATA_SIZE) {
6947575abbcSIngo Weinhold 					ErrorOutput()->PrintError("Error: Invalid %s section: "
6957575abbcSIngo Weinhold 						"inline data too long\n", CurrentSection()->name);
6967575abbcSIngo Weinhold 					return B_BAD_DATA;
6977575abbcSIngo Weinhold 				}
6987575abbcSIngo Weinhold 
6997575abbcSIngo Weinhold 				const void* buffer;
7007575abbcSIngo Weinhold 				error = _GetTOCBuffer(size, buffer);
7017575abbcSIngo Weinhold 				if (error != B_OK)
7027575abbcSIngo Weinhold 					return error;
7037575abbcSIngo Weinhold 				_value.SetToData(size, buffer);
7047575abbcSIngo Weinhold 			} else {
7057575abbcSIngo Weinhold 				ErrorOutput()->PrintError("Error: Invalid %s section: invalid "
7067575abbcSIngo Weinhold 					"raw encoding (%u)\n", CurrentSection()->name, encoding);
7077575abbcSIngo Weinhold 				return B_BAD_DATA;
7087575abbcSIngo Weinhold 			}
7097575abbcSIngo Weinhold 
7107575abbcSIngo Weinhold 			return B_OK;
7117575abbcSIngo Weinhold 		}
7127575abbcSIngo Weinhold 
7137575abbcSIngo Weinhold 		default:
7147575abbcSIngo Weinhold 			return inherited::ReadAttributeValue(type, encoding, _value);
7157575abbcSIngo Weinhold 	}
7167575abbcSIngo Weinhold }
7177575abbcSIngo Weinhold 
7187575abbcSIngo Weinhold 
7197575abbcSIngo Weinhold status_t
_GetTOCBuffer(size_t size,const void * & _buffer)7207575abbcSIngo Weinhold PackageReaderImpl::_GetTOCBuffer(size_t size, const void*& _buffer)
7217575abbcSIngo Weinhold {
7227575abbcSIngo Weinhold 	if (size > fTOCSection.uncompressedLength - fTOCSection.currentOffset) {
7237575abbcSIngo Weinhold 		ErrorOutput()->PrintError("_GetTOCBuffer(%lu): read beyond TOC end\n",
7247575abbcSIngo Weinhold 			size);
7257575abbcSIngo Weinhold 		return B_BAD_DATA;
7267575abbcSIngo Weinhold 	}
7277575abbcSIngo Weinhold 
7287575abbcSIngo Weinhold 	_buffer = fTOCSection.data + fTOCSection.currentOffset;
7297575abbcSIngo Weinhold 	fTOCSection.currentOffset += size;
7307575abbcSIngo Weinhold 	return B_OK;
7317575abbcSIngo Weinhold }
7327575abbcSIngo Weinhold 
7337575abbcSIngo Weinhold 
7347575abbcSIngo Weinhold }	// namespace BPrivate
7357575abbcSIngo Weinhold 
7367575abbcSIngo Weinhold }	// namespace V1
7377575abbcSIngo Weinhold 
7387575abbcSIngo Weinhold }	// namespace BHPKG
7397575abbcSIngo Weinhold 
7407575abbcSIngo Weinhold }	// namespace BPackageKit
741