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