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