xref: /haiku/src/kits/package/hpkg/ReaderImplBase.cpp (revision a5061ecec55353a5f394759473f1fd6df04890da)
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 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PRE_UNINSTALL_SCRIPT:
672 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PRE_UNINSTALL_SCRIPTS,
673 				value.string);
674 			break;
675 
676 		default:
677 			if (context->ignoreUnknownAttributes)
678 				break;
679 
680 			context->errorOutput->PrintError(
681 				"Error: Invalid package attribute section: unexpected "
682 				"package attribute id %d encountered\n", id);
683 			return B_BAD_DATA;
684 	}
685 
686 	// notify unless the current attribute has children, in which case
687 	// the child-handler will notify when it's done
688 	if (_handler == NULL) {
689 		status_t error = context->packageContentHandler
690 			->HandlePackageAttribute(fPackageInfoValue);
691 		if (context->ignoreUnknownAttributes && error == B_NOT_SUPPORTED)
692 			error = B_OK; // Safe to skip a future/unknown attribute.
693 		fPackageInfoValue.Clear();
694 		if (error != B_OK)
695 			return error;
696 	}
697 
698 	return B_OK;
699 }
700 
701 
702 // #pragma mark - LowLevelAttributeHandler
703 
704 
705 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
706 	:
707 	fParentToken(NULL),
708 	fToken(NULL),
709 	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
710 {
711 }
712 
713 
714 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
715 	const BPackageAttributeValue& value, void* parentToken, void* token)
716 	:
717 	fParentToken(NULL),
718 	fToken(token),
719 	fID(id),
720 	fValue(value)
721 {
722 }
723 
724 
725 status_t
726 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
727 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
728 	AttributeHandler** _handler)
729 {
730 	// notify the content handler
731 	void* token;
732 	status_t error = context->lowLevelHandler->HandleAttribute(
733 		(BHPKGAttributeID)id, value, fToken, token);
734 	if (error != B_OK)
735 		return error;
736 
737 	// create a subhandler for the attribute, if it has children
738 	if (_handler != NULL) {
739 		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
740 			fToken, token);
741 		if (*_handler == NULL) {
742 			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
743 				value, fToken, token);
744 			return B_NO_MEMORY;
745 		}
746 		return B_OK;
747 	}
748 
749 	// no children -- just call the done hook
750 	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
751 		value, fToken, token);
752 }
753 
754 
755 status_t
756 ReaderImplBase::LowLevelAttributeHandler::NotifyDone(
757 	AttributeHandlerContext* context)
758 {
759 	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
760 		status_t error = context->lowLevelHandler->HandleAttributeDone(
761 			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
762 		if (error != B_OK)
763 			return error;
764 	}
765 	return super::NotifyDone(context);
766 }
767 
768 
769 // #pragma mark - ReaderImplBase
770 
771 
772 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput)
773 	:
774 	fPackageAttributesSection("package attributes"),
775 	fFileType(fileType),
776 	fErrorOutput(errorOutput),
777 	fFile(NULL),
778 	fOwnsFile(false),
779 	fRawHeapReader(NULL),
780 	fHeapReader(NULL),
781 	fCurrentSection(NULL)
782 {
783 }
784 
785 
786 ReaderImplBase::~ReaderImplBase()
787 {
788 	delete fHeapReader;
789 	if (fRawHeapReader != fHeapReader)
790 		delete fRawHeapReader;
791 
792 	if (fOwnsFile)
793 		delete fFile;
794 }
795 
796 
797 uint64
798 ReaderImplBase::UncompressedHeapSize() const
799 {
800 	return fRawHeapReader->UncompressedHeapSize();
801 }
802 
803 
804 BAbstractBufferedDataReader*
805 ReaderImplBase::DetachHeapReader(PackageFileHeapReader*& _rawHeapReader)
806 {
807 	BAbstractBufferedDataReader* heapReader = fHeapReader;
808 	_rawHeapReader = fRawHeapReader;
809 	fHeapReader = NULL;
810 	fRawHeapReader = NULL;
811 
812 	return heapReader;
813 }
814 
815 
816 status_t
817 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,
818 	off_t offset, uint64 compressedSize, uint64 uncompressedSize)
819 {
820 	DecompressionAlgorithmOwner* decompressionAlgorithm = NULL;
821 	BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference;
822 
823 	switch (compression) {
824 		case B_HPKG_COMPRESSION_NONE:
825 			break;
826 		case B_HPKG_COMPRESSION_ZLIB:
827 			decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
828 				new(std::nothrow) BZlibCompressionAlgorithm,
829 				new(std::nothrow) BZlibDecompressionParameters);
830 			decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
831 			if (decompressionAlgorithm == NULL
832 				|| decompressionAlgorithm->algorithm == NULL
833 				|| decompressionAlgorithm->parameters == NULL) {
834 				return B_NO_MEMORY;
835 			}
836 			break;
837 #ifdef ZSTD_ENABLED
838 		case B_HPKG_COMPRESSION_ZSTD:
839 			decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
840 				new(std::nothrow) BZstdCompressionAlgorithm,
841 				new(std::nothrow) BZstdDecompressionParameters);
842 			decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
843 			if (decompressionAlgorithm == NULL
844 				|| decompressionAlgorithm->algorithm == NULL
845 				|| decompressionAlgorithm->parameters == NULL) {
846 				return B_NO_MEMORY;
847 			}
848 			break;
849 #endif
850 		default:
851 			fErrorOutput->PrintError("Error: Invalid heap compression\n");
852 			return B_BAD_DATA;
853 	}
854 
855 	fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput,
856 		fFile, offset, compressedSize, uncompressedSize,
857 		decompressionAlgorithm);
858 	if (fRawHeapReader == NULL)
859 		return B_NO_MEMORY;
860 
861 	status_t error = fRawHeapReader->Init();
862 	if (error != B_OK)
863 		return error;
864 
865 	error = CreateCachedHeapReader(fRawHeapReader, fHeapReader);
866 	if (error != B_OK) {
867 		if (error != B_NOT_SUPPORTED)
868 			return error;
869 
870 		fHeapReader = fRawHeapReader;
871 	}
872 
873 	return B_OK;
874 }
875 
876 
877 status_t
878 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader,
879 	BAbstractBufferedDataReader*& _cachedReader)
880 {
881 	return B_NOT_SUPPORTED;
882 }
883 
884 
885 status_t
886 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset,
887 	uint64 length, uint64 maxSaneLength, uint64 stringsLength,
888 	uint64 stringsCount)
889 {
890 	// check length vs. endOffset
891 	if (length > endOffset) {
892 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
893 			B_PRIu64 " bytes. This is greater than the available space\n",
894 			fFileType, section.name, length);
895 		return B_BAD_DATA;
896 	}
897 
898 	// check sanity length
899 	if (maxSaneLength > 0 && length > maxSaneLength) {
900 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
901 			B_PRIu64 " bytes. This is beyond the reader's sanity limit\n",
902 			fFileType, section.name, length);
903 		return B_NOT_SUPPORTED;
904 	}
905 
906 	// check strings subsection size/count
907 	if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) {
908 		ErrorOutput()->PrintError("Error: strings subsection description of %s "
909 			"file %s section is invalid (%" B_PRIu64 " strings, length: %"
910 			B_PRIu64 ", section length: %" B_PRIu64 ")\n",
911 			fFileType, section.name, stringsCount, stringsLength, length);
912 		return B_BAD_DATA;
913 	}
914 
915 	section.uncompressedLength = length;
916 	section.offset = endOffset - length;
917 	section.currentOffset = 0;
918 	section.stringsLength = stringsLength;
919 	section.stringsCount = stringsCount;
920 
921 	return B_OK;
922 }
923 
924 
925 status_t
926 ReaderImplBase::PrepareSection(PackageFileSection& section)
927 {
928 	// allocate memory for the section data and read it in
929 	section.data = new(std::nothrow) uint8[section.uncompressedLength];
930 	if (section.data == NULL) {
931 		ErrorOutput()->PrintError("Error: Out of memory!\n");
932 		return B_NO_MEMORY;
933 	}
934 
935 	status_t error = ReadSection(section);
936 	if (error != B_OK)
937 		return error;
938 
939 	// parse the section strings
940 	section.currentOffset = 0;
941 	SetCurrentSection(&section);
942 
943 	error = ParseStrings();
944 	if (error != B_OK)
945 		return error;
946 
947 	return B_OK;
948 }
949 
950 
951 status_t
952 ReaderImplBase::ParseStrings()
953 {
954 	// allocate table, if there are any strings
955 	if (fCurrentSection->stringsCount == 0) {
956 		fCurrentSection->currentOffset += fCurrentSection->stringsLength;
957 		return B_OK;
958 	}
959 
960 	fCurrentSection->strings
961 		= new(std::nothrow) char*[fCurrentSection->stringsCount];
962 	if (fCurrentSection->strings == NULL) {
963 		fErrorOutput->PrintError("Error: Out of memory!\n");
964 		return B_NO_MEMORY;
965 	}
966 
967 	// parse the section and fill the table
968 	char* position
969 		= (char*)fCurrentSection->data + fCurrentSection->currentOffset;
970 	char* sectionEnd = position + fCurrentSection->stringsLength;
971 	uint32 index = 0;
972 	while (true) {
973 		if (position >= sectionEnd) {
974 			fErrorOutput->PrintError("Error: Malformed %s strings section\n",
975 				fCurrentSection->name);
976 			return B_BAD_DATA;
977 		}
978 
979 		size_t stringLength = strnlen(position, (char*)sectionEnd - position);
980 
981 		if (stringLength == 0) {
982 			if (position + 1 != sectionEnd) {
983 				fErrorOutput->PrintError(
984 					"Error: %ld excess bytes in %s strings section\n",
985 					sectionEnd - (position + 1), fCurrentSection->name);
986 				return B_BAD_DATA;
987 			}
988 
989 			if (index != fCurrentSection->stringsCount) {
990 				fErrorOutput->PrintError("Error: Invalid %s strings section: "
991 					"Less strings (%lld) than specified in the header (%lld)\n",
992 					fCurrentSection->name, index,
993 					fCurrentSection->stringsCount);
994 				return B_BAD_DATA;
995 			}
996 
997 			fCurrentSection->currentOffset += fCurrentSection->stringsLength;
998 
999 			return B_OK;
1000 		}
1001 
1002 		if (index >= fCurrentSection->stringsCount) {
1003 			fErrorOutput->PrintError("Error: Invalid %s strings section: "
1004 				"More strings (%lld) than specified in the header (%lld)\n",
1005 				fCurrentSection->name, index, fCurrentSection->stringsCount);
1006 			return B_BAD_DATA;
1007 		}
1008 
1009 		fCurrentSection->strings[index++] = position;
1010 		position += stringLength + 1;
1011 	}
1012 }
1013 
1014 
1015 status_t
1016 ReaderImplBase::ParsePackageAttributesSection(
1017 	AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
1018 {
1019 	// parse package attributes
1020 	SetCurrentSection(&fPackageAttributesSection);
1021 
1022 	// init the attribute handler stack
1023 	rootAttributeHandler->SetLevel(0);
1024 	ClearAttributeHandlerStack();
1025 	PushAttributeHandler(rootAttributeHandler);
1026 
1027 	bool sectionHandled;
1028 	status_t error = ParseAttributeTree(context, sectionHandled);
1029 	if (error == B_OK && sectionHandled) {
1030 		if (fPackageAttributesSection.currentOffset
1031 				< fPackageAttributesSection.uncompressedLength) {
1032 			fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
1033 				"attributes section\n",
1034 				fPackageAttributesSection.uncompressedLength
1035 					- fPackageAttributesSection.currentOffset);
1036 			error = B_BAD_DATA;
1037 		}
1038 	}
1039 
1040 	SetCurrentSection(NULL);
1041 
1042 	// clean up on error
1043 	if (error != B_OK) {
1044 		context->ErrorOccurred();
1045 		while (AttributeHandler* handler = PopAttributeHandler()) {
1046 			if (handler != rootAttributeHandler)
1047 				handler->Delete(context);
1048 		}
1049 		return error;
1050 	}
1051 
1052 	return B_OK;
1053 }
1054 
1055 
1056 status_t
1057 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
1058 	bool& _sectionHandled)
1059 {
1060 	if (context->hasLowLevelHandler) {
1061 		bool handleSection = false;
1062 		status_t error = context->lowLevelHandler->HandleSectionStart(
1063 			context->section, handleSection);
1064 		if (error != B_OK)
1065 			return error;
1066 
1067 		if (!handleSection) {
1068 			_sectionHandled = false;
1069 			return B_OK;
1070 		}
1071 	}
1072 
1073 	status_t error = _ParseAttributeTree(context);
1074 
1075 	if (context->hasLowLevelHandler) {
1076 		status_t endError = context->lowLevelHandler->HandleSectionEnd(
1077 			context->section);
1078 		if (error == B_OK)
1079 			error = endError;
1080 	}
1081 
1082 	_sectionHandled = true;
1083 	return error;
1084 }
1085 
1086 
1087 status_t
1088 ReaderImplBase::_Init(BPositionIO* file, bool keepFile)
1089 {
1090 	fFile = file;
1091 	fOwnsFile = keepFile;
1092 	return fFile != NULL ? B_OK : B_BAD_VALUE;
1093 }
1094 
1095 
1096 status_t
1097 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
1098 {
1099 	int level = 0;
1100 
1101 	while (true) {
1102 		uint8 id;
1103 		AttributeValue value;
1104 		bool hasChildren;
1105 		uint64 tag;
1106 
1107 		status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
1108 		if (error != B_OK)
1109 			return error;
1110 
1111 		if (tag == 0) {
1112 			AttributeHandler* handler = PopAttributeHandler();
1113 			error = handler->NotifyDone(context);
1114 			if (error != B_OK)
1115 				return error;
1116 			if (level-- == 0)
1117 				return B_OK;
1118 
1119 			error = handler->Delete(context);
1120 			if (error != B_OK)
1121 				return error;
1122 
1123 			continue;
1124 		}
1125 
1126 		AttributeHandler* childHandler = NULL;
1127 		error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
1128 			hasChildren ? &childHandler : NULL);
1129 		if (error != B_OK)
1130 			return error;
1131 
1132 		// parse children
1133 		if (hasChildren) {
1134 			// create an ignore handler, if necessary
1135 			if (childHandler == NULL) {
1136 				childHandler = new(std::nothrow) IgnoreAttributeHandler;
1137 				if (childHandler == NULL) {
1138 					fErrorOutput->PrintError("Error: Out of memory!\n");
1139 					return B_NO_MEMORY;
1140 				}
1141 			}
1142 
1143 			childHandler->SetLevel(++level);
1144 			PushAttributeHandler(childHandler);
1145 		}
1146 	}
1147 }
1148 
1149 
1150 status_t
1151 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
1152 	bool* _hasChildren, uint64* _tag)
1153 {
1154 	uint64 tag;
1155 	status_t error = ReadUnsignedLEB128(tag);
1156 	if (error != B_OK)
1157 		return error;
1158 
1159 	if (tag != 0) {
1160 		// get the type
1161 		uint16 type = attribute_tag_type(tag);
1162 		if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
1163 			fErrorOutput->PrintError("Error: Invalid %s section: attribute "
1164 				"type %d not supported!\n", fCurrentSection->name, type);
1165 			return B_BAD_DATA;
1166 		}
1167 
1168 		// get the ID
1169 		_id = attribute_tag_id(tag);
1170 		if (_id < B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
1171 			if (type != kAttributeTypes[_id]) {
1172 				fErrorOutput->PrintError("Error: Invalid %s section: "
1173 					"unexpected type %d for attribute id %d (expected %d)!\n",
1174 					fCurrentSection->name, type, _id, kAttributeTypes[_id]);
1175 				return B_BAD_DATA;
1176 			}
1177 		} else if (fMinorFormatVersion <= fCurrentMinorFormatVersion) {
1178 			fErrorOutput->PrintError("Error: Invalid %s section: "
1179 				"attribute id %d not supported!\n", fCurrentSection->name, _id);
1180 			return B_BAD_DATA;
1181 		}
1182 
1183 		// get the value
1184 		error = ReadAttributeValue(type, attribute_tag_encoding(tag),
1185 			_value);
1186 		if (error != B_OK)
1187 			return error;
1188 	}
1189 
1190 	if (_hasChildren != NULL)
1191 		*_hasChildren = attribute_tag_has_children(tag);
1192 	if (_tag != NULL)
1193 		*_tag = tag;
1194 
1195 	return B_OK;
1196 }
1197 
1198 
1199 status_t
1200 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
1201 	AttributeValue& _value)
1202 {
1203 	switch (type) {
1204 		case B_HPKG_ATTRIBUTE_TYPE_INT:
1205 		case B_HPKG_ATTRIBUTE_TYPE_UINT:
1206 		{
1207 			uint64 intValue;
1208 			status_t error;
1209 
1210 			switch (encoding) {
1211 				case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
1212 				{
1213 					uint8 value;
1214 					error = _Read(value);
1215 					intValue = value;
1216 					break;
1217 				}
1218 				case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
1219 				{
1220 					uint16 value;
1221 					error = _Read(value);
1222 					intValue = B_BENDIAN_TO_HOST_INT16(value);
1223 					break;
1224 				}
1225 				case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
1226 				{
1227 					uint32 value;
1228 					error = _Read(value);
1229 					intValue = B_BENDIAN_TO_HOST_INT32(value);
1230 					break;
1231 				}
1232 				case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
1233 				{
1234 					uint64 value;
1235 					error = _Read(value);
1236 					intValue = B_BENDIAN_TO_HOST_INT64(value);
1237 					break;
1238 				}
1239 				default:
1240 				{
1241 					fErrorOutput->PrintError("Error: Invalid %s section: "
1242 						"invalid encoding %d for int value type %d\n",
1243 						fCurrentSection->name, encoding, type);
1244 					return B_BAD_VALUE;
1245 				}
1246 			}
1247 
1248 			if (error != B_OK)
1249 				return error;
1250 
1251 			if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
1252 				_value.SetTo((int64)intValue);
1253 			else
1254 				_value.SetTo(intValue);
1255 
1256 			return B_OK;
1257 		}
1258 
1259 		case B_HPKG_ATTRIBUTE_TYPE_STRING:
1260 		{
1261 			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
1262 				uint64 index;
1263 				status_t error = ReadUnsignedLEB128(index);
1264 				if (error != B_OK)
1265 					return error;
1266 
1267 				if (index > fCurrentSection->stringsCount) {
1268 					fErrorOutput->PrintError("Error: Invalid %s section: "
1269 						"string reference (%lld) out of bounds (%lld)\n",
1270 						fCurrentSection->name, index,
1271 						fCurrentSection->stringsCount);
1272 					return B_BAD_DATA;
1273 				}
1274 
1275 				_value.SetTo(fCurrentSection->strings[index]);
1276 			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
1277 				const char* string;
1278 				status_t error = _ReadString(string);
1279 				if (error != B_OK)
1280 					return error;
1281 
1282 				_value.SetTo(string);
1283 			} else {
1284 				fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1285 					"string encoding (%u)\n", fCurrentSection->name, encoding);
1286 				return B_BAD_DATA;
1287 			}
1288 
1289 			return B_OK;
1290 		}
1291 
1292 		default:
1293 			fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1294 				"value type: %d\n", fCurrentSection->name, type);
1295 			return B_BAD_DATA;
1296 	}
1297 }
1298 
1299 
1300 status_t
1301 ReaderImplBase::ReadUnsignedLEB128(uint64& _value)
1302 {
1303 	uint64 result = 0;
1304 	int shift = 0;
1305 	while (true) {
1306 		uint8 byte;
1307 		status_t error = _Read(byte);
1308 		if (error != B_OK)
1309 			return error;
1310 
1311 		result |= uint64(byte & 0x7f) << shift;
1312 		if ((byte & 0x80) == 0)
1313 			break;
1314 		shift += 7;
1315 	}
1316 
1317 	_value = result;
1318 	return B_OK;
1319 }
1320 
1321 
1322 status_t
1323 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength)
1324 {
1325 	const char* string
1326 		= (const char*)fCurrentSection->data + fCurrentSection->currentOffset;
1327 	size_t stringLength = strnlen(string,
1328 		fCurrentSection->uncompressedLength - fCurrentSection->currentOffset);
1329 
1330 	if (stringLength
1331 		== fCurrentSection->uncompressedLength
1332 			- fCurrentSection->currentOffset) {
1333 		fErrorOutput->PrintError(
1334 			"_ReadString(): string extends beyond %s end\n",
1335 			fCurrentSection->name);
1336 		return B_BAD_DATA;
1337 	}
1338 
1339 	_string = string;
1340 	if (_stringLength != NULL)
1341 		*_stringLength = stringLength;
1342 
1343 	fCurrentSection->currentOffset += stringLength + 1;
1344 	return B_OK;
1345 }
1346 
1347 
1348 status_t
1349 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size)
1350 {
1351 	if (size > fCurrentSection->uncompressedLength
1352 			- fCurrentSection->currentOffset) {
1353 		fErrorOutput->PrintError(
1354 			"_ReadSectionBuffer(%lu): read beyond %s end\n", size,
1355 			fCurrentSection->name);
1356 		return B_BAD_DATA;
1357 	}
1358 
1359 	memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset,
1360 		size);
1361 	fCurrentSection->currentOffset += size;
1362 	return B_OK;
1363 }
1364 
1365 
1366 status_t
1367 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size)
1368 {
1369 	status_t error = fFile->ReadAtExactly(offset, buffer, size);
1370 	if (error != B_OK) {
1371 		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1372 			"%s\n", buffer, size, strerror(error));
1373 		return error;
1374 	}
1375 
1376 	return B_OK;
1377 }
1378 
1379 
1380 status_t
1381 ReaderImplBase::ReadSection(const PackageFileSection& section)
1382 {
1383 	return fHeapReader->ReadData(section.offset,
1384 		section.data, section.uncompressedLength);
1385 }
1386 
1387 
1388 }	// namespace BPrivate
1389 
1390 }	// namespace BHPKG
1391 
1392 }	// namespace BPackageKit
1393