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