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