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