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