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