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