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