xref: /haiku/headers/private/package/hpkg/ReaderImplBase.h (revision 986e4abce4efeccd9418eb8cdc7a710487f093b9)
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 			uint8*				fScratchBuffer;
202 			size_t				fScratchBufferSize;
203 };
204 
205 
206 // #pragma mark - attribute handlers
207 
208 
209 class ReaderImplBase::AttributeHandlerContext {
210 public:
211 			BErrorOutput*			errorOutput;
212 			union {
213 				BPackageContentHandler*			packageContentHandler;
214 				BLowLevelPackageContentHandler*	lowLevelHandler;
215 			};
216 			bool					hasLowLevelHandler;
217 			bool					ignoreUnknownAttributes;
218 
219 			BHPKGPackageSectionID	section;
220 
221 public:
222 								AttributeHandlerContext(
223 									BErrorOutput* errorOutput,
224 									BPackageContentHandler*
225 										packageContentHandler,
226 									BHPKGPackageSectionID section,
227 									bool ignoreUnknownAttributes);
228 								AttributeHandlerContext(
229 									BErrorOutput* errorOutput,
230 									BLowLevelPackageContentHandler*
231 										lowLevelHandler,
232 									BHPKGPackageSectionID section,
233 									bool ignoreUnknownAttributes);
234 
235 			void				ErrorOccurred();
236 };
237 
238 
239 class ReaderImplBase::AttributeHandler
240 	: public SinglyLinkedListLinkImpl<AttributeHandler> {
241 public:
242 	virtual						~AttributeHandler();
243 
244 			void				SetLevel(int level);
245 	virtual	status_t			HandleAttribute(
246 									AttributeHandlerContext* context, uint8 id,
247 									const AttributeValue& value,
248 									AttributeHandler** _handler);
249 
250 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
251 
252 	virtual	status_t			Delete(AttributeHandlerContext* context);
253 
254 protected:
255 			int					fLevel;
256 };
257 
258 
259 class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler {
260 };
261 
262 
263 class ReaderImplBase::PackageInfoAttributeHandlerBase
264 	: public AttributeHandler {
265 private:
266 	typedef	AttributeHandler	super;
267 public:
268 								PackageInfoAttributeHandlerBase(
269 									BPackageInfoAttributeValue&
270 										packageInfoValue);
271 
272 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
273 
274 protected:
275 			BPackageInfoAttributeValue& fPackageInfoValue;
276 };
277 
278 
279 class ReaderImplBase::PackageVersionAttributeHandler
280 	: public PackageInfoAttributeHandlerBase {
281 private:
282 	typedef	PackageInfoAttributeHandlerBase	super;
283 public:
284 								PackageVersionAttributeHandler(
285 									BPackageInfoAttributeValue&
286 										packageInfoValue,
287 									BPackageVersionData& versionData,
288 									bool notify);
289 
290 	virtual	status_t			HandleAttribute(
291 									AttributeHandlerContext* context, uint8 id,
292 									const AttributeValue& value,
293 									AttributeHandler** _handler);
294 
295 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
296 
297 private:
298 			BPackageVersionData& fPackageVersionData;
299 			bool				fNotify;
300 };
301 
302 
303 class ReaderImplBase::PackageResolvableAttributeHandler
304 	: public PackageInfoAttributeHandlerBase {
305 private:
306 	typedef	PackageInfoAttributeHandlerBase	super;
307 public:
308 								PackageResolvableAttributeHandler(
309 									BPackageInfoAttributeValue&
310 										packageInfoValue);
311 
312 	virtual	status_t			HandleAttribute(
313 									AttributeHandlerContext* context, uint8 id,
314 									const AttributeValue& value,
315 									AttributeHandler** _handler);
316 };
317 
318 
319 class ReaderImplBase::PackageResolvableExpressionAttributeHandler
320 	: public PackageInfoAttributeHandlerBase {
321 private:
322 	typedef	PackageInfoAttributeHandlerBase	super;
323 public:
324 								PackageResolvableExpressionAttributeHandler(
325 									BPackageInfoAttributeValue&
326 										packageInfoValue);
327 
328 	virtual	status_t			HandleAttribute(
329 									AttributeHandlerContext* context, uint8 id,
330 									const AttributeValue& value,
331 									AttributeHandler** _handler);
332 };
333 
334 
335 class ReaderImplBase::GlobalWritableFileInfoAttributeHandler
336 	: public PackageInfoAttributeHandlerBase {
337 private:
338 	typedef	PackageInfoAttributeHandlerBase	super;
339 public:
340 								GlobalWritableFileInfoAttributeHandler(
341 									BPackageInfoAttributeValue&
342 										packageInfoValue);
343 
344 	virtual	status_t			HandleAttribute(
345 									AttributeHandlerContext* context, uint8 id,
346 									const AttributeValue& value,
347 									AttributeHandler** _handler);
348 };
349 
350 
351 class ReaderImplBase::UserSettingsFileInfoAttributeHandler
352 	: public PackageInfoAttributeHandlerBase {
353 private:
354 	typedef	PackageInfoAttributeHandlerBase	super;
355 public:
356 								UserSettingsFileInfoAttributeHandler(
357 									BPackageInfoAttributeValue&
358 										packageInfoValue);
359 
360 	virtual	status_t			HandleAttribute(
361 									AttributeHandlerContext* context, uint8 id,
362 									const AttributeValue& value,
363 									AttributeHandler** _handler);
364 };
365 
366 
367 class ReaderImplBase::UserAttributeHandler
368 	: public PackageInfoAttributeHandlerBase {
369 private:
370 	typedef	PackageInfoAttributeHandlerBase	super;
371 public:
372 								UserAttributeHandler(
373 									BPackageInfoAttributeValue&
374 										packageInfoValue);
375 
376 	virtual	status_t			HandleAttribute(
377 									AttributeHandlerContext* context, uint8 id,
378 									const AttributeValue& value,
379 									AttributeHandler** _handler);
380 
381 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
382 
383 private:
384 			Array<const char*>	fGroups;
385 };
386 
387 
388 class ReaderImplBase::PackageAttributeHandler : public AttributeHandler {
389 private:
390 	typedef	AttributeHandler	super;
391 public:
392 	virtual	status_t			HandleAttribute(
393 									AttributeHandlerContext* context, uint8 id,
394 									const AttributeValue& value,
395 									AttributeHandler** _handler);
396 
397 private:
398 			BPackageInfoAttributeValue fPackageInfoValue;
399 };
400 
401 
402 class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler {
403 private:
404 	typedef	AttributeHandler	super;
405 public:
406 								LowLevelAttributeHandler();
407 								LowLevelAttributeHandler(uint8 id,
408 									const BPackageAttributeValue& value,
409 									void* parentToken, void* token);
410 
411 	virtual	status_t			HandleAttribute(
412 									AttributeHandlerContext* context, uint8 id,
413 									const AttributeValue& value,
414 									AttributeHandler** _handler);
415 
416 	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
417 
418 private:
419 			void*				fParentToken;
420 			void*				fToken;
421 			uint8				fID;
422 			AttributeValue		fValue;
423 };
424 
425 
426 // #pragma mark - template and inline methods
427 
428 
429 template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion>
430 status_t
431 ReaderImplBase::Init(int fd, bool keepFD, Header& header, uint32 flags)
432 {
433 	status_t error = _Init(fd, keepFD);
434 	if (error != B_OK)
435 		return error;
436 
437 	// stat the file
438 	struct stat st;
439 	if (fstat(FD(), &st) < 0) {
440 		ErrorOutput()->PrintError("Error: Failed to access %s file: %s\n",
441 			fFileType, strerror(errno));
442 		return errno;
443 	}
444 
445 	// read the header
446 	if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK)
447 		return error;
448 
449 	// check the header
450 
451 	// magic
452 	if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) {
453 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid "
454 			"magic\n", fFileType);
455 		return B_BAD_DATA;
456 	}
457 
458 	// version
459 	if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) {
460 		if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) {
461 			ErrorOutput()->PrintError("Error: Invalid/unsupported %s file "
462 				"version (%d)\n", fFileType,
463 				B_BENDIAN_TO_HOST_INT16(header.version));
464 		}
465 		return B_MISMATCHED_VALUES;
466 	}
467 
468 	fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version);
469 	fCurrentMinorFormatVersion = kMinorVersion;
470 
471 	// header size
472 	uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
473 	if (heapOffset < (off_t)sizeof(header)) {
474 		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header "
475 			"size (%" B_PRIu64 ")\n", fFileType, heapOffset);
476 		return B_BAD_DATA;
477 	}
478 
479 	// total size
480 	uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
481 	if (totalSize != (uint64)st.st_size) {
482 		ErrorOutput()->PrintError("Error: Invalid %s file: Total size in "
483 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
484 			B_PRIdOFF ")\n", fFileType, totalSize, st.st_size);
485 		return B_BAD_DATA;
486 	}
487 
488 	// heap size
489 	uint64 compressedHeapSize
490 		= B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed);
491 	if (compressedHeapSize > totalSize
492 		|| heapOffset > totalSize - compressedHeapSize) {
493 		ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in "
494 			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
495 			B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType,
496 			compressedHeapSize, totalSize, heapOffset);
497 		return B_BAD_DATA;
498 	}
499 
500 	error = InitHeapReader(
501 		B_BENDIAN_TO_HOST_INT16(header.heap_compression),
502 		B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset,
503 		compressedHeapSize,
504 		B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed));
505 	if (error != B_OK)
506 		return error;
507 
508 	return B_OK;
509 }
510 
511 
512 inline int
513 ReaderImplBase::FD() const
514 {
515 	return fFD;
516 }
517 
518 
519 inline BErrorOutput*
520 ReaderImplBase::ErrorOutput() const
521 {
522 	return fErrorOutput;
523 }
524 
525 
526 PackageFileSection*
527 ReaderImplBase::CurrentSection()
528 {
529 	return fCurrentSection;
530 }
531 
532 
533 void
534 ReaderImplBase::SetCurrentSection(PackageFileSection* section)
535 {
536 	fCurrentSection = section;
537 }
538 
539 
540 template<typename Type>
541 status_t
542 ReaderImplBase::_Read(Type& _value)
543 {
544 	return _ReadSectionBuffer(&_value, sizeof(Type));
545 }
546 
547 
548 inline ReaderImplBase::AttributeHandler*
549 ReaderImplBase::CurrentAttributeHandler() const
550 {
551 	return fAttributeHandlerStack.Head();
552 }
553 
554 
555 inline void
556 ReaderImplBase::PushAttributeHandler(AttributeHandler* handler)
557 {
558 	fAttributeHandlerStack.Add(handler);
559 }
560 
561 
562 inline ReaderImplBase::AttributeHandler*
563 ReaderImplBase::PopAttributeHandler()
564 {
565 	return fAttributeHandlerStack.RemoveHead();
566 }
567 
568 
569 inline void
570 ReaderImplBase::ClearAttributeHandlerStack()
571 {
572 	fAttributeHandlerStack.MakeEmpty();
573 }
574 
575 
576 }	// namespace BPrivate
577 
578 }	// namespace BHPKG
579 
580 }	// namespace BPackageKit
581 
582 
583 #endif	// _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
584