xref: /haiku/src/kits/package/hpkg/ReaderImplBase.cpp (revision 46122852f1dfbbf4bac6f5a634452ff90c5635ce)
1 /*
2  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <package/hpkg/ReaderImplBase.h>
9 
10 #include <errno.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <algorithm>
16 #include <new>
17 
18 #include <ByteOrder.h>
19 
20 #include <package/hpkg/HPKGDefsPrivate.h>
21 
22 #include <package/hpkg/DataOutput.h>
23 #include <package/hpkg/PackageFileHeapReader.h>
24 #include <package/hpkg/ZlibDecompressor.h>
25 
26 
27 namespace BPackageKit {
28 
29 namespace BHPKG {
30 
31 namespace BPrivate {
32 
33 
34 static const size_t kScratchBufferSize = 64 * 1024;
35 
36 
37 // #pragma mark - AttributeHandlerContext
38 
39 
40 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
41 	BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
42 	BHPKGPackageSectionID section)
43 	:
44 	errorOutput(errorOutput),
45 	packageContentHandler(packageContentHandler),
46 	hasLowLevelHandler(false),
47 	section(section)
48 {
49 }
50 
51 
52 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
53 	BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
54 	BHPKGPackageSectionID section)
55 	:
56 	errorOutput(errorOutput),
57 	lowLevelHandler(lowLevelHandler),
58 	hasLowLevelHandler(true),
59 	section(section)
60 {
61 }
62 
63 
64 void
65 ReaderImplBase::AttributeHandlerContext::ErrorOccurred()
66 {
67 	if (hasLowLevelHandler)
68 		lowLevelHandler->HandleErrorOccurred();
69 	else
70 		packageContentHandler->HandleErrorOccurred();
71 }
72 
73 
74 // #pragma mark - AttributeHandler
75 
76 
77 ReaderImplBase::AttributeHandler::~AttributeHandler()
78 {
79 }
80 
81 
82 void
83 ReaderImplBase::AttributeHandler::SetLevel(int level)
84 {
85 	fLevel = level;
86 }
87 
88 
89 status_t
90 ReaderImplBase::AttributeHandler::HandleAttribute(
91 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
92 	AttributeHandler** _handler)
93 {
94 	return B_OK;
95 }
96 
97 
98 status_t
99 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
100 {
101 	delete this;
102 	return B_OK;
103 }
104 
105 
106 // #pragma mark - PackageVersionAttributeHandler
107 
108 
109 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
110 	BPackageInfoAttributeValue& packageInfoValue,
111 	BPackageVersionData& versionData, bool notify)
112 	:
113 	fPackageInfoValue(packageInfoValue),
114 	fPackageVersionData(versionData),
115 	fNotify(notify)
116 {
117 }
118 
119 
120 status_t
121 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
122 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
123 	AttributeHandler** _handler)
124 {
125 	switch (id) {
126 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
127 			fPackageVersionData.minor = value.string;
128 			break;
129 
130 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
131 			fPackageVersionData.micro = value.string;
132 			break;
133 
134 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
135 			fPackageVersionData.preRelease = value.string;
136 			break;
137 
138 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
139 			fPackageVersionData.revision = value.unsignedInt;
140 			break;
141 
142 		default:
143 			context->errorOutput->PrintError("Error: Invalid package "
144 				"attribute section: unexpected package attribute id %d "
145 				"encountered when parsing package version\n", id);
146 			return B_BAD_DATA;
147 	}
148 
149 	return B_OK;
150 }
151 
152 
153 status_t
154 ReaderImplBase::PackageVersionAttributeHandler::Delete(
155 	AttributeHandlerContext* context)
156 {
157 	status_t error = B_OK;
158 	if (fNotify) {
159 		fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
160 		error = context->packageContentHandler->HandlePackageAttribute(
161 			fPackageInfoValue);
162 		fPackageInfoValue.Clear();
163 	}
164 
165 	delete this;
166 	return error;
167 }
168 
169 
170 // #pragma mark - PackageResolvableAttributeHandler
171 
172 
173 ReaderImplBase::PackageResolvableAttributeHandler
174 	::PackageResolvableAttributeHandler(
175 		BPackageInfoAttributeValue& packageInfoValue)
176 	:
177 	fPackageInfoValue(packageInfoValue)
178 {
179 }
180 
181 
182 status_t
183 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
184 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
185 	AttributeHandler** _handler)
186 {
187 	switch (id) {
188 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
189 			fPackageInfoValue.resolvable.haveVersion = true;
190 			fPackageInfoValue.resolvable.version.major = value.string;
191 			if (_handler != NULL) {
192 				*_handler
193 					= new(std::nothrow) PackageVersionAttributeHandler(
194 						fPackageInfoValue,
195 						fPackageInfoValue.resolvable.version, false);
196 				if (*_handler == NULL)
197 					return B_NO_MEMORY;
198 			}
199 			break;
200 
201 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
202 			fPackageInfoValue.resolvable.haveCompatibleVersion = true;
203 			fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
204 			if (_handler != NULL) {
205 				*_handler
206 					= new(std::nothrow) PackageVersionAttributeHandler(
207 						fPackageInfoValue,
208 						fPackageInfoValue.resolvable.compatibleVersion, false);
209 				if (*_handler == NULL)
210 					return B_NO_MEMORY;
211 			}
212 			break;
213 
214 		default:
215 			context->errorOutput->PrintError("Error: Invalid package "
216 				"attribute section: unexpected package attribute id %d "
217 				"encountered when parsing package resolvable\n", id);
218 			return B_BAD_DATA;
219 	}
220 
221 	return B_OK;
222 }
223 
224 
225 status_t
226 ReaderImplBase::PackageResolvableAttributeHandler::Delete(
227 	AttributeHandlerContext* context)
228 {
229 	status_t error = context->packageContentHandler->HandlePackageAttribute(
230 		fPackageInfoValue);
231 	fPackageInfoValue.Clear();
232 
233 	delete this;
234 	return error;
235 }
236 
237 
238 // #pragma mark - PackageResolvableExpressionAttributeHandler
239 
240 
241 ReaderImplBase::PackageResolvableExpressionAttributeHandler
242 	::PackageResolvableExpressionAttributeHandler(
243 		BPackageInfoAttributeValue& packageInfoValue)
244 	:
245 	fPackageInfoValue(packageInfoValue)
246 {
247 }
248 
249 
250 status_t
251 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
252 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
253 	AttributeHandler** _handler)
254 {
255 	switch (id) {
256 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
257 			if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
258 				context->errorOutput->PrintError(
259 					"Error: Invalid package attribute section: invalid "
260 					"package resolvable operator %lld encountered\n",
261 					value.unsignedInt);
262 				return B_BAD_DATA;
263 			}
264 			fPackageInfoValue.resolvableExpression.op
265 				= (BPackageResolvableOperator)value.unsignedInt;
266 			break;
267 
268 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
269 			fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
270 			fPackageInfoValue.resolvableExpression.version.major
271 				= value.string;
272 			if (_handler != NULL) {
273 				*_handler
274 					= new(std::nothrow) PackageVersionAttributeHandler(
275 						fPackageInfoValue,
276 						fPackageInfoValue.resolvableExpression.version,
277 						false);
278 				if (*_handler == NULL)
279 					return B_NO_MEMORY;
280 			}
281 			return B_OK;
282 
283 		default:
284 			context->errorOutput->PrintError("Error: Invalid package "
285 				"attribute section: unexpected package attribute id %d "
286 				"encountered when parsing package resolvable-expression\n",
287 				id);
288 			return B_BAD_DATA;
289 	}
290 
291 	return B_OK;
292 }
293 
294 
295 status_t
296 ReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete(
297 	AttributeHandlerContext* context)
298 {
299 	status_t error = context->packageContentHandler->HandlePackageAttribute(
300 		fPackageInfoValue);
301 	fPackageInfoValue.Clear();
302 
303 	delete this;
304 	return error;
305 }
306 
307 
308 // #pragma mark - PackageAttributeHandler
309 
310 
311 status_t
312 ReaderImplBase::PackageAttributeHandler::HandleAttribute(
313 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
314 	AttributeHandler** _handler)
315 {
316 	switch (id) {
317 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
318 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
319 			break;
320 
321 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
322 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
323 			break;
324 
325 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
326 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
327 				value.string);
328 			break;
329 
330 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
331 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
332 			break;
333 
334 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
335 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
336 			break;
337 
338 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE:
339 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string);
340 			break;
341 
342 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
343 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
344 				(uint32)value.unsignedInt);
345 			break;
346 
347 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
348 			if (value.unsignedInt
349 					>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
350 				context->errorOutput->PrintError(
351 					"Error: Invalid package attribute section: "
352 					"Invalid package architecture %lld encountered\n",
353 					value.unsignedInt);
354 				return B_BAD_DATA;
355 			}
356 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
357 				(uint8)value.unsignedInt);
358 			break;
359 
360 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
361 			fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
362 			fPackageInfoValue.version.major = value.string;
363 			if (_handler != NULL) {
364 				*_handler
365 					= new(std::nothrow) PackageVersionAttributeHandler(
366 						fPackageInfoValue, fPackageInfoValue.version, true);
367 				if (*_handler == NULL)
368 					return B_NO_MEMORY;
369 			}
370 			break;
371 
372 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
373 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
374 				value.string);
375 			break;
376 
377 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
378 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
379 				value.string);
380 			break;
381 
382 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
383 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
384 			break;
385 
386 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
387 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
388 			break;
389 
390 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
391 			fPackageInfoValue.resolvable.name = value.string;
392 			fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
393 			if (_handler != NULL) {
394 				*_handler
395 					= new(std::nothrow) PackageResolvableAttributeHandler(
396 						fPackageInfoValue);
397 				if (*_handler == NULL)
398 					return B_NO_MEMORY;
399 			}
400 			break;
401 
402 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
403 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
404 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
405 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
406 			fPackageInfoValue.resolvableExpression.name = value.string;
407 			switch (id) {
408 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
409 					fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
410 					break;
411 
412 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
413 					fPackageInfoValue.attributeID
414 						= B_PACKAGE_INFO_SUPPLEMENTS;
415 					break;
416 
417 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
418 					fPackageInfoValue.attributeID
419 						= B_PACKAGE_INFO_CONFLICTS;
420 					break;
421 
422 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
423 					fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
424 					break;
425 			}
426 			if (_handler != NULL) {
427 				*_handler = new(std::nothrow)
428 					PackageResolvableExpressionAttributeHandler(
429 						fPackageInfoValue);
430 				if (*_handler == NULL)
431 					return B_NO_MEMORY;
432 			}
433 			break;
434 
435 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
436 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
437 			break;
438 
439 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
440 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
441 			break;
442 
443 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
444 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
445 			break;
446 
447 		default:
448 			context->errorOutput->PrintError(
449 				"Error: Invalid package attribute section: unexpected "
450 				"package attribute id %d encountered\n", id);
451 			return B_BAD_DATA;
452 	}
453 
454 	// notify unless the current attribute has children, in which case
455 	// the child-handler will notify when it's done
456 	if (_handler == NULL) {
457 		status_t error = context->packageContentHandler
458 			->HandlePackageAttribute(fPackageInfoValue);
459 		fPackageInfoValue.Clear();
460 		if (error != B_OK)
461 			return error;
462 	}
463 
464 	return B_OK;
465 }
466 
467 
468 // #pragma mark - LowLevelAttributeHandler
469 
470 
471 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
472 	:
473 	fParentToken(NULL),
474 	fToken(NULL),
475 	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
476 {
477 }
478 
479 
480 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
481 	const BPackageAttributeValue& value, void* parentToken, void* token)
482 	:
483 	fParentToken(NULL),
484 	fToken(token),
485 	fID(id),
486 	fValue(value)
487 {
488 }
489 
490 
491 status_t
492 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
493 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
494 	AttributeHandler** _handler)
495 {
496 	// notify the content handler
497 	void* token;
498 	status_t error = context->lowLevelHandler->HandleAttribute(
499 		(BHPKGAttributeID)id, value, fToken, token);
500 	if (error != B_OK)
501 		return error;
502 
503 	// create a subhandler for the attribute, if it has children
504 	if (_handler != NULL) {
505 		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
506 			fToken, token);
507 		if (*_handler == NULL) {
508 			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
509 				value, fToken, token);
510 			return B_NO_MEMORY;
511 		}
512 		return B_OK;
513 	}
514 
515 	// no children -- just call the done hook
516 	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
517 		value, fToken, token);
518 }
519 
520 
521 status_t
522 ReaderImplBase::LowLevelAttributeHandler::Delete(
523 	AttributeHandlerContext* context)
524 {
525 	status_t error = B_OK;
526 	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
527 		error = context->lowLevelHandler->HandleAttributeDone(
528 			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
529 	}
530 
531 	delete this;
532 	return error;
533 }
534 
535 
536 // #pragma mark - ReaderImplBase
537 
538 
539 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput)
540 	:
541 	fPackageAttributesSection("package attributes"),
542 	fFileType(fileType),
543 	fErrorOutput(errorOutput),
544 	fFD(-1),
545 	fOwnsFD(false),
546 	fRawHeapReader(NULL),
547 	fHeapReader(NULL),
548 	fCurrentSection(NULL),
549 	fScratchBuffer(NULL),
550 	fScratchBufferSize(0)
551 {
552 }
553 
554 
555 ReaderImplBase::~ReaderImplBase()
556 {
557 	delete fHeapReader;
558 	if (fRawHeapReader != fHeapReader)
559 		delete fRawHeapReader;
560 
561 	if (fOwnsFD && fFD >= 0)
562 		close(fFD);
563 
564 	delete[] fScratchBuffer;
565 }
566 
567 
568 uint64
569 ReaderImplBase::UncompressedHeapSize() const
570 {
571 	return fRawHeapReader->UncompressedHeapSize();
572 }
573 
574 
575 BAbstractBufferedDataReader*
576 ReaderImplBase::DetachHeapReader(PackageFileHeapReader** _rawHeapReader)
577 {
578 	BAbstractBufferedDataReader* heapReader = fHeapReader;
579 	fHeapReader = NULL;
580 
581 	if (_rawHeapReader != NULL)
582 		*_rawHeapReader = fRawHeapReader;
583 	fRawHeapReader = NULL;
584 
585 	return heapReader;
586 }
587 
588 
589 status_t
590 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,
591 	off_t offset, uint64 compressedSize, uint64 uncompressedSize)
592 {
593 	if (compression != B_HPKG_COMPRESSION_ZLIB) {
594 		fErrorOutput->PrintError("Error: Invalid heap compression\n");
595 		return B_BAD_DATA;
596 	}
597 
598 	fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, fFD,
599 		offset, compressedSize, uncompressedSize);
600 	if (fRawHeapReader == NULL)
601 		return B_NO_MEMORY;
602 
603 	status_t error = fRawHeapReader->Init();
604 	if (error != B_OK)
605 		return error;
606 
607 	error = CreateCachedHeapReader(fRawHeapReader, fHeapReader);
608 	if (error != B_OK) {
609 		if (error != B_NOT_SUPPORTED)
610 			return error;
611 
612 		fHeapReader = fRawHeapReader;
613 	}
614 
615 	return B_OK;
616 }
617 
618 
619 status_t
620 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader,
621 	BAbstractBufferedDataReader*& _cachedReader)
622 {
623 	return B_NOT_SUPPORTED;
624 }
625 
626 
627 status_t
628 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset,
629 	uint64 length, uint64 maxSaneLength, uint64 stringsLength,
630 	uint64 stringsCount)
631 {
632 	// check length vs. endOffset
633 	if (length > endOffset) {
634 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
635 			B_PRIu64 " bytes. This is greater than the available space\n",
636 			fFileType, section.name, length);
637 		return B_BAD_DATA;
638 	}
639 
640 	// check sanity length
641 	if (maxSaneLength > 0 && length > maxSaneLength) {
642 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
643 			B_PRIu64 " bytes. This is beyond the reader's sanity limit\n",
644 			fFileType, section.name, length);
645 		return B_NOT_SUPPORTED;
646 	}
647 
648 	// check strings subsection size/count
649 	if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) {
650 		ErrorOutput()->PrintError("Error: strings subsection description of %s "
651 			"file %s section is invalid (%" B_PRIu64 " strings, length: %"
652 			B_PRIu64 ", section length: %" B_PRIu64 ")\n",
653 			fFileType, section.name, stringsCount, stringsLength, length);
654 		return B_BAD_DATA;
655 	}
656 
657 	section.uncompressedLength = length;
658 	section.offset = endOffset - length;
659 	section.currentOffset = 0;
660 	section.stringsLength = stringsLength;
661 	section.stringsCount = stringsCount;
662 
663 	return B_OK;
664 }
665 
666 
667 status_t
668 ReaderImplBase::PrepareSection(PackageFileSection& section)
669 {
670 	// allocate memory for the section data and read it in
671 	section.data = new(std::nothrow) uint8[section.uncompressedLength];
672 	if (section.data == NULL) {
673 		ErrorOutput()->PrintError("Error: Out of memory!\n");
674 		return B_NO_MEMORY;
675 	}
676 
677 	status_t error = ReadSection(section);
678 	if (error != B_OK)
679 		return error;
680 
681 	// parse the section strings
682 	section.currentOffset = 0;
683 	SetCurrentSection(&section);
684 
685 	error = ParseStrings();
686 	if (error != B_OK)
687 		return error;
688 
689 	return B_OK;
690 }
691 
692 
693 status_t
694 ReaderImplBase::ParseStrings()
695 {
696 	// allocate table, if there are any strings
697 	if (fCurrentSection->stringsCount == 0) {
698 		fCurrentSection->currentOffset += fCurrentSection->stringsLength;
699 		return B_OK;
700 	}
701 
702 	fCurrentSection->strings
703 		= new(std::nothrow) char*[fCurrentSection->stringsCount];
704 	if (fCurrentSection->strings == NULL) {
705 		fErrorOutput->PrintError("Error: Out of memory!\n");
706 		return B_NO_MEMORY;
707 	}
708 
709 	// parse the section and fill the table
710 	char* position
711 		= (char*)fCurrentSection->data + fCurrentSection->currentOffset;
712 	char* sectionEnd = position + fCurrentSection->stringsLength;
713 	uint32 index = 0;
714 	while (true) {
715 		if (position >= sectionEnd) {
716 			fErrorOutput->PrintError("Error: Malformed %s strings section\n",
717 				fCurrentSection->name);
718 			return B_BAD_DATA;
719 		}
720 
721 		size_t stringLength = strnlen(position, (char*)sectionEnd - position);
722 
723 		if (stringLength == 0) {
724 			if (position + 1 != sectionEnd) {
725 				fErrorOutput->PrintError(
726 					"Error: %ld excess bytes in %s strings section\n",
727 					sectionEnd - (position + 1), fCurrentSection->name);
728 				return B_BAD_DATA;
729 			}
730 
731 			if (index != fCurrentSection->stringsCount) {
732 				fErrorOutput->PrintError("Error: Invalid %s strings section: "
733 					"Less strings (%lld) than specified in the header (%lld)\n",
734 					fCurrentSection->name, index,
735 					fCurrentSection->stringsCount);
736 				return B_BAD_DATA;
737 			}
738 
739 			fCurrentSection->currentOffset += fCurrentSection->stringsLength;
740 
741 			return B_OK;
742 		}
743 
744 		if (index >= fCurrentSection->stringsCount) {
745 			fErrorOutput->PrintError("Error: Invalid %s strings section: "
746 				"More strings (%lld) than specified in the header (%lld)\n",
747 				fCurrentSection->name, index, fCurrentSection->stringsCount);
748 			return B_BAD_DATA;
749 		}
750 
751 		fCurrentSection->strings[index++] = position;
752 		position += stringLength + 1;
753 	}
754 }
755 
756 
757 status_t
758 ReaderImplBase::ParsePackageAttributesSection(
759 	AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
760 {
761 	// parse package attributes
762 	SetCurrentSection(&fPackageAttributesSection);
763 
764 	// init the attribute handler stack
765 	rootAttributeHandler->SetLevel(0);
766 	ClearAttributeHandlerStack();
767 	PushAttributeHandler(rootAttributeHandler);
768 
769 	bool sectionHandled;
770 	status_t error = ParseAttributeTree(context, sectionHandled);
771 	if (error == B_OK && sectionHandled) {
772 		if (fPackageAttributesSection.currentOffset
773 				< fPackageAttributesSection.uncompressedLength) {
774 			fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
775 				"attributes section\n",
776 				fPackageAttributesSection.uncompressedLength
777 					- fPackageAttributesSection.currentOffset);
778 			error = B_BAD_DATA;
779 		}
780 	}
781 
782 	SetCurrentSection(NULL);
783 
784 	// clean up on error
785 	if (error != B_OK) {
786 		context->ErrorOccurred();
787 		while (AttributeHandler* handler = PopAttributeHandler()) {
788 			if (handler != rootAttributeHandler)
789 				handler->Delete(context);
790 		}
791 		return error;
792 	}
793 
794 	return B_OK;
795 }
796 
797 
798 status_t
799 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
800 	bool& _sectionHandled)
801 {
802 	if (context->hasLowLevelHandler) {
803 		bool handleSection = false;
804 		status_t error = context->lowLevelHandler->HandleSectionStart(
805 			context->section, handleSection);
806 		if (error != B_OK)
807 			return error;
808 
809 		if (!handleSection) {
810 			_sectionHandled = false;
811 			return B_OK;
812 		}
813 	}
814 
815 	status_t error = _ParseAttributeTree(context);
816 
817 	if (context->hasLowLevelHandler) {
818 		status_t endError = context->lowLevelHandler->HandleSectionEnd(
819 			context->section);
820 		if (error == B_OK)
821 			error = endError;
822 	}
823 
824 	_sectionHandled = true;
825 	return error;
826 }
827 
828 
829 status_t
830 ReaderImplBase::_Init(int fd, bool keepFD)
831 {
832 	fFD = fd;
833 	fOwnsFD = keepFD;
834 
835 	// allocate a scratch buffer
836 	fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
837 	if (fScratchBuffer == NULL) {
838 		fErrorOutput->PrintError("Error: Out of memory!\n");
839 		return B_NO_MEMORY;
840 	}
841 	fScratchBufferSize = kScratchBufferSize;
842 
843 	return B_OK;
844 }
845 
846 
847 status_t
848 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
849 {
850 	int level = 0;
851 
852 	while (true) {
853 		uint8 id;
854 		AttributeValue value;
855 		bool hasChildren;
856 		uint64 tag;
857 
858 		status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
859 		if (error != B_OK)
860 			return error;
861 
862 		if (tag == 0) {
863 			AttributeHandler* handler = PopAttributeHandler();
864 			if (level-- == 0)
865 				return B_OK;
866 
867 			error = handler->Delete(context);
868 			if (error != B_OK)
869 				return error;
870 
871 			continue;
872 		}
873 
874 		AttributeHandler* childHandler = NULL;
875 		error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
876 			hasChildren ? &childHandler : NULL);
877 		if (error != B_OK)
878 			return error;
879 
880 		// parse children
881 		if (hasChildren) {
882 			// create an ignore handler, if necessary
883 			if (childHandler == NULL) {
884 				childHandler = new(std::nothrow) IgnoreAttributeHandler;
885 				if (childHandler == NULL) {
886 					fErrorOutput->PrintError("Error: Out of memory!\n");
887 					return B_NO_MEMORY;
888 				}
889 			}
890 
891 			childHandler->SetLevel(++level);
892 			PushAttributeHandler(childHandler);
893 		}
894 	}
895 }
896 
897 
898 status_t
899 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
900 	bool* _hasChildren, uint64* _tag)
901 {
902 	uint64 tag;
903 	status_t error = ReadUnsignedLEB128(tag);
904 	if (error != B_OK)
905 		return error;
906 
907 	if (tag != 0) {
908 		// get the type
909 		uint16 type = attribute_tag_type(tag);
910 		if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
911 			fErrorOutput->PrintError("Error: Invalid %s section: attribute "
912 				"type %d not supported!\n", fCurrentSection->name, type);
913 			return B_BAD_DATA;
914 		}
915 
916 		// get the value
917 		error = ReadAttributeValue(type, attribute_tag_encoding(tag),
918 			_value);
919 		if (error != B_OK)
920 			return error;
921 
922 		_id = attribute_tag_id(tag);
923 		if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
924 			fErrorOutput->PrintError("Error: Invalid %s section: "
925 				"attribute id %d not supported!\n", fCurrentSection->name, _id);
926 			return B_BAD_DATA;
927 		}
928 	}
929 
930 	if (_hasChildren != NULL)
931 		*_hasChildren = attribute_tag_has_children(tag);
932 	if (_tag != NULL)
933 		*_tag = tag;
934 
935 	return B_OK;
936 }
937 
938 
939 status_t
940 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
941 	AttributeValue& _value)
942 {
943 	switch (type) {
944 		case B_HPKG_ATTRIBUTE_TYPE_INT:
945 		case B_HPKG_ATTRIBUTE_TYPE_UINT:
946 		{
947 			uint64 intValue;
948 			status_t error;
949 
950 			switch (encoding) {
951 				case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
952 				{
953 					uint8 value;
954 					error = _Read(value);
955 					intValue = value;
956 					break;
957 				}
958 				case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
959 				{
960 					uint16 value;
961 					error = _Read(value);
962 					intValue = B_BENDIAN_TO_HOST_INT16(value);
963 					break;
964 				}
965 				case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
966 				{
967 					uint32 value;
968 					error = _Read(value);
969 					intValue = B_BENDIAN_TO_HOST_INT32(value);
970 					break;
971 				}
972 				case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
973 				{
974 					uint64 value;
975 					error = _Read(value);
976 					intValue = B_BENDIAN_TO_HOST_INT64(value);
977 					break;
978 				}
979 				default:
980 				{
981 					fErrorOutput->PrintError("Error: Invalid %s section: "
982 						"invalid encoding %d for int value type %d\n",
983 						fCurrentSection->name, encoding, type);
984 					return B_BAD_VALUE;
985 				}
986 			}
987 
988 			if (error != B_OK)
989 				return error;
990 
991 			if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
992 				_value.SetTo((int64)intValue);
993 			else
994 				_value.SetTo(intValue);
995 
996 			return B_OK;
997 		}
998 
999 		case B_HPKG_ATTRIBUTE_TYPE_STRING:
1000 		{
1001 			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
1002 				uint64 index;
1003 				status_t error = ReadUnsignedLEB128(index);
1004 				if (error != B_OK)
1005 					return error;
1006 
1007 				if (index > fCurrentSection->stringsCount) {
1008 					fErrorOutput->PrintError("Error: Invalid %s section: "
1009 						"string reference (%lld) out of bounds (%lld)\n",
1010 						fCurrentSection->name, index,
1011 						fCurrentSection->stringsCount);
1012 					return B_BAD_DATA;
1013 				}
1014 
1015 				_value.SetTo(fCurrentSection->strings[index]);
1016 			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
1017 				const char* string;
1018 				status_t error = _ReadString(string);
1019 				if (error != B_OK)
1020 					return error;
1021 
1022 				_value.SetTo(string);
1023 			} else {
1024 				fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1025 					"string encoding (%u)\n", fCurrentSection->name, encoding);
1026 				return B_BAD_DATA;
1027 			}
1028 
1029 			return B_OK;
1030 		}
1031 
1032 		default:
1033 			fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1034 				"value type: %d\n", fCurrentSection->name, type);
1035 			return B_BAD_DATA;
1036 	}
1037 }
1038 
1039 
1040 status_t
1041 ReaderImplBase::ReadUnsignedLEB128(uint64& _value)
1042 {
1043 	uint64 result = 0;
1044 	int shift = 0;
1045 	while (true) {
1046 		uint8 byte;
1047 		status_t error = _Read(byte);
1048 		if (error != B_OK)
1049 			return error;
1050 
1051 		result |= uint64(byte & 0x7f) << shift;
1052 		if ((byte & 0x80) == 0)
1053 			break;
1054 		shift += 7;
1055 	}
1056 
1057 	_value = result;
1058 	return B_OK;
1059 }
1060 
1061 
1062 status_t
1063 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength)
1064 {
1065 	const char* string
1066 		= (const char*)fCurrentSection->data + fCurrentSection->currentOffset;
1067 	size_t stringLength = strnlen(string,
1068 		fCurrentSection->uncompressedLength - fCurrentSection->currentOffset);
1069 
1070 	if (stringLength
1071 		== fCurrentSection->uncompressedLength
1072 			- fCurrentSection->currentOffset) {
1073 		fErrorOutput->PrintError(
1074 			"_ReadString(): string extends beyond %s end\n",
1075 			fCurrentSection->name);
1076 		return B_BAD_DATA;
1077 	}
1078 
1079 	_string = string;
1080 	if (_stringLength != NULL)
1081 		*_stringLength = stringLength;
1082 
1083 	fCurrentSection->currentOffset += stringLength + 1;
1084 	return B_OK;
1085 }
1086 
1087 
1088 status_t
1089 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size)
1090 {
1091 	if (size > fCurrentSection->uncompressedLength
1092 			- fCurrentSection->currentOffset) {
1093 		fErrorOutput->PrintError(
1094 			"_ReadSectionBuffer(%lu): read beyond %s end\n", size,
1095 			fCurrentSection->name);
1096 		return B_BAD_DATA;
1097 	}
1098 
1099 	memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset,
1100 		size);
1101 	fCurrentSection->currentOffset += size;
1102 	return B_OK;
1103 }
1104 
1105 
1106 status_t
1107 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size)
1108 {
1109 	ssize_t bytesRead = pread(fFD, buffer, size, offset);
1110 	if (bytesRead < 0) {
1111 		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1112 			"%s\n", buffer, size, strerror(errno));
1113 		return errno;
1114 	}
1115 	if ((size_t)bytesRead != size) {
1116 		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all "
1117 			"data\n", buffer, size);
1118 		return B_ERROR;
1119 	}
1120 
1121 	return B_OK;
1122 }
1123 
1124 
1125 status_t
1126 ReaderImplBase::ReadSection(const PackageFileSection& section)
1127 {
1128 	BBufferDataOutput output(section.data, section.uncompressedLength);
1129 	return fHeapReader->ReadDataToOutput(section.offset,
1130 		section.uncompressedLength, &output);
1131 }
1132 
1133 
1134 }	// namespace BPrivate
1135 
1136 }	// namespace BHPKG
1137 
1138 }	// namespace BPackageKit
1139