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