BPicture: Fix archive constructor.
[haiku.git] / src / kits / package / hpkg / ReaderImplBase.cpp
blobbb3bb1b05eb760f18022ad1790ada7d4c3116449
1 /*
2 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
4 * Distributed under the terms of the MIT License.
5 */
8 #include <package/hpkg/ReaderImplBase.h>
10 #include <errno.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
16 #include <algorithm>
17 #include <new>
19 #include <ByteOrder.h>
20 #include <DataIO.h>
22 #include <ZlibCompressionAlgorithm.h>
24 #include <package/hpkg/HPKGDefsPrivate.h>
25 #include <package/hpkg/PackageFileHeapReader.h>
28 namespace BPackageKit {
30 namespace BHPKG {
32 namespace BPrivate {
35 static const size_t kScratchBufferSize = 64 * 1024;
37 static const uint16 kAttributeTypes[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT] = {
38 #define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant) \
39 B_HPKG_ATTRIBUTE_TYPE_##type,
40 #include <package/hpkg/PackageAttributes.h>
41 #undef B_DEFINE_HPKG_ATTRIBUTE
44 // #pragma mark - AttributeHandlerContext
47 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
48 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
49 BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
51 errorOutput(errorOutput),
52 packageContentHandler(packageContentHandler),
53 hasLowLevelHandler(false),
54 ignoreUnknownAttributes(ignoreUnknownAttributes),
55 section(section)
60 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
61 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
62 BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
64 errorOutput(errorOutput),
65 lowLevelHandler(lowLevelHandler),
66 hasLowLevelHandler(true),
67 ignoreUnknownAttributes(ignoreUnknownAttributes),
68 section(section)
73 void
74 ReaderImplBase::AttributeHandlerContext::ErrorOccurred()
76 if (hasLowLevelHandler)
77 lowLevelHandler->HandleErrorOccurred();
78 else
79 packageContentHandler->HandleErrorOccurred();
83 // #pragma mark - AttributeHandler
86 ReaderImplBase::AttributeHandler::~AttributeHandler()
91 void
92 ReaderImplBase::AttributeHandler::SetLevel(int level)
94 fLevel = level;
98 status_t
99 ReaderImplBase::AttributeHandler::HandleAttribute(
100 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
101 AttributeHandler** _handler)
103 return B_OK;
107 status_t
108 ReaderImplBase::AttributeHandler::NotifyDone(
109 AttributeHandlerContext* context)
111 return B_OK;
115 status_t
116 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
118 delete this;
119 return B_OK;
123 // #pragma mark - PackageInfoAttributeHandlerBase
126 ReaderImplBase::PackageInfoAttributeHandlerBase
127 ::PackageInfoAttributeHandlerBase(
128 BPackageInfoAttributeValue& packageInfoValue)
130 fPackageInfoValue(packageInfoValue)
135 status_t
136 ReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone(
137 AttributeHandlerContext* context)
139 status_t error = context->packageContentHandler->HandlePackageAttribute(
140 fPackageInfoValue);
141 fPackageInfoValue.Clear();
142 return error;
146 // #pragma mark - PackageVersionAttributeHandler
149 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
150 BPackageInfoAttributeValue& packageInfoValue,
151 BPackageVersionData& versionData, bool notify)
153 super(packageInfoValue),
154 fPackageVersionData(versionData),
155 fNotify(notify)
160 status_t
161 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
162 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
163 AttributeHandler** _handler)
165 switch (id) {
166 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
167 fPackageVersionData.minor = value.string;
168 break;
170 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
171 fPackageVersionData.micro = value.string;
172 break;
174 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
175 fPackageVersionData.preRelease = value.string;
176 break;
178 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
179 fPackageVersionData.revision = value.unsignedInt;
180 break;
182 default:
183 if (context->ignoreUnknownAttributes)
184 break;
186 context->errorOutput->PrintError("Error: Invalid package "
187 "attribute section: unexpected package attribute id %d "
188 "encountered when parsing package version\n", id);
189 return B_BAD_DATA;
192 return B_OK;
196 status_t
197 ReaderImplBase::PackageVersionAttributeHandler::NotifyDone(
198 AttributeHandlerContext* context)
200 if (!fNotify)
201 return B_OK;
203 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
204 return super::NotifyDone(context);
208 // #pragma mark - PackageResolvableAttributeHandler
211 ReaderImplBase::PackageResolvableAttributeHandler
212 ::PackageResolvableAttributeHandler(
213 BPackageInfoAttributeValue& packageInfoValue)
215 super(packageInfoValue)
220 status_t
221 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
222 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
223 AttributeHandler** _handler)
225 switch (id) {
226 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
227 fPackageInfoValue.resolvable.haveVersion = true;
228 fPackageInfoValue.resolvable.version.major = value.string;
229 if (_handler != NULL) {
230 *_handler
231 = new(std::nothrow) PackageVersionAttributeHandler(
232 fPackageInfoValue,
233 fPackageInfoValue.resolvable.version, false);
234 if (*_handler == NULL)
235 return B_NO_MEMORY;
237 break;
239 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
240 fPackageInfoValue.resolvable.haveCompatibleVersion = true;
241 fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
242 if (_handler != NULL) {
243 *_handler
244 = new(std::nothrow) PackageVersionAttributeHandler(
245 fPackageInfoValue,
246 fPackageInfoValue.resolvable.compatibleVersion, false);
247 if (*_handler == NULL)
248 return B_NO_MEMORY;
250 break;
252 default:
253 if (context->ignoreUnknownAttributes)
254 break;
256 context->errorOutput->PrintError("Error: Invalid package "
257 "attribute section: unexpected package attribute id %d "
258 "encountered when parsing package resolvable\n", id);
259 return B_BAD_DATA;
262 return B_OK;
266 // #pragma mark - PackageResolvableExpressionAttributeHandler
269 ReaderImplBase::PackageResolvableExpressionAttributeHandler
270 ::PackageResolvableExpressionAttributeHandler(
271 BPackageInfoAttributeValue& packageInfoValue)
273 super(packageInfoValue)
278 status_t
279 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
280 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
281 AttributeHandler** _handler)
283 switch (id) {
284 case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
285 if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
286 context->errorOutput->PrintError(
287 "Error: Invalid package attribute section: invalid "
288 "package resolvable operator %lld encountered\n",
289 value.unsignedInt);
290 return B_BAD_DATA;
292 fPackageInfoValue.resolvableExpression.op
293 = (BPackageResolvableOperator)value.unsignedInt;
294 break;
296 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
297 fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
298 fPackageInfoValue.resolvableExpression.version.major
299 = value.string;
300 if (_handler != NULL) {
301 *_handler
302 = new(std::nothrow) PackageVersionAttributeHandler(
303 fPackageInfoValue,
304 fPackageInfoValue.resolvableExpression.version,
305 false);
306 if (*_handler == NULL)
307 return B_NO_MEMORY;
309 return B_OK;
311 default:
312 if (context->ignoreUnknownAttributes)
313 break;
315 context->errorOutput->PrintError("Error: Invalid package "
316 "attribute section: unexpected package attribute id %d "
317 "encountered when parsing package resolvable-expression\n",
318 id);
319 return B_BAD_DATA;
322 return B_OK;
326 // #pragma mark - GlobalWritableFileInfoAttributeHandler
329 ReaderImplBase::GlobalWritableFileInfoAttributeHandler
330 ::GlobalWritableFileInfoAttributeHandler(
331 BPackageInfoAttributeValue& packageInfoValue)
333 super(packageInfoValue)
338 status_t
339 ReaderImplBase::GlobalWritableFileInfoAttributeHandler::HandleAttribute(
340 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
341 AttributeHandler** _handler)
343 switch (id) {
344 case B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE:
345 if (value.unsignedInt >= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) {
346 context->errorOutput->PrintError(
347 "Error: Invalid package attribute section: invalid "
348 "global settings file update type %" B_PRIu64
349 " encountered\n", value.unsignedInt);
350 return B_BAD_DATA;
352 fPackageInfoValue.globalWritableFileInfo.updateType
353 = (BWritableFileUpdateType)value.unsignedInt;
354 break;
356 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
357 fPackageInfoValue.globalWritableFileInfo.isDirectory
358 = value.unsignedInt != 0;
359 break;
361 default:
362 if (context->ignoreUnknownAttributes)
363 break;
365 context->errorOutput->PrintError("Error: Invalid package "
366 "attribute section: unexpected package attribute id %d "
367 "encountered when parsing global settings file info\n",
368 id);
369 return B_BAD_DATA;
372 return B_OK;
376 // #pragma mark - UserSettingsFileInfoAttributeHandler
379 ReaderImplBase::UserSettingsFileInfoAttributeHandler
380 ::UserSettingsFileInfoAttributeHandler(
381 BPackageInfoAttributeValue& packageInfoValue)
383 super(packageInfoValue)
388 status_t
389 ReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute(
390 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
391 AttributeHandler** _handler)
393 switch (id) {
394 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE:
395 fPackageInfoValue.userSettingsFileInfo.templatePath = value.string;
396 break;
398 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
399 fPackageInfoValue.userSettingsFileInfo.isDirectory
400 = value.unsignedInt != 0;
401 break;
403 default:
404 if (context->ignoreUnknownAttributes)
405 break;
407 context->errorOutput->PrintError("Error: Invalid package "
408 "attribute section: unexpected package attribute id %d "
409 "encountered when parsing user settings file info\n",
410 id);
411 return B_BAD_DATA;
414 return B_OK;
418 // #pragma mark - UserAttributeHandler
421 ReaderImplBase::UserAttributeHandler::UserAttributeHandler(
422 BPackageInfoAttributeValue& packageInfoValue)
424 super(packageInfoValue),
425 fGroups()
430 status_t
431 ReaderImplBase::UserAttributeHandler::HandleAttribute(
432 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
433 AttributeHandler** _handler)
435 switch (id) {
436 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME:
437 fPackageInfoValue.user.realName = value.string;
438 break;
440 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME:
441 fPackageInfoValue.user.home = value.string;
442 break;
444 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL:
445 fPackageInfoValue.user.shell = value.string;
446 break;
448 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP:
449 if (!fGroups.Add(value.string))
450 return B_NO_MEMORY;
451 break;
453 default:
454 if (context->ignoreUnknownAttributes)
455 break;
457 context->errorOutput->PrintError("Error: Invalid package "
458 "attribute section: unexpected package attribute id %d "
459 "encountered when parsing user settings file info\n",
460 id);
461 return B_BAD_DATA;
464 return B_OK;
468 status_t
469 ReaderImplBase::UserAttributeHandler::NotifyDone(
470 AttributeHandlerContext* context)
472 if (!fGroups.IsEmpty()) {
473 fPackageInfoValue.user.groups = fGroups.Elements();
474 fPackageInfoValue.user.groupCount = fGroups.Count();
477 return super::NotifyDone(context);
481 // #pragma mark - PackageAttributeHandler
484 status_t
485 ReaderImplBase::PackageAttributeHandler::HandleAttribute(
486 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
487 AttributeHandler** _handler)
489 switch (id) {
490 case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
491 fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
492 break;
494 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
495 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
496 break;
498 case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
499 fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
500 value.string);
501 break;
503 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
504 fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
505 break;
507 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
508 fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
509 break;
511 case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE:
512 fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string);
513 break;
515 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
516 fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
517 (uint32)value.unsignedInt);
518 break;
520 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
521 if (value.unsignedInt
522 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
523 context->errorOutput->PrintError(
524 "Error: Invalid package attribute section: "
525 "Invalid package architecture %lld encountered\n",
526 value.unsignedInt);
527 return B_BAD_DATA;
529 fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
530 (uint8)value.unsignedInt);
531 break;
533 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
534 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
535 fPackageInfoValue.version.major = value.string;
536 if (_handler != NULL) {
537 *_handler
538 = new(std::nothrow) PackageVersionAttributeHandler(
539 fPackageInfoValue, fPackageInfoValue.version, true);
540 if (*_handler == NULL)
541 return B_NO_MEMORY;
543 break;
545 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
546 fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
547 value.string);
548 break;
550 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
551 fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
552 value.string);
553 break;
555 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
556 fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
557 break;
559 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
560 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
561 break;
563 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
564 fPackageInfoValue.resolvable.name = value.string;
565 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
566 if (_handler != NULL) {
567 *_handler
568 = new(std::nothrow) PackageResolvableAttributeHandler(
569 fPackageInfoValue);
570 if (*_handler == NULL)
571 return B_NO_MEMORY;
573 break;
575 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
576 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
577 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
578 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
579 fPackageInfoValue.resolvableExpression.name = value.string;
580 switch (id) {
581 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
582 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
583 break;
585 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
586 fPackageInfoValue.attributeID
587 = B_PACKAGE_INFO_SUPPLEMENTS;
588 break;
590 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
591 fPackageInfoValue.attributeID
592 = B_PACKAGE_INFO_CONFLICTS;
593 break;
595 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
596 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
597 break;
599 if (_handler != NULL) {
600 *_handler = new(std::nothrow)
601 PackageResolvableExpressionAttributeHandler(
602 fPackageInfoValue);
603 if (*_handler == NULL)
604 return B_NO_MEMORY;
606 break;
608 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
609 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
610 break;
612 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
613 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
614 break;
616 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
617 fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
618 break;
620 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE:
621 fPackageInfoValue.globalWritableFileInfo.path = value.string;
622 fPackageInfoValue.globalWritableFileInfo.updateType
623 = B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT;
624 fPackageInfoValue.attributeID
625 = B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES;
626 if (_handler != NULL) {
627 *_handler
628 = new(std::nothrow) GlobalWritableFileInfoAttributeHandler(
629 fPackageInfoValue);
630 if (*_handler == NULL)
631 return B_NO_MEMORY;
633 break;
635 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE:
636 fPackageInfoValue.userSettingsFileInfo.path = value.string;
637 fPackageInfoValue.attributeID
638 = B_PACKAGE_INFO_USER_SETTINGS_FILES;
639 if (_handler != NULL) {
640 *_handler
641 = new(std::nothrow) UserSettingsFileInfoAttributeHandler(
642 fPackageInfoValue);
643 if (*_handler == NULL)
644 return B_NO_MEMORY;
646 break;
648 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER:
649 fPackageInfoValue.user.name = value.string;
650 fPackageInfoValue.attributeID = B_PACKAGE_INFO_USERS;
651 if (_handler != NULL) {
652 *_handler = new(std::nothrow) UserAttributeHandler(
653 fPackageInfoValue);
654 if (*_handler == NULL)
655 return B_NO_MEMORY;
657 break;
659 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP:
660 fPackageInfoValue.SetTo(B_PACKAGE_INFO_GROUPS, value.string);
661 break;
663 case B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT:
664 fPackageInfoValue.SetTo(B_PACKAGE_INFO_POST_INSTALL_SCRIPTS,
665 value.string);
666 break;
668 default:
669 if (context->ignoreUnknownAttributes)
670 break;
672 context->errorOutput->PrintError(
673 "Error: Invalid package attribute section: unexpected "
674 "package attribute id %d encountered\n", id);
675 return B_BAD_DATA;
678 // notify unless the current attribute has children, in which case
679 // the child-handler will notify when it's done
680 if (_handler == NULL) {
681 status_t error = context->packageContentHandler
682 ->HandlePackageAttribute(fPackageInfoValue);
683 fPackageInfoValue.Clear();
684 if (error != B_OK)
685 return error;
688 return B_OK;
692 // #pragma mark - LowLevelAttributeHandler
695 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
697 fParentToken(NULL),
698 fToken(NULL),
699 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
704 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
705 const BPackageAttributeValue& value, void* parentToken, void* token)
707 fParentToken(NULL),
708 fToken(token),
709 fID(id),
710 fValue(value)
715 status_t
716 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
717 AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
718 AttributeHandler** _handler)
720 // notify the content handler
721 void* token;
722 status_t error = context->lowLevelHandler->HandleAttribute(
723 (BHPKGAttributeID)id, value, fToken, token);
724 if (error != B_OK)
725 return error;
727 // create a subhandler for the attribute, if it has children
728 if (_handler != NULL) {
729 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
730 fToken, token);
731 if (*_handler == NULL) {
732 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
733 value, fToken, token);
734 return B_NO_MEMORY;
736 return B_OK;
739 // no children -- just call the done hook
740 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
741 value, fToken, token);
745 status_t
746 ReaderImplBase::LowLevelAttributeHandler::NotifyDone(
747 AttributeHandlerContext* context)
749 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
750 status_t error = context->lowLevelHandler->HandleAttributeDone(
751 (BHPKGAttributeID)fID, fValue, fParentToken, fToken);
752 if (error != B_OK)
753 return error;
755 return super::NotifyDone(context);
759 // #pragma mark - ReaderImplBase
762 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput)
764 fPackageAttributesSection("package attributes"),
765 fFileType(fileType),
766 fErrorOutput(errorOutput),
767 fFile(NULL),
768 fOwnsFile(false),
769 fRawHeapReader(NULL),
770 fHeapReader(NULL),
771 fCurrentSection(NULL)
776 ReaderImplBase::~ReaderImplBase()
778 delete fHeapReader;
779 if (fRawHeapReader != fHeapReader)
780 delete fRawHeapReader;
782 if (fOwnsFile)
783 delete fFile;
787 uint64
788 ReaderImplBase::UncompressedHeapSize() const
790 return fRawHeapReader->UncompressedHeapSize();
794 BAbstractBufferedDataReader*
795 ReaderImplBase::DetachHeapReader(PackageFileHeapReader*& _rawHeapReader)
797 BAbstractBufferedDataReader* heapReader = fHeapReader;
798 _rawHeapReader = fRawHeapReader;
799 fHeapReader = NULL;
800 fRawHeapReader = NULL;
802 return heapReader;
806 status_t
807 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,
808 off_t offset, uint64 compressedSize, uint64 uncompressedSize)
810 DecompressionAlgorithmOwner* decompressionAlgorithm = NULL;
811 BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference;
813 switch (compression) {
814 case B_HPKG_COMPRESSION_NONE:
815 break;
816 case B_HPKG_COMPRESSION_ZLIB:
817 decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
818 new(std::nothrow) BZlibCompressionAlgorithm,
819 new(std::nothrow) BZlibDecompressionParameters);
820 decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
821 if (decompressionAlgorithm == NULL
822 || decompressionAlgorithm->algorithm == NULL
823 || decompressionAlgorithm->parameters == NULL) {
824 return B_NO_MEMORY;
826 break;
827 default:
828 fErrorOutput->PrintError("Error: Invalid heap compression\n");
829 return B_BAD_DATA;
832 fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput,
833 fFile, offset, compressedSize, uncompressedSize,
834 decompressionAlgorithm);
835 if (fRawHeapReader == NULL)
836 return B_NO_MEMORY;
838 status_t error = fRawHeapReader->Init();
839 if (error != B_OK)
840 return error;
842 error = CreateCachedHeapReader(fRawHeapReader, fHeapReader);
843 if (error != B_OK) {
844 if (error != B_NOT_SUPPORTED)
845 return error;
847 fHeapReader = fRawHeapReader;
850 return B_OK;
854 status_t
855 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader,
856 BAbstractBufferedDataReader*& _cachedReader)
858 return B_NOT_SUPPORTED;
862 status_t
863 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset,
864 uint64 length, uint64 maxSaneLength, uint64 stringsLength,
865 uint64 stringsCount)
867 // check length vs. endOffset
868 if (length > endOffset) {
869 ErrorOutput()->PrintError("Error: %s file %s section size is %"
870 B_PRIu64 " bytes. This is greater than the available space\n",
871 fFileType, section.name, length);
872 return B_BAD_DATA;
875 // check sanity length
876 if (maxSaneLength > 0 && length > maxSaneLength) {
877 ErrorOutput()->PrintError("Error: %s file %s section size is %"
878 B_PRIu64 " bytes. This is beyond the reader's sanity limit\n",
879 fFileType, section.name, length);
880 return B_NOT_SUPPORTED;
883 // check strings subsection size/count
884 if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) {
885 ErrorOutput()->PrintError("Error: strings subsection description of %s "
886 "file %s section is invalid (%" B_PRIu64 " strings, length: %"
887 B_PRIu64 ", section length: %" B_PRIu64 ")\n",
888 fFileType, section.name, stringsCount, stringsLength, length);
889 return B_BAD_DATA;
892 section.uncompressedLength = length;
893 section.offset = endOffset - length;
894 section.currentOffset = 0;
895 section.stringsLength = stringsLength;
896 section.stringsCount = stringsCount;
898 return B_OK;
902 status_t
903 ReaderImplBase::PrepareSection(PackageFileSection& section)
905 // allocate memory for the section data and read it in
906 section.data = new(std::nothrow) uint8[section.uncompressedLength];
907 if (section.data == NULL) {
908 ErrorOutput()->PrintError("Error: Out of memory!\n");
909 return B_NO_MEMORY;
912 status_t error = ReadSection(section);
913 if (error != B_OK)
914 return error;
916 // parse the section strings
917 section.currentOffset = 0;
918 SetCurrentSection(&section);
920 error = ParseStrings();
921 if (error != B_OK)
922 return error;
924 return B_OK;
928 status_t
929 ReaderImplBase::ParseStrings()
931 // allocate table, if there are any strings
932 if (fCurrentSection->stringsCount == 0) {
933 fCurrentSection->currentOffset += fCurrentSection->stringsLength;
934 return B_OK;
937 fCurrentSection->strings
938 = new(std::nothrow) char*[fCurrentSection->stringsCount];
939 if (fCurrentSection->strings == NULL) {
940 fErrorOutput->PrintError("Error: Out of memory!\n");
941 return B_NO_MEMORY;
944 // parse the section and fill the table
945 char* position
946 = (char*)fCurrentSection->data + fCurrentSection->currentOffset;
947 char* sectionEnd = position + fCurrentSection->stringsLength;
948 uint32 index = 0;
949 while (true) {
950 if (position >= sectionEnd) {
951 fErrorOutput->PrintError("Error: Malformed %s strings section\n",
952 fCurrentSection->name);
953 return B_BAD_DATA;
956 size_t stringLength = strnlen(position, (char*)sectionEnd - position);
958 if (stringLength == 0) {
959 if (position + 1 != sectionEnd) {
960 fErrorOutput->PrintError(
961 "Error: %ld excess bytes in %s strings section\n",
962 sectionEnd - (position + 1), fCurrentSection->name);
963 return B_BAD_DATA;
966 if (index != fCurrentSection->stringsCount) {
967 fErrorOutput->PrintError("Error: Invalid %s strings section: "
968 "Less strings (%lld) than specified in the header (%lld)\n",
969 fCurrentSection->name, index,
970 fCurrentSection->stringsCount);
971 return B_BAD_DATA;
974 fCurrentSection->currentOffset += fCurrentSection->stringsLength;
976 return B_OK;
979 if (index >= fCurrentSection->stringsCount) {
980 fErrorOutput->PrintError("Error: Invalid %s strings section: "
981 "More strings (%lld) than specified in the header (%lld)\n",
982 fCurrentSection->name, index, fCurrentSection->stringsCount);
983 return B_BAD_DATA;
986 fCurrentSection->strings[index++] = position;
987 position += stringLength + 1;
992 status_t
993 ReaderImplBase::ParsePackageAttributesSection(
994 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
996 // parse package attributes
997 SetCurrentSection(&fPackageAttributesSection);
999 // init the attribute handler stack
1000 rootAttributeHandler->SetLevel(0);
1001 ClearAttributeHandlerStack();
1002 PushAttributeHandler(rootAttributeHandler);
1004 bool sectionHandled;
1005 status_t error = ParseAttributeTree(context, sectionHandled);
1006 if (error == B_OK && sectionHandled) {
1007 if (fPackageAttributesSection.currentOffset
1008 < fPackageAttributesSection.uncompressedLength) {
1009 fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
1010 "attributes section\n",
1011 fPackageAttributesSection.uncompressedLength
1012 - fPackageAttributesSection.currentOffset);
1013 error = B_BAD_DATA;
1017 SetCurrentSection(NULL);
1019 // clean up on error
1020 if (error != B_OK) {
1021 context->ErrorOccurred();
1022 while (AttributeHandler* handler = PopAttributeHandler()) {
1023 if (handler != rootAttributeHandler)
1024 handler->Delete(context);
1026 return error;
1029 return B_OK;
1033 status_t
1034 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
1035 bool& _sectionHandled)
1037 if (context->hasLowLevelHandler) {
1038 bool handleSection = false;
1039 status_t error = context->lowLevelHandler->HandleSectionStart(
1040 context->section, handleSection);
1041 if (error != B_OK)
1042 return error;
1044 if (!handleSection) {
1045 _sectionHandled = false;
1046 return B_OK;
1050 status_t error = _ParseAttributeTree(context);
1052 if (context->hasLowLevelHandler) {
1053 status_t endError = context->lowLevelHandler->HandleSectionEnd(
1054 context->section);
1055 if (error == B_OK)
1056 error = endError;
1059 _sectionHandled = true;
1060 return error;
1064 status_t
1065 ReaderImplBase::_Init(BPositionIO* file, bool keepFile)
1067 fFile = file;
1068 fOwnsFile = keepFile;
1069 return fFile != NULL ? B_OK : B_BAD_VALUE;
1073 status_t
1074 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
1076 int level = 0;
1078 while (true) {
1079 uint8 id;
1080 AttributeValue value;
1081 bool hasChildren;
1082 uint64 tag;
1084 status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
1085 if (error != B_OK)
1086 return error;
1088 if (tag == 0) {
1089 AttributeHandler* handler = PopAttributeHandler();
1090 error = handler->NotifyDone(context);
1091 if (error != B_OK)
1092 return error;
1093 if (level-- == 0)
1094 return B_OK;
1096 error = handler->Delete(context);
1097 if (error != B_OK)
1098 return error;
1100 continue;
1103 AttributeHandler* childHandler = NULL;
1104 error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
1105 hasChildren ? &childHandler : NULL);
1106 if (error != B_OK)
1107 return error;
1109 // parse children
1110 if (hasChildren) {
1111 // create an ignore handler, if necessary
1112 if (childHandler == NULL) {
1113 childHandler = new(std::nothrow) IgnoreAttributeHandler;
1114 if (childHandler == NULL) {
1115 fErrorOutput->PrintError("Error: Out of memory!\n");
1116 return B_NO_MEMORY;
1120 childHandler->SetLevel(++level);
1121 PushAttributeHandler(childHandler);
1127 status_t
1128 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
1129 bool* _hasChildren, uint64* _tag)
1131 uint64 tag;
1132 status_t error = ReadUnsignedLEB128(tag);
1133 if (error != B_OK)
1134 return error;
1136 if (tag != 0) {
1137 // get the type
1138 uint16 type = attribute_tag_type(tag);
1139 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
1140 fErrorOutput->PrintError("Error: Invalid %s section: attribute "
1141 "type %d not supported!\n", fCurrentSection->name, type);
1142 return B_BAD_DATA;
1145 // get the ID
1146 _id = attribute_tag_id(tag);
1147 if (_id < B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
1148 if (type != kAttributeTypes[_id]) {
1149 fErrorOutput->PrintError("Error: Invalid %s section: "
1150 "unexpected type %d for attribute id %d (expected %d)!\n",
1151 fCurrentSection->name, type, _id, kAttributeTypes[_id]);
1152 return B_BAD_DATA;
1154 } else if (fMinorFormatVersion <= fCurrentMinorFormatVersion) {
1155 fErrorOutput->PrintError("Error: Invalid %s section: "
1156 "attribute id %d not supported!\n", fCurrentSection->name, _id);
1157 return B_BAD_DATA;
1160 // get the value
1161 error = ReadAttributeValue(type, attribute_tag_encoding(tag),
1162 _value);
1163 if (error != B_OK)
1164 return error;
1167 if (_hasChildren != NULL)
1168 *_hasChildren = attribute_tag_has_children(tag);
1169 if (_tag != NULL)
1170 *_tag = tag;
1172 return B_OK;
1176 status_t
1177 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
1178 AttributeValue& _value)
1180 switch (type) {
1181 case B_HPKG_ATTRIBUTE_TYPE_INT:
1182 case B_HPKG_ATTRIBUTE_TYPE_UINT:
1184 uint64 intValue;
1185 status_t error;
1187 switch (encoding) {
1188 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
1190 uint8 value;
1191 error = _Read(value);
1192 intValue = value;
1193 break;
1195 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
1197 uint16 value;
1198 error = _Read(value);
1199 intValue = B_BENDIAN_TO_HOST_INT16(value);
1200 break;
1202 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
1204 uint32 value;
1205 error = _Read(value);
1206 intValue = B_BENDIAN_TO_HOST_INT32(value);
1207 break;
1209 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
1211 uint64 value;
1212 error = _Read(value);
1213 intValue = B_BENDIAN_TO_HOST_INT64(value);
1214 break;
1216 default:
1218 fErrorOutput->PrintError("Error: Invalid %s section: "
1219 "invalid encoding %d for int value type %d\n",
1220 fCurrentSection->name, encoding, type);
1221 return B_BAD_VALUE;
1225 if (error != B_OK)
1226 return error;
1228 if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
1229 _value.SetTo((int64)intValue);
1230 else
1231 _value.SetTo(intValue);
1233 return B_OK;
1236 case B_HPKG_ATTRIBUTE_TYPE_STRING:
1238 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
1239 uint64 index;
1240 status_t error = ReadUnsignedLEB128(index);
1241 if (error != B_OK)
1242 return error;
1244 if (index > fCurrentSection->stringsCount) {
1245 fErrorOutput->PrintError("Error: Invalid %s section: "
1246 "string reference (%lld) out of bounds (%lld)\n",
1247 fCurrentSection->name, index,
1248 fCurrentSection->stringsCount);
1249 return B_BAD_DATA;
1252 _value.SetTo(fCurrentSection->strings[index]);
1253 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
1254 const char* string;
1255 status_t error = _ReadString(string);
1256 if (error != B_OK)
1257 return error;
1259 _value.SetTo(string);
1260 } else {
1261 fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1262 "string encoding (%u)\n", fCurrentSection->name, encoding);
1263 return B_BAD_DATA;
1266 return B_OK;
1269 default:
1270 fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1271 "value type: %d\n", fCurrentSection->name, type);
1272 return B_BAD_DATA;
1277 status_t
1278 ReaderImplBase::ReadUnsignedLEB128(uint64& _value)
1280 uint64 result = 0;
1281 int shift = 0;
1282 while (true) {
1283 uint8 byte;
1284 status_t error = _Read(byte);
1285 if (error != B_OK)
1286 return error;
1288 result |= uint64(byte & 0x7f) << shift;
1289 if ((byte & 0x80) == 0)
1290 break;
1291 shift += 7;
1294 _value = result;
1295 return B_OK;
1299 status_t
1300 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength)
1302 const char* string
1303 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset;
1304 size_t stringLength = strnlen(string,
1305 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset);
1307 if (stringLength
1308 == fCurrentSection->uncompressedLength
1309 - fCurrentSection->currentOffset) {
1310 fErrorOutput->PrintError(
1311 "_ReadString(): string extends beyond %s end\n",
1312 fCurrentSection->name);
1313 return B_BAD_DATA;
1316 _string = string;
1317 if (_stringLength != NULL)
1318 *_stringLength = stringLength;
1320 fCurrentSection->currentOffset += stringLength + 1;
1321 return B_OK;
1325 status_t
1326 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size)
1328 if (size > fCurrentSection->uncompressedLength
1329 - fCurrentSection->currentOffset) {
1330 fErrorOutput->PrintError(
1331 "_ReadSectionBuffer(%lu): read beyond %s end\n", size,
1332 fCurrentSection->name);
1333 return B_BAD_DATA;
1336 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset,
1337 size);
1338 fCurrentSection->currentOffset += size;
1339 return B_OK;
1343 status_t
1344 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size)
1346 status_t error = fFile->ReadAtExactly(offset, buffer, size);
1347 if (error != B_OK) {
1348 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1349 "%s\n", buffer, size, strerror(error));
1350 return error;
1353 return B_OK;
1357 status_t
1358 ReaderImplBase::ReadSection(const PackageFileSection& section)
1360 return fHeapReader->ReadData(section.offset,
1361 section.data, section.uncompressedLength);
1365 } // namespace BPrivate
1367 } // namespace BHPKG
1369 } // namespace BPackageKit