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