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