xref: /haiku/headers/private/package/hpkg/ReaderImplBase.h (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 #ifndef _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
7 #define _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
8 
9 
10 #include <errno.h>
11 #include <sys/stat.h>
12 
13 #include <ByteOrder.h>
14 #include <DataIO.h>
15 
16 #include <Array.h>
17 #include <util/BumpAllocator.h>
18 #include <util/SinglyLinkedList.h>
19 
20 #include <package/hpkg/ErrorOutput.h>
21 #include <package/hpkg/PackageAttributeValue.h>
22 #include <package/hpkg/PackageContentHandler.h>
23 #include <package/hpkg/PackageInfoAttributeValue.h>
24 
25 
26 class BCompressionAlgorithm;
27 class BDecompressionParameters;
28 
29 
30 namespace BPackageKit {
31 
32 namespace BHPKG {
33 
34 
35 class BAbstractBufferedDataReader;
36 class BErrorOutput;
37 
38 
39 namespace BPrivate {
40 
41 
42 class PackageFileHeapReader;
43 
44 
45 struct PackageFileSection {
46 	uint32			uncompressedLength;
47 	uint8*			data;
48 	uint64			offset;
49 	uint64			currentOffset;
50 	uint64			stringsLength;
51 	uint64			stringsCount;
52 	char**			strings;
53 	const char*		name;
54 
55 	PackageFileSection(const char* _name)
56 		:
57 		data(NULL),
58 		strings(NULL),
59 		name(_name)
60 	{
61 	}
62 
63 	~PackageFileSection()
64 	{
65 		delete[] strings;
66 		delete[] data;
67 	}
68 };
69 
70 
71 class ReaderImplBase {
72 public:
73 	inline	const PackageFileSection& PackageAttributesSection() const
74 									{ return fPackageAttributesSection; }
75 
76 protected:
77 								ReaderImplBase(const char* fileType,
78 									BErrorOutput* errorOutput);
79 	virtual						~ReaderImplBase();
80 
81 			BPositionIO*		File() const;
82 
83 			BErrorOutput*		ErrorOutput() const;
84 
85 			uint16				MinorFormatVersion() const
86 									{ return fMinorFormatVersion; }
87 
88 			uint64				UncompressedHeapSize() const;
89 
90 			PackageFileHeapReader* RawHeapReader() const
91 									{ return fRawHeapReader; }
92 			BAbstractBufferedDataReader* HeapReader() const
93 									{ return fHeapReader; }
94 									// equals RawHeapReader(), if uncached
95 
96 			BAbstractBufferedDataReader* DetachHeapReader(
97 									PackageFileHeapReader*& _rawHeapReader);
98 									// Detaches both raw and (if applicable)
99 									// cached heap reader. The called gains
100 									// ownership of both. The file may need to
101 									// be set on the raw heap reader, if it
102 									// shall be used after destroying this
103 									// object and Init() has been called with
104 									// keepFile == true.
105 
106 protected:
107 			class AttributeHandlerContext;
108 			class AttributeHandler;
109 			class IgnoreAttributeHandler;
110 			class PackageInfoAttributeHandlerBase;
111 			class PackageVersionAttributeHandler;
112 			class PackageResolvableAttributeHandler;
113 			class PackageResolvableExpressionAttributeHandler;
114 			class GlobalWritableFileInfoAttributeHandler;
115 			class UserSettingsFileInfoAttributeHandler;
116 			class UserAttributeHandler;
117 			class PackageAttributeHandler;
118 			class LowLevelAttributeHandler;
119 
120 			typedef BPackageAttributeValue AttributeValue;
121 			typedef SinglyLinkedList<AttributeHandler> AttributeHandlerList;
122 
123 protected:
124 			template<typename Header, uint32 kMagic, uint16 kVersion,
125 				uint16 kMinorVersion>
126 			status_t			Init(BPositionIO* file, bool keepFile,
127 									Header& header, uint32 flags);
128 			status_t			InitHeapReader(uint32 compression,
129 									uint32 chunkSize, off_t offset,
130 									uint64 compressedSize,
131 									uint64 uncompressedSize);
132 	virtual	status_t			CreateCachedHeapReader(
133 									PackageFileHeapReader* heapReader,
134 									BAbstractBufferedDataReader*&
135 										_cachedReader);
136 			status_t			InitSection(PackageFileSection& section,
137 									uint64 endOffset, uint64 length,
138 									uint64 maxSaneLength, uint64 stringsLength,
139 									uint64 stringsCount);
140 			status_t			PrepareSection(PackageFileSection& section);
141 
142 			status_t			ParseStrings();
143 
144 			status_t			ParsePackageAttributesSection(
145 									AttributeHandlerContext* context,
146 									AttributeHandler* rootAttributeHandler);
147 			status_t			ParseAttributeTree(
148 									AttributeHandlerContext* context,
149 									bool& _sectionHandled);
150 
151 	virtual	status_t			ReadAttributeValue(uint8 type, uint8 encoding,
152 									AttributeValue& _value);
153 
154 			status_t			ReadUnsignedLEB128(uint64& _value);
155 
156 			status_t			ReadBuffer(off_t offset, void* buffer,
157 									size_t size);
158 			status_t			ReadSection(const PackageFileSection& section);
159 
160 	inline	AttributeHandler*	CurrentAttributeHandler() const;
161 	inline	void				PushAttributeHandler(
162 									AttributeHandler* handler);
163 	inline	AttributeHandler*	PopAttributeHandler();
164 	inline	void				ClearAttributeHandlerStack();
165 
166 	inline	PackageFileSection*	CurrentSection();
167 	inline	void				SetCurrentSection(PackageFileSection* section);
168 
169 protected:
170 			PackageFileSection	fPackageAttributesSection;
171 
172 private:
173 			status_t			_Init(BPositionIO* file, bool keepFile);
174 
175 			status_t			_ParseAttributeTree(
176 									AttributeHandlerContext* context);
177 
178 	template<typename Type>
179 	inline	status_t			_Read(Type& _value);
180 
181 			status_t			_ReadSectionBuffer(void* buffer, size_t size);
182 
183 			status_t			_ReadAttribute(uint8& _id,
184 									AttributeValue& _value,
185 									bool* _hasChildren = NULL,
186 									uint64* _tag = NULL);
187 
188 			status_t			_ReadString(const char*& _string,
189 									size_t* _stringLength = NULL);
190 
191 private:
192 			const char*			fFileType;
193 			BErrorOutput*		fErrorOutput;
194 			BPositionIO*		fFile;
195 			bool				fOwnsFile;
196 			uint16				fMinorFormatVersion;
197 			uint16				fCurrentMinorFormatVersion;
198 
199 			PackageFileHeapReader* fRawHeapReader;
200 			BAbstractBufferedDataReader* fHeapReader;
201 
202 			PackageFileSection*	fCurrentSection;
203 
204 			AttributeHandlerList fAttributeHandlerStack;
205 };
206 
207 
208 // #pragma mark - attribute handlers
209 
210 
211 class ReaderImplBase::AttributeHandlerContext {
212 public:
213 			BErrorOutput*			errorOutput;
214 			union {
215 				BPackageContentHandler*			packageContentHandler;
216 				BLowLevelPackageContentHandler*	lowLevelHandler;
217 			};
218 			bool					hasLowLevelHandler;
219 			bool					ignoreUnknownAttributes;
220 
221 			BHPKGPackageSectionID	section;
222 
223 			BumpAllocator<>			handlersAllocator;
224 
225 public:
226 								AttributeHandlerContext(
227 									BErrorOutput* errorOutput,
228 									BPackageContentHandler*
229 										packageContentHandler,
230 									BHPKGPackageSectionID section,
231 									bool ignoreUnknownAttributes);
232 								AttributeHandlerContext(
233 									BErrorOutput* errorOutput,
234 									BLowLevelPackageContentHandler*
235 										lowLevelHandler,
236 									BHPKGPackageSectionID section,
237 									bool ignoreUnknownAttributes);
238 								~AttributeHandlerContext();
239 
240 			void				ErrorOccurred();
241 };
242 
243 
244 class ReaderImplBase::AttributeHandler
245 	: public SinglyLinkedListLinkImpl<AttributeHandler> {
246 public:
247 			void*				operator new(size_t size, AttributeHandlerContext* context);
248 			void				operator delete(void* pointer);
249 
250 	virtual						~AttributeHandler();
251 
252 			void				SetLevel(int level);
253 	virtual	status_t			HandleAttribute(
254 									AttributeHandlerContext* context, uint8 id,
255 									const AttributeValue& value,
256 									AttributeHandler** _handler);
257 
258 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
259 
260 	virtual	status_t			Delete(AttributeHandlerContext* context);
261 
262 protected:
263 			int					fLevel;
264 
265 private:
266 			bool				fDeleting;
267 };
268 
269 
270 class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler {
271 };
272 
273 
274 class ReaderImplBase::PackageInfoAttributeHandlerBase
275 	: public AttributeHandler {
276 private:
277 	typedef	AttributeHandler	super;
278 public:
279 								PackageInfoAttributeHandlerBase(
280 									BPackageInfoAttributeValue&
281 										packageInfoValue);
282 
283 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
284 
285 protected:
286 			BPackageInfoAttributeValue& fPackageInfoValue;
287 };
288 
289 
290 class ReaderImplBase::PackageVersionAttributeHandler
291 	: public PackageInfoAttributeHandlerBase {
292 private:
293 	typedef	PackageInfoAttributeHandlerBase	super;
294 public:
295 								PackageVersionAttributeHandler(
296 									BPackageInfoAttributeValue&
297 										packageInfoValue,
298 									BPackageVersionData& versionData,
299 									bool notify);
300 
301 	virtual	status_t			HandleAttribute(
302 									AttributeHandlerContext* context, uint8 id,
303 									const AttributeValue& value,
304 									AttributeHandler** _handler);
305 
306 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
307 
308 private:
309 			BPackageVersionData& fPackageVersionData;
310 			bool				fNotify;
311 };
312 
313 
314 class ReaderImplBase::PackageResolvableAttributeHandler
315 	: public PackageInfoAttributeHandlerBase {
316 private:
317 	typedef	PackageInfoAttributeHandlerBase	super;
318 public:
319 								PackageResolvableAttributeHandler(
320 									BPackageInfoAttributeValue&
321 										packageInfoValue);
322 
323 	virtual	status_t			HandleAttribute(
324 									AttributeHandlerContext* context, uint8 id,
325 									const AttributeValue& value,
326 									AttributeHandler** _handler);
327 };
328 
329 
330 class ReaderImplBase::PackageResolvableExpressionAttributeHandler
331 	: public PackageInfoAttributeHandlerBase {
332 private:
333 	typedef	PackageInfoAttributeHandlerBase	super;
334 public:
335 								PackageResolvableExpressionAttributeHandler(
336 									BPackageInfoAttributeValue&
337 										packageInfoValue);
338 
339 	virtual	status_t			HandleAttribute(
340 									AttributeHandlerContext* context, uint8 id,
341 									const AttributeValue& value,
342 									AttributeHandler** _handler);
343 };
344 
345 
346 class ReaderImplBase::GlobalWritableFileInfoAttributeHandler
347 	: public PackageInfoAttributeHandlerBase {
348 private:
349 	typedef	PackageInfoAttributeHandlerBase	super;
350 public:
351 								GlobalWritableFileInfoAttributeHandler(
352 									BPackageInfoAttributeValue&
353 										packageInfoValue);
354 
355 	virtual	status_t			HandleAttribute(
356 									AttributeHandlerContext* context, uint8 id,
357 									const AttributeValue& value,
358 									AttributeHandler** _handler);
359 };
360 
361 
362 class ReaderImplBase::UserSettingsFileInfoAttributeHandler
363 	: public PackageInfoAttributeHandlerBase {
364 private:
365 	typedef	PackageInfoAttributeHandlerBase	super;
366 public:
367 								UserSettingsFileInfoAttributeHandler(
368 									BPackageInfoAttributeValue&
369 										packageInfoValue);
370 
371 	virtual	status_t			HandleAttribute(
372 									AttributeHandlerContext* context, uint8 id,
373 									const AttributeValue& value,
374 									AttributeHandler** _handler);
375 };
376 
377 
378 class ReaderImplBase::UserAttributeHandler
379 	: public PackageInfoAttributeHandlerBase {
380 private:
381 	typedef	PackageInfoAttributeHandlerBase	super;
382 public:
383 								UserAttributeHandler(
384 									BPackageInfoAttributeValue&
385 										packageInfoValue);
386 
387 	virtual	status_t			HandleAttribute(
388 									AttributeHandlerContext* context, uint8 id,
389 									const AttributeValue& value,
390 									AttributeHandler** _handler);
391 
392 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
393 
394 private:
395 			Array<const char*>	fGroups;
396 };
397 
398 
399 class ReaderImplBase::PackageAttributeHandler : public AttributeHandler {
400 private:
401 	typedef	AttributeHandler	super;
402 public:
403 	virtual	status_t			HandleAttribute(
404 									AttributeHandlerContext* context, uint8 id,
405 									const AttributeValue& value,
406 									AttributeHandler** _handler);
407 
408 private:
409 			BPackageInfoAttributeValue fPackageInfoValue;
410 };
411 
412 
413 class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler {
414 private:
415 	typedef	AttributeHandler	super;
416 public:
417 								LowLevelAttributeHandler();
418 								LowLevelAttributeHandler(uint8 id,
419 									const BPackageAttributeValue& value,
420 									void* parentToken, void* token);
421 
422 	virtual	status_t			HandleAttribute(
423 									AttributeHandlerContext* context, uint8 id,
424 									const AttributeValue& value,
425 									AttributeHandler** _handler);
426 
427 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
428 
429 private:
430 			void*				fParentToken;
431 			void*				fToken;
432 			uint8				fID;
433 			AttributeValue		fValue;
434 };
435 
436 
437 // #pragma mark - template and inline methods
438 
439 
440 template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion>
441 status_t
442 ReaderImplBase::Init(BPositionIO* file, bool keepFile, Header& header, uint32 flags)
443 {
444 	status_t error = _Init(file, keepFile);
445 	if (error != B_OK)
446 		return error;
447 
448 	// get the file size
449 	off_t fileSize;
450 	error = fFile->GetSize(&fileSize);
451 	if (error != B_OK) {
452 		if (error != B_NOT_SUPPORTED) {
453 			ErrorOutput()->PrintError(
454 				"Error: Failed to get size of %s file: %s\n",
455 				fFileType, strerror(error));
456 			return error;
457 		}
458 
459 		// Might be a stream. We only use the file size for checking the total
460 		// heap size, which we don't have to do.
461 		fileSize = -1;
462 	}
463 
464 	// validate file is longer than header (when not a stream)
465 	if (fileSize >= 0 && fileSize < (off_t)sizeof(header)) {
466 		ErrorOutput()->PrintError("Error: Invalid %s file: Length shorter than "
467 			"header!\n", fFileType);
468 		return B_BAD_DATA;
469 	}
470 
471 	// read the header
472 	if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK)
473 		return error;
474 
475 	// check the header
476 
477 	// magic
478 	if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) {
479 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid "
480 			"magic\n", fFileType);
481 		return B_BAD_DATA;
482 	}
483 
484 	// version
485 	if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) {
486 		if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) {
487 			ErrorOutput()->PrintError("Error: Invalid/unsupported %s file "
488 				"version (%d)\n", fFileType,
489 				B_BENDIAN_TO_HOST_INT16(header.version));
490 		}
491 		return B_MISMATCHED_VALUES;
492 	}
493 
494 	fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version);
495 	fCurrentMinorFormatVersion = kMinorVersion;
496 
497 	// header size
498 	uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
499 	if (heapOffset < (off_t)sizeof(header)) {
500 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header "
501 			"size (%" B_PRIu64 ")\n", fFileType, heapOffset);
502 		return B_BAD_DATA;
503 	}
504 
505 	// total size
506 	uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
507 	if (fileSize >= 0 && totalSize != (uint64)fileSize) {
508 		ErrorOutput()->PrintError("Error: Invalid %s file: Total size in "
509 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
510 			B_PRIdOFF ")\n", fFileType, totalSize, fileSize);
511 		return B_BAD_DATA;
512 	}
513 
514 	// heap size
515 	uint64 compressedHeapSize
516 		= B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed);
517 	if (compressedHeapSize > totalSize
518 		|| heapOffset > totalSize - compressedHeapSize) {
519 		ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in "
520 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
521 			B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType,
522 			compressedHeapSize, totalSize, heapOffset);
523 		return B_BAD_DATA;
524 	}
525 
526 	error = InitHeapReader(
527 		B_BENDIAN_TO_HOST_INT16(header.heap_compression),
528 		B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset,
529 		compressedHeapSize,
530 		B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed));
531 	if (error != B_OK)
532 		return error;
533 
534 	return B_OK;
535 }
536 
537 
538 inline BPositionIO*
539 ReaderImplBase::File() const
540 {
541 	return fFile;
542 }
543 
544 
545 inline BErrorOutput*
546 ReaderImplBase::ErrorOutput() const
547 {
548 	return fErrorOutput;
549 }
550 
551 
552 PackageFileSection*
553 ReaderImplBase::CurrentSection()
554 {
555 	return fCurrentSection;
556 }
557 
558 
559 void
560 ReaderImplBase::SetCurrentSection(PackageFileSection* section)
561 {
562 	fCurrentSection = section;
563 }
564 
565 
566 template<typename Type>
567 status_t
568 ReaderImplBase::_Read(Type& _value)
569 {
570 	return _ReadSectionBuffer(&_value, sizeof(Type));
571 }
572 
573 
574 inline ReaderImplBase::AttributeHandler*
575 ReaderImplBase::CurrentAttributeHandler() const
576 {
577 	return fAttributeHandlerStack.Head();
578 }
579 
580 
581 inline void
582 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler)
583 {
584 	fAttributeHandlerStack.Add(handler);
585 }
586 
587 
588 inline ReaderImplBase::AttributeHandler*
589 ReaderImplBase::PopAttributeHandler()
590 {
591 	return fAttributeHandlerStack.RemoveHead();
592 }
593 
594 
595 inline void
596 ReaderImplBase::ClearAttributeHandlerStack()
597 {
598 	fAttributeHandlerStack.MakeEmpty();
599 }
600 
601 
602 }	// namespace BPrivate
603 
604 }	// namespace BHPKG
605 
606 }	// namespace BPackageKit
607 
608 
609 #endif	// _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
610