Mappable.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #ifndef Mappable_h
  5. #define Mappable_h
  6. #include "Zip.h"
  7. #include "SeekableZStream.h"
  8. #include "mozilla/RefPtr.h"
  9. #include "mozilla/UniquePtr.h"
  10. #include "zlib.h"
  11. /**
  12. * Abstract class to handle mmap()ing from various kind of entities, such as
  13. * plain files or Zip entries. The virtual members are meant to act as the
  14. * equivalent system functions, except mapped memory is always MAP_PRIVATE,
  15. * even though a given implementation may use something different internally.
  16. */
  17. class Mappable: public mozilla::RefCounted<Mappable>
  18. {
  19. public:
  20. MOZ_DECLARE_REFCOUNTED_TYPENAME(Mappable)
  21. virtual ~Mappable() { }
  22. virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags,
  23. off_t offset) = 0;
  24. enum Kind {
  25. MAPPABLE_FILE,
  26. MAPPABLE_EXTRACT_FILE,
  27. MAPPABLE_DEFLATE,
  28. MAPPABLE_SEEKABLE_ZSTREAM
  29. };
  30. virtual Kind GetKind() const = 0;
  31. private:
  32. virtual void munmap(void *addr, size_t length) {
  33. ::munmap(addr, length);
  34. }
  35. /* Limit use of Mappable::munmap to classes that keep track of the address
  36. * and size of the mapping. This allows to ignore ::munmap return value. */
  37. friend class Mappable1stPagePtr;
  38. friend class LibHandle;
  39. public:
  40. /**
  41. * Ensures the availability of the memory pages for the page(s) containing
  42. * the given address. Returns whether the pages were successfully made
  43. * available.
  44. */
  45. virtual bool ensure(const void *addr) { return true; }
  46. /**
  47. * Indicate to a Mappable instance that no further mmap is going to happen.
  48. */
  49. virtual void finalize() = 0;
  50. /**
  51. * Shows some stats about the Mappable instance.
  52. * Meant for MappableSeekableZStream only.
  53. * As Mappables don't keep track of what they are instanciated for, the name
  54. * argument is used to make the stats logging useful to the reader. The when
  55. * argument is to be used by the caller to give an identifier of the when
  56. * the stats call is made.
  57. */
  58. virtual void stats(const char *when, const char *name) const { }
  59. /**
  60. * Returns the maximum length that can be mapped from this Mappable for
  61. * offset = 0.
  62. */
  63. virtual size_t GetLength() const = 0;
  64. };
  65. /**
  66. * Mappable implementation for plain files
  67. */
  68. class MappableFile: public Mappable
  69. {
  70. public:
  71. ~MappableFile() { }
  72. /**
  73. * Create a MappableFile instance for the given file path.
  74. */
  75. static Mappable *Create(const char *path);
  76. /* Inherited from Mappable */
  77. virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
  78. virtual void finalize();
  79. virtual size_t GetLength() const;
  80. virtual Kind GetKind() const { return MAPPABLE_FILE; };
  81. protected:
  82. MappableFile(int fd): fd(fd) { }
  83. private:
  84. /* File descriptor */
  85. AutoCloseFD fd;
  86. };
  87. /**
  88. * Mappable implementation for deflated stream in a Zip archive
  89. * Inflates the complete stream into a cache file.
  90. */
  91. class MappableExtractFile: public MappableFile
  92. {
  93. public:
  94. ~MappableExtractFile() = default;
  95. /**
  96. * Create a MappableExtractFile instance for the given Zip stream. The name
  97. * argument is used to create the cache file in the cache directory.
  98. */
  99. static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
  100. /* Override finalize from MappableFile */
  101. virtual void finalize() {}
  102. virtual Kind GetKind() const { return MAPPABLE_EXTRACT_FILE; };
  103. private:
  104. /**
  105. * AutoUnlinkFile keeps track of a file name and removes (unlinks) the file
  106. * when the instance is destroyed.
  107. */
  108. struct UnlinkFile
  109. {
  110. void operator()(char *value) {
  111. unlink(value);
  112. delete [] value;
  113. }
  114. };
  115. typedef mozilla::UniquePtr<char[], UnlinkFile> AutoUnlinkFile;
  116. MappableExtractFile(int fd, const char* path)
  117. : MappableFile(fd), path(path) { }
  118. /* Extracted file path */
  119. mozilla::UniquePtr<const char[]> path;
  120. };
  121. class _MappableBuffer;
  122. /**
  123. * Mappable implementation for deflated stream in a Zip archive.
  124. * Inflates the mapped bits in a temporary buffer.
  125. */
  126. class MappableDeflate: public Mappable
  127. {
  128. public:
  129. ~MappableDeflate();
  130. /**
  131. * Create a MappableDeflate instance for the given Zip stream. The name
  132. * argument is used for an appropriately named temporary file, and the Zip
  133. * instance is given for the MappableDeflate to keep a reference of it.
  134. */
  135. static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
  136. /* Inherited from Mappable */
  137. virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
  138. virtual void finalize();
  139. virtual size_t GetLength() const;
  140. virtual Kind GetKind() const { return MAPPABLE_DEFLATE; };
  141. private:
  142. MappableDeflate(_MappableBuffer *buf, Zip *zip, Zip::Stream *stream);
  143. /* Zip reference */
  144. RefPtr<Zip> zip;
  145. /* Decompression buffer */
  146. mozilla::UniquePtr<_MappableBuffer> buffer;
  147. /* Zlib data */
  148. zxx_stream zStream;
  149. };
  150. /**
  151. * Mappable implementation for seekable zStreams.
  152. * Inflates the mapped bits in a temporary buffer, on demand.
  153. */
  154. class MappableSeekableZStream: public Mappable
  155. {
  156. public:
  157. ~MappableSeekableZStream();
  158. /**
  159. * Create a MappableSeekableZStream instance for the given Zip stream. The
  160. * name argument is used for an appropriately named temporary file, and the
  161. * Zip instance is given for the MappableSeekableZStream to keep a reference
  162. * of it.
  163. */
  164. static Mappable *Create(const char *name, Zip *zip,
  165. Zip::Stream *stream);
  166. /* Inherited from Mappable */
  167. virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
  168. virtual void munmap(void *addr, size_t length);
  169. virtual void finalize();
  170. virtual bool ensure(const void *addr);
  171. virtual void stats(const char *when, const char *name) const;
  172. virtual size_t GetLength() const;
  173. virtual Kind GetKind() const { return MAPPABLE_SEEKABLE_ZSTREAM; };
  174. private:
  175. MappableSeekableZStream(Zip *zip);
  176. /* Zip reference */
  177. RefPtr<Zip> zip;
  178. /* Decompression buffer */
  179. mozilla::UniquePtr<_MappableBuffer> buffer;
  180. /* Seekable ZStream */
  181. SeekableZStream zStream;
  182. /* Keep track of mappings performed with MappableSeekableZStream::mmap so
  183. * that they can be realized by MappableSeekableZStream::ensure.
  184. * Values stored in the struct are those passed to mmap */
  185. struct LazyMap
  186. {
  187. const void *addr;
  188. size_t length;
  189. int prot;
  190. off_t offset;
  191. /* Returns addr + length, as a pointer */
  192. const void *end() const {
  193. return reinterpret_cast<const void *>
  194. (reinterpret_cast<const unsigned char *>(addr) + length);
  195. }
  196. /* Returns offset + length */
  197. off_t endOffset() const {
  198. return offset + length;
  199. }
  200. /* Returns the offset corresponding to the given address */
  201. off_t offsetOf(const void *ptr) const {
  202. return reinterpret_cast<uintptr_t>(ptr)
  203. - reinterpret_cast<uintptr_t>(addr) + offset;
  204. }
  205. /* Returns whether the given address is in the LazyMap range */
  206. bool Contains(const void *ptr) const {
  207. return (ptr >= addr) && (ptr < end());
  208. }
  209. };
  210. /* List of all mappings */
  211. std::vector<LazyMap> lazyMaps;
  212. /* Array keeping track of which chunks have already been decompressed.
  213. * Each value is the number of pages decompressed for the given chunk. */
  214. mozilla::UniquePtr<unsigned char[]> chunkAvail;
  215. /* Number of chunks that have already been decompressed. */
  216. mozilla::Atomic<size_t> chunkAvailNum;
  217. /* Mutex protecting decompression */
  218. pthread_mutex_t mutex;
  219. };
  220. #endif /* Mappable_h */