xref: /haiku/src/kits/package/hpkg/v1/ReaderImplBaseV1.cpp (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
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/v1/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 <package/hpkg/ErrorOutput.h>
23  
24  #include <AutoDeleter.h>
25  #include <package/hpkg/v1/HPKGDefsPrivate.h>
26  #include <ZlibCompressionAlgorithm.h>
27  
28  
29  namespace BPackageKit {
30  
31  namespace BHPKG {
32  
33  namespace V1 {
34  
35  namespace BPrivate {
36  
37  
38  static const size_t kScratchBufferSize = 64 * 1024;
39  
40  
41  // #pragma mark - AttributeHandlerContext
42  
43  
44  ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
45  	BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
46  	BHPKGPackageSectionID section)
47  	:
48  	errorOutput(errorOutput),
49  	packageContentHandler(packageContentHandler),
50  	hasLowLevelHandler(false),
51  	section(section)
52  {
53  }
54  
55  
56  ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
57  	BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
58  	BHPKGPackageSectionID section)
59  	:
60  	errorOutput(errorOutput),
61  	lowLevelHandler(lowLevelHandler),
62  	hasLowLevelHandler(true),
63  	section(section)
64  {
65  }
66  
67  
68  void
69  ReaderImplBase::AttributeHandlerContext::ErrorOccurred()
70  {
71  	if (hasLowLevelHandler)
72  		lowLevelHandler->HandleErrorOccurred();
73  	else
74  		packageContentHandler->HandleErrorOccurred();
75  }
76  
77  
78  // #pragma mark - AttributeHandler
79  
80  
81  ReaderImplBase::AttributeHandler::~AttributeHandler()
82  {
83  }
84  
85  
86  void
87  ReaderImplBase::AttributeHandler::SetLevel(int level)
88  {
89  	fLevel = level;
90  }
91  
92  
93  status_t
94  ReaderImplBase::AttributeHandler::HandleAttribute(
95  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
96  	AttributeHandler** _handler)
97  {
98  	return B_OK;
99  }
100  
101  
102  status_t
103  ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
104  {
105  	delete this;
106  	return B_OK;
107  }
108  
109  
110  // #pragma mark - PackageVersionAttributeHandler
111  
112  
113  ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
114  	BPackageInfoAttributeValue& packageInfoValue,
115  	BPackageVersionData& versionData, bool notify)
116  	:
117  	fPackageInfoValue(packageInfoValue),
118  	fPackageVersionData(versionData),
119  	fNotify(notify)
120  {
121  }
122  
123  
124  status_t
125  ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
126  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
127  	AttributeHandler** _handler)
128  {
129  	switch (id) {
130  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
131  			fPackageVersionData.minor = value.string;
132  			break;
133  
134  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
135  			fPackageVersionData.micro = value.string;
136  			break;
137  
138  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
139  			fPackageVersionData.preRelease = value.string;
140  			break;
141  
142  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
143  			fPackageVersionData.revision = value.unsignedInt;
144  			break;
145  
146  		default:
147  			context->errorOutput->PrintError("Error: Invalid package "
148  				"attribute section: unexpected package attribute id %d "
149  				"encountered when parsing package version\n", id);
150  			return B_BAD_DATA;
151  	}
152  
153  	return B_OK;
154  }
155  
156  
157  status_t
158  ReaderImplBase::PackageVersionAttributeHandler::Delete(
159  	AttributeHandlerContext* context)
160  {
161  	status_t error = B_OK;
162  	if (fNotify) {
163  		fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
164  		error = context->packageContentHandler->HandlePackageAttribute(
165  			fPackageInfoValue);
166  		fPackageInfoValue.Clear();
167  	}
168  
169  	delete this;
170  	return error;
171  }
172  
173  
174  // #pragma mark - PackageResolvableAttributeHandler
175  
176  
177  ReaderImplBase::PackageResolvableAttributeHandler
178  	::PackageResolvableAttributeHandler(
179  		BPackageInfoAttributeValue& packageInfoValue)
180  	:
181  	fPackageInfoValue(packageInfoValue)
182  {
183  }
184  
185  
186  status_t
187  ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
188  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
189  	AttributeHandler** _handler)
190  {
191  	switch (id) {
192  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE:
193  			// obsolete
194  			break;
195  
196  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
197  			fPackageInfoValue.resolvable.haveVersion = true;
198  			fPackageInfoValue.resolvable.version.major = value.string;
199  			if (_handler != NULL) {
200  				*_handler
201  					= new(std::nothrow) PackageVersionAttributeHandler(
202  						fPackageInfoValue,
203  						fPackageInfoValue.resolvable.version, false);
204  				if (*_handler == NULL)
205  					return B_NO_MEMORY;
206  			}
207  			break;
208  
209  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
210  			fPackageInfoValue.resolvable.haveCompatibleVersion = true;
211  			fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
212  			if (_handler != NULL) {
213  				*_handler
214  					= new(std::nothrow) PackageVersionAttributeHandler(
215  						fPackageInfoValue,
216  						fPackageInfoValue.resolvable.compatibleVersion, false);
217  				if (*_handler == NULL)
218  					return B_NO_MEMORY;
219  			}
220  			break;
221  
222  		default:
223  			context->errorOutput->PrintError("Error: Invalid package "
224  				"attribute section: unexpected package attribute id %d "
225  				"encountered when parsing package resolvable\n", id);
226  			return B_BAD_DATA;
227  	}
228  
229  	return B_OK;
230  }
231  
232  
233  status_t
234  ReaderImplBase::PackageResolvableAttributeHandler::Delete(
235  	AttributeHandlerContext* context)
236  {
237  	status_t error = context->packageContentHandler->HandlePackageAttribute(
238  		fPackageInfoValue);
239  	fPackageInfoValue.Clear();
240  
241  	delete this;
242  	return error;
243  }
244  
245  
246  // #pragma mark - PackageResolvableExpressionAttributeHandler
247  
248  
249  ReaderImplBase::PackageResolvableExpressionAttributeHandler
250  	::PackageResolvableExpressionAttributeHandler(
251  		BPackageInfoAttributeValue& packageInfoValue)
252  	:
253  	fPackageInfoValue(packageInfoValue)
254  {
255  }
256  
257  
258  status_t
259  ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
260  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
261  	AttributeHandler** _handler)
262  {
263  	switch (id) {
264  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
265  			if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
266  				context->errorOutput->PrintError(
267  					"Error: Invalid package attribute section: invalid "
268  					"package resolvable operator %lld encountered\n",
269  					value.unsignedInt);
270  				return B_BAD_DATA;
271  			}
272  			fPackageInfoValue.resolvableExpression.op
273  				= (BPackageResolvableOperator)value.unsignedInt;
274  			break;
275  
276  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
277  			fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
278  			fPackageInfoValue.resolvableExpression.version.major
279  				= value.string;
280  			if (_handler != NULL) {
281  				*_handler
282  					= new(std::nothrow) PackageVersionAttributeHandler(
283  						fPackageInfoValue,
284  						fPackageInfoValue.resolvableExpression.version,
285  						false);
286  				if (*_handler == NULL)
287  					return B_NO_MEMORY;
288  			}
289  			return B_OK;
290  
291  		default:
292  			context->errorOutput->PrintError("Error: Invalid package "
293  				"attribute section: unexpected package attribute id %d "
294  				"encountered when parsing package resolvable-expression\n",
295  				id);
296  			return B_BAD_DATA;
297  	}
298  
299  	return B_OK;
300  }
301  
302  
303  status_t
304  ReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete(
305  	AttributeHandlerContext* context)
306  {
307  	status_t error = context->packageContentHandler->HandlePackageAttribute(
308  		fPackageInfoValue);
309  	fPackageInfoValue.Clear();
310  
311  	delete this;
312  	return error;
313  }
314  
315  
316  // #pragma mark - PackageAttributeHandler
317  
318  
319  status_t
320  ReaderImplBase::PackageAttributeHandler::HandleAttribute(
321  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
322  	AttributeHandler** _handler)
323  {
324  	switch (id) {
325  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
326  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
327  			break;
328  
329  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
330  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
331  			break;
332  
333  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
334  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
335  				value.string);
336  			break;
337  
338  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
339  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
340  			break;
341  
342  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
343  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
344  			break;
345  
346  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
347  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
348  				(uint32)value.unsignedInt);
349  			break;
350  
351  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
352  			if (value.unsignedInt
353  					>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
354  				context->errorOutput->PrintError(
355  					"Error: Invalid package attribute section: "
356  					"Invalid package architecture %lld encountered\n",
357  					value.unsignedInt);
358  				return B_BAD_DATA;
359  			}
360  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
361  				(uint8)value.unsignedInt);
362  			break;
363  
364  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
365  			fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
366  			fPackageInfoValue.version.major = value.string;
367  			if (_handler != NULL) {
368  				*_handler
369  					= new(std::nothrow) PackageVersionAttributeHandler(
370  						fPackageInfoValue, fPackageInfoValue.version, true);
371  				if (*_handler == NULL)
372  					return B_NO_MEMORY;
373  			}
374  			break;
375  
376  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
377  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
378  				value.string);
379  			break;
380  
381  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
382  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
383  				value.string);
384  			break;
385  
386  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
387  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
388  			break;
389  
390  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
391  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
392  			break;
393  
394  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
395  			fPackageInfoValue.resolvable.name = value.string;
396  			fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
397  			if (_handler != NULL) {
398  				*_handler
399  					= new(std::nothrow) PackageResolvableAttributeHandler(
400  						fPackageInfoValue);
401  				if (*_handler == NULL)
402  					return B_NO_MEMORY;
403  			}
404  			break;
405  
406  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
407  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
408  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
409  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
410  			fPackageInfoValue.resolvableExpression.name = value.string;
411  			switch (id) {
412  				case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
413  					fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
414  					break;
415  
416  				case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
417  					fPackageInfoValue.attributeID
418  						= B_PACKAGE_INFO_SUPPLEMENTS;
419  					break;
420  
421  				case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
422  					fPackageInfoValue.attributeID
423  						= B_PACKAGE_INFO_CONFLICTS;
424  					break;
425  
426  				case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
427  					fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
428  					break;
429  			}
430  			if (_handler != NULL) {
431  				*_handler = new(std::nothrow)
432  					PackageResolvableExpressionAttributeHandler(
433  						fPackageInfoValue);
434  				if (*_handler == NULL)
435  					return B_NO_MEMORY;
436  			}
437  			break;
438  
439  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
440  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
441  			break;
442  
443  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
444  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
445  			break;
446  
447  		case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
448  			fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
449  			break;
450  
451  		default:
452  			context->errorOutput->PrintError(
453  				"Error: Invalid package attribute section: unexpected "
454  				"package attribute id %d encountered\n", id);
455  			return B_BAD_DATA;
456  	}
457  
458  	// notify unless the current attribute has children, in which case
459  	// the child-handler will notify when it's done
460  	if (_handler == NULL) {
461  		status_t error = context->packageContentHandler
462  			->HandlePackageAttribute(fPackageInfoValue);
463  		fPackageInfoValue.Clear();
464  		if (error != B_OK)
465  			return error;
466  	}
467  
468  	return B_OK;
469  }
470  
471  
472  // #pragma mark - LowLevelAttributeHandler
473  
474  
475  ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
476  	:
477  	fParentToken(NULL),
478  	fToken(NULL),
479  	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
480  {
481  }
482  
483  
484  ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
485  	const BPackageAttributeValue& value, void* parentToken, void* token)
486  	:
487  	fParentToken(NULL),
488  	fToken(token),
489  	fID(id),
490  	fValue(value)
491  {
492  }
493  
494  
495  status_t
496  ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
497  	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
498  	AttributeHandler** _handler)
499  {
500  	// notify the content handler
501  	void* token;
502  	status_t error = context->lowLevelHandler->HandleAttribute(
503  		(BHPKGAttributeID)id, value, fToken, token);
504  	if (error != B_OK)
505  		return error;
506  
507  	// create a subhandler for the attribute, if it has children
508  	if (_handler != NULL) {
509  		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
510  			fToken, token);
511  		if (*_handler == NULL) {
512  			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
513  				value, fToken, token);
514  			return B_NO_MEMORY;
515  		}
516  		return B_OK;
517  	}
518  
519  	// no children -- just call the done hook
520  	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
521  		value, fToken, token);
522  }
523  
524  
525  status_t
526  ReaderImplBase::LowLevelAttributeHandler::Delete(
527  	AttributeHandlerContext* context)
528  {
529  	status_t error = B_OK;
530  	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
531  		error = context->lowLevelHandler->HandleAttributeDone(
532  			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
533  	}
534  
535  	delete this;
536  	return error;
537  }
538  
539  
540  // #pragma mark - ReaderImplBase
541  
542  
543  ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput)
544  	:
545  	fPackageAttributesSection("package attributes"),
546  	fErrorOutput(errorOutput),
547  	fFD(-1),
548  	fOwnsFD(false),
549  	fCurrentSection(NULL),
550  	fScratchBuffer(NULL),
551  	fScratchBufferSize(0)
552  {
553  }
554  
555  
556  ReaderImplBase::~ReaderImplBase()
557  {
558  	if (fOwnsFD && fFD >= 0)
559  		close(fFD);
560  
561  	delete[] fScratchBuffer;
562  }
563  
564  
565  status_t
566  ReaderImplBase::Init(int fd, bool keepFD)
567  {
568  	fFD = fd;
569  	fOwnsFD = keepFD;
570  
571  	// allocate a scratch buffer
572  	fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
573  	if (fScratchBuffer == NULL) {
574  		fErrorOutput->PrintError("Error: Out of memory!\n");
575  		return B_NO_MEMORY;
576  	}
577  	fScratchBufferSize = kScratchBufferSize;
578  
579  	return B_OK;
580  }
581  
582  
583  const char*
584  ReaderImplBase::CheckCompression(const SectionInfo& section) const
585  {
586  	switch (section.compression) {
587  		case B_HPKG_COMPRESSION_NONE:
588  			if (section.compressedLength != section.uncompressedLength) {
589  				return "Uncompressed, but compressed and uncompressed length "
590  					"don't match";
591  			}
592  			return NULL;
593  
594  		case B_HPKG_COMPRESSION_ZLIB:
595  			if (section.compressedLength >= section.uncompressedLength) {
596  				return "Compressed, but compressed length is not less than "
597  					"uncompressed length";
598  			}
599  			return NULL;
600  
601  		default:
602  			return "Invalid compression algorithm ID";
603  	}
604  }
605  
606  
607  status_t
608  ReaderImplBase::ParseStrings()
609  {
610  	// allocate table, if there are any strings
611  	if (fCurrentSection->stringsCount == 0) {
612  		fCurrentSection->currentOffset += fCurrentSection->stringsLength;
613  		return B_OK;
614  	}
615  
616  	fCurrentSection->strings
617  		= new(std::nothrow) char*[fCurrentSection->stringsCount];
618  	if (fCurrentSection->strings == NULL) {
619  		fErrorOutput->PrintError("Error: Out of memory!\n");
620  		return B_NO_MEMORY;
621  	}
622  
623  	// parse the section and fill the table
624  	char* position
625  		= (char*)fCurrentSection->data + fCurrentSection->currentOffset;
626  	char* sectionEnd = position + fCurrentSection->stringsLength;
627  	uint32 index = 0;
628  	while (true) {
629  		if (position >= sectionEnd) {
630  			fErrorOutput->PrintError("Error: Malformed %s strings section\n",
631  				fCurrentSection->name);
632  			return B_BAD_DATA;
633  		}
634  
635  		size_t stringLength = strnlen(position, (char*)sectionEnd - position);
636  
637  		if (stringLength == 0) {
638  			if (position + 1 != sectionEnd) {
639  				fErrorOutput->PrintError(
640  					"Error: %ld excess bytes in %s strings section\n",
641  					sectionEnd - (position + 1), fCurrentSection->name);
642  				return B_BAD_DATA;
643  			}
644  
645  			if (index != fCurrentSection->stringsCount) {
646  				fErrorOutput->PrintError("Error: Invalid %s strings section: "
647  					"Less strings (%lld) than specified in the header (%lld)\n",
648  					fCurrentSection->name, index,
649  					fCurrentSection->stringsCount);
650  				return B_BAD_DATA;
651  			}
652  
653  			fCurrentSection->currentOffset += fCurrentSection->stringsLength;
654  
655  			return B_OK;
656  		}
657  
658  		if (index >= fCurrentSection->stringsCount) {
659  			fErrorOutput->PrintError("Error: Invalid %s strings section: "
660  				"More strings (%lld) than specified in the header (%lld)\n",
661  				fCurrentSection->name, index, fCurrentSection->stringsCount);
662  			return B_BAD_DATA;
663  		}
664  
665  		fCurrentSection->strings[index++] = position;
666  		position += stringLength + 1;
667  	}
668  }
669  
670  
671  status_t
672  ReaderImplBase::ParsePackageAttributesSection(
673  	AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
674  {
675  	// parse package attributes
676  	SetCurrentSection(&fPackageAttributesSection);
677  
678  	// init the attribute handler stack
679  	rootAttributeHandler->SetLevel(0);
680  	ClearAttributeHandlerStack();
681  	PushAttributeHandler(rootAttributeHandler);
682  
683  	bool sectionHandled;
684  	status_t error = ParseAttributeTree(context, sectionHandled);
685  	if (error == B_OK && sectionHandled) {
686  		if (fPackageAttributesSection.currentOffset
687  				< fPackageAttributesSection.uncompressedLength) {
688  			fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
689  				"attributes section\n",
690  				fPackageAttributesSection.uncompressedLength
691  					- fPackageAttributesSection.currentOffset);
692  			error = B_BAD_DATA;
693  		}
694  	}
695  
696  	SetCurrentSection(NULL);
697  
698  	// clean up on error
699  	if (error != B_OK) {
700  		context->ErrorOccurred();
701  		while (AttributeHandler* handler = PopAttributeHandler()) {
702  			if (handler != rootAttributeHandler)
703  				handler->Delete(context);
704  		}
705  		return error;
706  	}
707  
708  	return B_OK;
709  }
710  
711  
712  status_t
713  ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
714  	bool& _sectionHandled)
715  {
716  	if (context->hasLowLevelHandler) {
717  		bool handleSection = false;
718  		status_t error = context->lowLevelHandler->HandleSectionStart(
719  			context->section, handleSection);
720  		if (error != B_OK)
721  			return error;
722  
723  		if (!handleSection) {
724  			_sectionHandled = false;
725  			return B_OK;
726  		}
727  	}
728  
729  	status_t error = _ParseAttributeTree(context);
730  
731  	if (context->hasLowLevelHandler) {
732  		status_t endError = context->lowLevelHandler->HandleSectionEnd(
733  			context->section);
734  		if (error == B_OK)
735  			error = endError;
736  	}
737  
738  	_sectionHandled = true;
739  	return error;
740  }
741  
742  
743  status_t
744  ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
745  {
746  	int level = 0;
747  
748  	while (true) {
749  		uint8 id;
750  		AttributeValue value;
751  		bool hasChildren;
752  		uint64 tag;
753  
754  		status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
755  		if (error != B_OK)
756  			return error;
757  
758  		if (tag == 0) {
759  			AttributeHandler* handler = PopAttributeHandler();
760  			if (level-- == 0)
761  				return B_OK;
762  
763  			error = handler->Delete(context);
764  			if (error != B_OK)
765  				return error;
766  
767  			continue;
768  		}
769  
770  		AttributeHandler* childHandler = NULL;
771  		error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
772  			hasChildren ? &childHandler : NULL);
773  		if (error != B_OK)
774  			return error;
775  
776  		// parse children
777  		if (hasChildren) {
778  			// create an ignore handler, if necessary
779  			if (childHandler == NULL) {
780  				childHandler = new(std::nothrow) IgnoreAttributeHandler;
781  				if (childHandler == NULL) {
782  					fErrorOutput->PrintError("Error: Out of memory!\n");
783  					return B_NO_MEMORY;
784  				}
785  			}
786  
787  			childHandler->SetLevel(++level);
788  			PushAttributeHandler(childHandler);
789  		}
790  	}
791  }
792  
793  
794  status_t
795  ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
796  	bool* _hasChildren, uint64* _tag)
797  {
798  	uint64 tag;
799  	status_t error = ReadUnsignedLEB128(tag);
800  	if (error != B_OK)
801  		return error;
802  
803  	if (tag != 0) {
804  		// get the type
805  		uint16 type = attribute_tag_type(tag);
806  		if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
807  			fErrorOutput->PrintError("Error: Invalid %s section: attribute "
808  				"type %d not supported!\n", fCurrentSection->name, type);
809  			return B_BAD_DATA;
810  		}
811  
812  		// get the value
813  		error = ReadAttributeValue(type, attribute_tag_encoding(tag),
814  			_value);
815  		if (error != B_OK)
816  			return error;
817  
818  		_id = attribute_tag_id(tag);
819  		if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
820  			fErrorOutput->PrintError("Error: Invalid %s section: "
821  				"attribute id %d not supported!\n", fCurrentSection->name, _id);
822  			return B_BAD_DATA;
823  		}
824  	}
825  
826  	if (_hasChildren != NULL)
827  		*_hasChildren = attribute_tag_has_children(tag);
828  	if (_tag != NULL)
829  		*_tag = tag;
830  
831  	return B_OK;
832  }
833  
834  
835  status_t
836  ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
837  	AttributeValue& _value)
838  {
839  	switch (type) {
840  		case B_HPKG_ATTRIBUTE_TYPE_INT:
841  		case B_HPKG_ATTRIBUTE_TYPE_UINT:
842  		{
843  			uint64 intValue;
844  			status_t error;
845  
846  			switch (encoding) {
847  				case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
848  				{
849  					uint8 value;
850  					error = _Read(value);
851  					intValue = value;
852  					break;
853  				}
854  				case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
855  				{
856  					uint16 value;
857  					error = _Read(value);
858  					intValue = B_BENDIAN_TO_HOST_INT16(value);
859  					break;
860  				}
861  				case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
862  				{
863  					uint32 value;
864  					error = _Read(value);
865  					intValue = B_BENDIAN_TO_HOST_INT32(value);
866  					break;
867  				}
868  				case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
869  				{
870  					uint64 value;
871  					error = _Read(value);
872  					intValue = B_BENDIAN_TO_HOST_INT64(value);
873  					break;
874  				}
875  				default:
876  				{
877  					fErrorOutput->PrintError("Error: Invalid %s section: "
878  						"invalid encoding %d for int value type %d\n",
879  						fCurrentSection->name, encoding, type);
880  					return B_BAD_VALUE;
881  				}
882  			}
883  
884  			if (error != B_OK)
885  				return error;
886  
887  			if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
888  				_value.SetTo((int64)intValue);
889  			else
890  				_value.SetTo(intValue);
891  
892  			return B_OK;
893  		}
894  
895  		case B_HPKG_ATTRIBUTE_TYPE_STRING:
896  		{
897  			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
898  				uint64 index;
899  				status_t error = ReadUnsignedLEB128(index);
900  				if (error != B_OK)
901  					return error;
902  
903  				if (index > fCurrentSection->stringsCount) {
904  					fErrorOutput->PrintError("Error: Invalid %s section: "
905  						"string reference (%lld) out of bounds (%lld)\n",
906  						fCurrentSection->name, index,
907  						fCurrentSection->stringsCount);
908  					return B_BAD_DATA;
909  				}
910  
911  				_value.SetTo(fCurrentSection->strings[index]);
912  			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
913  				const char* string;
914  				status_t error = _ReadString(string);
915  				if (error != B_OK)
916  					return error;
917  
918  				_value.SetTo(string);
919  			} else {
920  				fErrorOutput->PrintError("Error: Invalid %s section: invalid "
921  					"string encoding (%u)\n", fCurrentSection->name, encoding);
922  				return B_BAD_DATA;
923  			}
924  
925  			return B_OK;
926  		}
927  
928  		default:
929  			fErrorOutput->PrintError("Error: Invalid %s section: invalid "
930  				"value type: %d\n", fCurrentSection->name, type);
931  			return B_BAD_DATA;
932  	}
933  }
934  
935  
936  status_t
937  ReaderImplBase::ReadUnsignedLEB128(uint64& _value)
938  {
939  	uint64 result = 0;
940  	int shift = 0;
941  	while (true) {
942  		uint8 byte;
943  		status_t error = _Read(byte);
944  		if (error != B_OK)
945  			return error;
946  
947  		result |= uint64(byte & 0x7f) << shift;
948  		if ((byte & 0x80) == 0)
949  			break;
950  		shift += 7;
951  	}
952  
953  	_value = result;
954  	return B_OK;
955  }
956  
957  
958  status_t
959  ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength)
960  {
961  	const char* string
962  		= (const char*)fCurrentSection->data + fCurrentSection->currentOffset;
963  	size_t stringLength = strnlen(string,
964  		fCurrentSection->uncompressedLength - fCurrentSection->currentOffset);
965  
966  	if (stringLength
967  		== fCurrentSection->uncompressedLength
968  			- fCurrentSection->currentOffset) {
969  		fErrorOutput->PrintError(
970  			"_ReadString(): string extends beyond %s end\n",
971  			fCurrentSection->name);
972  		return B_BAD_DATA;
973  	}
974  
975  	_string = string;
976  	if (_stringLength != NULL)
977  		*_stringLength = stringLength;
978  
979  	fCurrentSection->currentOffset += stringLength + 1;
980  	return B_OK;
981  }
982  
983  
984  status_t
985  ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size)
986  {
987  	if (size > fCurrentSection->uncompressedLength
988  			- fCurrentSection->currentOffset) {
989  		fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n",
990  			size, fCurrentSection->name);
991  		return B_BAD_DATA;
992  	}
993  
994  	memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset,
995  		size);
996  	fCurrentSection->currentOffset += size;
997  	return B_OK;
998  }
999  
1000  
1001  status_t
1002  ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size)
1003  {
1004  	ssize_t bytesRead = pread(fFD, buffer, size, offset);
1005  	if (bytesRead < 0) {
1006  		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1007  			"%s\n", buffer, size, strerror(errno));
1008  		return errno;
1009  	}
1010  	if ((size_t)bytesRead != size) {
1011  		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all "
1012  			"data\n", buffer, size);
1013  		return B_ERROR;
1014  	}
1015  
1016  	return B_OK;
1017  }
1018  
1019  
1020  status_t
1021  ReaderImplBase::ReadCompressedBuffer(const SectionInfo& section)
1022  {
1023  	uint32 compressedSize = section.compressedLength;
1024  	uint64 offset = section.offset;
1025  
1026  	switch (section.compression) {
1027  		case B_HPKG_COMPRESSION_NONE:
1028  			return ReadBuffer(offset, section.data, compressedSize);
1029  
1030  		case B_HPKG_COMPRESSION_ZLIB:
1031  		{
1032  			// create the decompression stream
1033  			BMemoryIO bufferOutput(section.data, section.uncompressedLength);
1034  			BZlibCompressionAlgorithm algorithm;
1035  			BDataIO* zlibOutput;
1036  			status_t error = algorithm.CreateDecompressingOutputStream(
1037  				&bufferOutput, NULL, zlibOutput);
1038  			if (error != B_OK)
1039  				return error;
1040  
1041  			ObjectDeleter<BDataIO> zlibOutputDeleter(zlibOutput);
1042  
1043  			while (compressedSize > 0) {
1044  				// read compressed buffer
1045  				size_t toRead = std::min((size_t)compressedSize,
1046  					fScratchBufferSize);
1047  				error = ReadBuffer(offset, fScratchBuffer, toRead);
1048  				if (error != B_OK)
1049  					return error;
1050  
1051  				// uncompress
1052  				error = zlibOutput->WriteExactly(fScratchBuffer, toRead);
1053  				if (error != B_OK)
1054  					return error;
1055  
1056  				compressedSize -= toRead;
1057  				offset += toRead;
1058  			}
1059  
1060  			error = zlibOutput->Flush();
1061  			if (error != B_OK)
1062  				return error;
1063  
1064  			// verify that all data have been read
1065  			if ((uint64)bufferOutput.Position() != section.uncompressedLength) {
1066  				fErrorOutput->PrintError("Error: Missing bytes in uncompressed "
1067  					"buffer!\n");
1068  				return B_BAD_DATA;
1069  			}
1070  
1071  			return B_OK;
1072  		}
1073  
1074  		default:
1075  		{
1076  			fErrorOutput->PrintError("Error: Invalid compression type: %u\n",
1077  				section.compression);
1078  			return B_BAD_DATA;
1079  		}
1080  	}
1081  }
1082  
1083  
1084  }	// namespace BPrivate
1085  
1086  }	// namespace V1
1087  
1088  }	// namespace BHPKG
1089  
1090  }	// namespace BPackageKit
1091