xref: /haiku/headers/private/package/hpkg/ReaderImplBase.h (revision 6a89a36aa0ce6a53f9758ba767863ac6b4c6156c)
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 namespace BPackageKit {
26 
27 namespace BHPKG {
28 
29 
30 class BAbstractBufferedDataReader;
31 class BErrorOutput;
32 
33 
34 namespace BPrivate {
35 
36 
37 class PackageFileHeapReader;
38 
39 
40 struct 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 
66 class ReaderImplBase {
67 public:
68 	inline	const PackageFileSection& PackageAttributesSection() const
69 									{ return fPackageAttributesSection; }
70 
71 protected:
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 
101 protected:
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 
118 protected:
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 
164 protected:
165 			PackageFileSection	fPackageAttributesSection;
166 
167 private:
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 
186 private:
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 
206 class ReaderImplBase::AttributeHandlerContext {
207 public:
208 			BErrorOutput*			errorOutput;
209 			union {
210 				BPackageContentHandler*			packageContentHandler;
211 				BLowLevelPackageContentHandler*	lowLevelHandler;
212 			};
213 			bool					hasLowLevelHandler;
214 			bool					ignoreUnknownAttributes;
215 
216 			BHPKGPackageSectionID	section;
217 
218 public:
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 
236 class ReaderImplBase::AttributeHandler
237 	: public SinglyLinkedListLinkImpl<AttributeHandler> {
238 public:
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 
251 protected:
252 			int					fLevel;
253 };
254 
255 
256 class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler {
257 };
258 
259 
260 class ReaderImplBase::PackageInfoAttributeHandlerBase
261 	: public AttributeHandler {
262 private:
263 	typedef	AttributeHandler	super;
264 public:
265 								PackageInfoAttributeHandlerBase(
266 									BPackageInfoAttributeValue&
267 										packageInfoValue);
268 
269 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
270 
271 protected:
272 			BPackageInfoAttributeValue& fPackageInfoValue;
273 };
274 
275 
276 class ReaderImplBase::PackageVersionAttributeHandler
277 	: public PackageInfoAttributeHandlerBase {
278 private:
279 	typedef	PackageInfoAttributeHandlerBase	super;
280 public:
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 
294 private:
295 			BPackageVersionData& fPackageVersionData;
296 			bool				fNotify;
297 };
298 
299 
300 class ReaderImplBase::PackageResolvableAttributeHandler
301 	: public PackageInfoAttributeHandlerBase {
302 private:
303 	typedef	PackageInfoAttributeHandlerBase	super;
304 public:
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 
316 class ReaderImplBase::PackageResolvableExpressionAttributeHandler
317 	: public PackageInfoAttributeHandlerBase {
318 private:
319 	typedef	PackageInfoAttributeHandlerBase	super;
320 public:
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 
332 class ReaderImplBase::GlobalWritableFileInfoAttributeHandler
333 	: public PackageInfoAttributeHandlerBase {
334 private:
335 	typedef	PackageInfoAttributeHandlerBase	super;
336 public:
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 
348 class ReaderImplBase::UserSettingsFileInfoAttributeHandler
349 	: public PackageInfoAttributeHandlerBase {
350 private:
351 	typedef	PackageInfoAttributeHandlerBase	super;
352 public:
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 
364 class ReaderImplBase::UserAttributeHandler
365 	: public PackageInfoAttributeHandlerBase {
366 private:
367 	typedef	PackageInfoAttributeHandlerBase	super;
368 public:
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 
380 private:
381 			Array<const char*>	fGroups;
382 };
383 
384 
385 class ReaderImplBase::PackageAttributeHandler : public AttributeHandler {
386 private:
387 	typedef	AttributeHandler	super;
388 public:
389 	virtual	status_t			HandleAttribute(
390 									AttributeHandlerContext* context, uint8 id,
391 									const AttributeValue& value,
392 									AttributeHandler** _handler);
393 
394 private:
395 			BPackageInfoAttributeValue fPackageInfoValue;
396 };
397 
398 
399 class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler {
400 private:
401 	typedef	AttributeHandler	super;
402 public:
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 
415 private:
416 			void*				fParentToken;
417 			void*				fToken;
418 			uint8				fID;
419 			AttributeValue		fValue;
420 };
421 
422 
423 // #pragma mark - template and inline methods
424 
425 
426 template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion>
427 status_t
428 ReaderImplBase::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 
509 inline int
510 ReaderImplBase::FD() const
511 {
512 	return fFD;
513 }
514 
515 
516 inline BErrorOutput*
517 ReaderImplBase::ErrorOutput() const
518 {
519 	return fErrorOutput;
520 }
521 
522 
523 PackageFileSection*
524 ReaderImplBase::CurrentSection()
525 {
526 	return fCurrentSection;
527 }
528 
529 
530 void
531 ReaderImplBase::SetCurrentSection(PackageFileSection* section)
532 {
533 	fCurrentSection = section;
534 }
535 
536 
537 template<typename Type>
538 status_t
539 ReaderImplBase::_Read(Type& _value)
540 {
541 	return _ReadSectionBuffer(&_value, sizeof(Type));
542 }
543 
544 
545 inline ReaderImplBase::AttributeHandler*
546 ReaderImplBase::CurrentAttributeHandler() const
547 {
548 	return fAttributeHandlerStack.Head();
549 }
550 
551 
552 inline void
553 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler)
554 {
555 	fAttributeHandlerStack.Add(handler);
556 }
557 
558 
559 inline ReaderImplBase::AttributeHandler*
560 ReaderImplBase::PopAttributeHandler()
561 {
562 	return fAttributeHandlerStack.RemoveHead();
563 }
564 
565 
566 inline void
567 ReaderImplBase::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