xref: /haiku/headers/private/package/hpkg/ReaderImplBase.h (revision a629567a9001547736cfe892cdf992be16868fed)
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 
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 			int					FD() 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 										= NULL);
98 									// Detaches both raw and (if applicable)
99 									// cached heap reader. The called gains
100 									// ownership. The FD may need to be set on
101 									// the raw heap reader, if it shall be used
102 									// after destroying this object and Init()
103 									// has been called with keepFD == 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(int fd, bool keepFD, Header& header,
126 									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(int fd, bool keepFD);
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 			int					fFD;
194 			bool				fOwnsFD;
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(int fd, bool keepFD, Header& header, uint32 flags)
433 {
434 	status_t error = _Init(fd, keepFD);
435 	if (error != B_OK)
436 		return error;
437 
438 	// stat the file
439 	struct stat st;
440 	if (fstat(FD(), &st) < 0) {
441 		ErrorOutput()->PrintError("Error: Failed to access %s file: %s\n",
442 			fFileType, strerror(errno));
443 		return errno;
444 	}
445 
446 	// read the header
447 	if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK)
448 		return error;
449 
450 	// check the header
451 
452 	// magic
453 	if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) {
454 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid "
455 			"magic\n", fFileType);
456 		return B_BAD_DATA;
457 	}
458 
459 	// version
460 	if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) {
461 		if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) {
462 			ErrorOutput()->PrintError("Error: Invalid/unsupported %s file "
463 				"version (%d)\n", fFileType,
464 				B_BENDIAN_TO_HOST_INT16(header.version));
465 		}
466 		return B_MISMATCHED_VALUES;
467 	}
468 
469 	fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version);
470 	fCurrentMinorFormatVersion = kMinorVersion;
471 
472 	// header size
473 	uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
474 	if (heapOffset < (off_t)sizeof(header)) {
475 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header "
476 			"size (%" B_PRIu64 ")\n", fFileType, heapOffset);
477 		return B_BAD_DATA;
478 	}
479 
480 	// total size
481 	uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
482 	if (totalSize != (uint64)st.st_size) {
483 		ErrorOutput()->PrintError("Error: Invalid %s file: Total size in "
484 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
485 			B_PRIdOFF ")\n", fFileType, totalSize, st.st_size);
486 		return B_BAD_DATA;
487 	}
488 
489 	// heap size
490 	uint64 compressedHeapSize
491 		= B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed);
492 	if (compressedHeapSize > totalSize
493 		|| heapOffset > totalSize - compressedHeapSize) {
494 		ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in "
495 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
496 			B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType,
497 			compressedHeapSize, totalSize, heapOffset);
498 		return B_BAD_DATA;
499 	}
500 
501 	error = InitHeapReader(
502 		B_BENDIAN_TO_HOST_INT16(header.heap_compression),
503 		B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset,
504 		compressedHeapSize,
505 		B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed));
506 	if (error != B_OK)
507 		return error;
508 
509 	return B_OK;
510 }
511 
512 
513 inline int
514 ReaderImplBase::FD() const
515 {
516 	return fFD;
517 }
518 
519 
520 inline BErrorOutput*
521 ReaderImplBase::ErrorOutput() const
522 {
523 	return fErrorOutput;
524 }
525 
526 
527 PackageFileSection*
528 ReaderImplBase::CurrentSection()
529 {
530 	return fCurrentSection;
531 }
532 
533 
534 void
535 ReaderImplBase::SetCurrentSection(PackageFileSection* section)
536 {
537 	fCurrentSection = section;
538 }
539 
540 
541 template<typename Type>
542 status_t
543 ReaderImplBase::_Read(Type& _value)
544 {
545 	return _ReadSectionBuffer(&_value, sizeof(Type));
546 }
547 
548 
549 inline ReaderImplBase::AttributeHandler*
550 ReaderImplBase::CurrentAttributeHandler() const
551 {
552 	return fAttributeHandlerStack.Head();
553 }
554 
555 
556 inline void
557 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler)
558 {
559 	fAttributeHandlerStack.Add(handler);
560 }
561 
562 
563 inline ReaderImplBase::AttributeHandler*
564 ReaderImplBase::PopAttributeHandler()
565 {
566 	return fAttributeHandlerStack.RemoveHead();
567 }
568 
569 
570 inline void
571 ReaderImplBase::ClearAttributeHandlerStack()
572 {
573 	fAttributeHandlerStack.MakeEmpty();
574 }
575 
576 
577 }	// namespace BPrivate
578 
579 }	// namespace BHPKG
580 
581 }	// namespace BPackageKit
582 
583 
584 #endif	// _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
585