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