Bumping gaia.json for 3 gaia-central revision(s) a=gaia-bump
[gecko.git] / modules / libjar / nsZipArchive.h
blobcb39e31f0131486126dc0342949b31f725b44557
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsZipArchive_h_
7 #define nsZipArchive_h_
9 #include "mozilla/Attributes.h"
11 #define ZIP_TABSIZE 256
12 #define ZIP_BUFLEN (4*1024) /* Used as output buffer when deflating items to a file */
14 #ifndef PL_ARENA_CONST_ALIGN_MASK
15 #define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1)
16 #endif
17 #include "plarena.h"
19 #include "zlib.h"
20 #include "zipstruct.h"
21 #include "nsAutoPtr.h"
22 #include "nsIFile.h"
23 #include "nsISupportsImpl.h" // For mozilla::ThreadSafeAutoRefCnt
24 #include "mozilla/FileUtils.h"
25 #include "mozilla/FileLocation.h"
27 #if defined(XP_WIN) && defined(_MSC_VER)
28 #define MOZ_WIN_MEM_TRY_BEGIN __try {
29 #define MOZ_WIN_MEM_TRY_CATCH(cmd) } \
30 __except(GetExceptionCode()==EXCEPTION_IN_PAGE_ERROR ? \
31 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) \
32 { \
33 NS_WARNING("EXCEPTION_IN_PAGE_ERROR in " __FUNCTION__); \
34 cmd; \
36 #else
37 #define MOZ_WIN_MEM_TRY_BEGIN {
38 #define MOZ_WIN_MEM_TRY_CATCH(cmd) }
39 #endif
41 class nsZipFind;
42 struct PRFileDesc;
44 /**
45 * This file defines some of the basic structures used by libjar to
46 * read Zip files. It makes use of zlib in order to do the decompression.
48 * A few notes on the classes/structs:
49 * nsZipArchive represents a single Zip file, and maintains an index
50 * of all the items in the file.
51 * nsZipItem represents a single item (file) in the Zip archive.
52 * nsZipFind represents the metadata involved in doing a search,
53 * and current state of the iteration of found objects.
54 * 'MT''safe' reading from the zipfile is performed through JARInputStream,
55 * which maintains its own file descriptor, allowing for multiple reads
56 * concurrently from the same zip file.
59 /**
60 * nsZipItem -- a helper struct for nsZipArchive
62 * each nsZipItem represents one file in the archive and all the
63 * information needed to manipulate it.
65 class nsZipItem
67 public:
68 const char* Name() { return ((const char*)central) + ZIPCENTRAL_SIZE; }
70 uint32_t LocalOffset();
71 uint32_t Size();
72 uint32_t RealSize();
73 uint32_t CRC32();
74 uint16_t Date();
75 uint16_t Time();
76 uint16_t Compression();
77 bool IsDirectory();
78 uint16_t Mode();
79 const uint8_t* GetExtraField(uint16_t aTag, uint16_t *aBlockSize);
80 PRTime LastModTime();
82 #ifdef XP_UNIX
83 bool IsSymlink();
84 #endif
86 nsZipItem* next;
87 const ZipCentral* central;
88 uint16_t nameLength;
89 bool isSynthetic;
92 class nsZipHandle;
94 /**
95 * nsZipArchive -- a class for reading the PKZIP file format.
98 class nsZipArchive
100 friend class nsZipFind;
102 public:
103 /** constructing does not open the archive. See OpenArchive() */
104 nsZipArchive();
106 /** destructing the object closes the archive */
107 ~nsZipArchive();
109 /**
110 * OpenArchive
112 * It's an error to call this more than once on the same nsZipArchive
113 * object. If we were allowed to use exceptions this would have been
114 * part of the constructor
116 * @param aZipHandle The nsZipHandle used to access the zip
117 * @param aFd Optional PRFileDesc for Windows readahead optimization
118 * @return status code
120 nsresult OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd = nullptr);
122 /**
123 * OpenArchive
125 * Convenience function that generates nsZipHandle
127 * @param aFile The file used to access the zip
128 * @return status code
130 nsresult OpenArchive(nsIFile *aFile);
133 * Test the integrity of items in this archive by running
134 * a CRC check after extracting each item into a memory
135 * buffer. If an entry name is supplied only the
136 * specified item is tested. Else, if null is supplied
137 * then all the items in the archive are tested.
139 * @return status code
141 nsresult Test(const char *aEntryName);
144 * Closes an open archive.
146 nsresult CloseArchive();
148 /**
149 * GetItem
150 * @param aEntryName Name of file in the archive
151 * @return pointer to nsZipItem
153 nsZipItem* GetItem(const char * aEntryName);
155 /**
156 * ExtractFile
158 * @param zipEntry Name of file in archive to extract
159 * @param outFD Filedescriptor to write contents to
160 * @param outname Name of file to write to
161 * @return status code
163 nsresult ExtractFile(nsZipItem * zipEntry, const char *outname, PRFileDesc * outFD);
166 * FindInit
168 * Initializes a search for files in the archive. FindNext() returns
169 * the actual matches. The nsZipFind must be deleted when you're done
171 * @param aPattern a string or RegExp pattern to search for
172 * (may be nullptr to find all files in archive)
173 * @param aFind a pointer to a pointer to a structure used
174 * in FindNext. In the case of an error this
175 * will be set to nullptr.
176 * @return status code
178 nsresult FindInit(const char * aPattern, nsZipFind** aFind);
181 * Gets an undependent handle to the mapped file.
183 nsZipHandle* GetFD();
186 * Get pointer to the data of the item.
187 * @param aItem Pointer to nsZipItem
188 * reutrns null when zip file is corrupt.
190 const uint8_t* GetData(nsZipItem* aItem);
192 bool GetComment(nsACString &aComment);
195 * Gets the amount of memory taken up by the archive's mapping.
196 * @return the size
198 int64_t SizeOfMapping();
201 * Refcounting
203 NS_METHOD_(nsrefcnt) AddRef(void);
204 NS_METHOD_(nsrefcnt) Release(void);
206 private:
207 //--- private members ---
208 mozilla::ThreadSafeAutoRefCnt mRefCnt; /* ref count */
209 NS_DECL_OWNINGTHREAD
211 nsZipItem* mFiles[ZIP_TABSIZE];
212 PLArenaPool mArena;
214 const char* mCommentPtr;
215 uint16_t mCommentLen;
217 // Whether we synthesized the directory entries
218 bool mBuiltSynthetics;
220 // file handle
221 nsRefPtr<nsZipHandle> mFd;
223 // file URI, for logging
224 nsCString mURI;
226 private:
227 //--- private methods ---
228 nsZipItem* CreateZipItem();
229 nsresult BuildFileList(PRFileDesc *aFd = nullptr);
230 nsresult BuildSynthetics();
232 nsZipArchive& operator=(const nsZipArchive& rhs) MOZ_DELETE;
233 nsZipArchive(const nsZipArchive& rhs) MOZ_DELETE;
236 /**
237 * nsZipFind
239 * a helper class for nsZipArchive, representing a search
241 class nsZipFind
243 public:
244 nsZipFind(nsZipArchive* aZip, char* aPattern, bool regExp);
245 ~nsZipFind();
247 nsresult FindNext(const char** aResult, uint16_t* aNameLen);
249 private:
250 nsRefPtr<nsZipArchive> mArchive;
251 char* mPattern;
252 nsZipItem* mItem;
253 uint16_t mSlot;
254 bool mRegExp;
256 nsZipFind& operator=(const nsZipFind& rhs) MOZ_DELETE;
257 nsZipFind(const nsZipFind& rhs) MOZ_DELETE;
260 /**
261 * nsZipCursor -- a low-level class for reading the individual items in a zip.
263 class nsZipCursor {
264 public:
266 * Initializes the cursor
268 * @param aItem Item of interest
269 * @param aZip Archive
270 * @param aBuf Buffer used for decompression.
271 * This determines the maximum Read() size in the compressed case.
272 * @param aBufSize Buffer size
273 * @param doCRC When set to true Read() will check crc
275 nsZipCursor(nsZipItem *aItem, nsZipArchive *aZip, uint8_t* aBuf = nullptr, uint32_t aBufSize = 0, bool doCRC = false);
277 ~nsZipCursor();
280 * Performs reads. In the compressed case it uses aBuf(passed in constructor), for stored files
281 * it returns a zero-copy buffer.
283 * @param aBytesRead Outparam for number of bytes read.
284 * @return data read or nullptr if item is corrupted.
286 uint8_t* Read(uint32_t *aBytesRead) {
287 return ReadOrCopy(aBytesRead, false);
291 * Performs a copy. It always uses aBuf(passed in constructor).
293 * @param aBytesRead Outparam for number of bytes read.
294 * @return data read or nullptr if item is corrupted.
296 uint8_t* Copy(uint32_t *aBytesRead) {
297 return ReadOrCopy(aBytesRead, true);
300 private:
301 /* Actual implementation for both Read and Copy above */
302 uint8_t* ReadOrCopy(uint32_t *aBytesRead, bool aCopy);
304 nsZipItem *mItem;
305 uint8_t *mBuf;
306 uint32_t mBufSize;
307 z_stream mZs;
308 uint32_t mCRC;
309 bool mDoCRC;
313 * nsZipItemPtr - a RAII convenience class for reading the individual items in a zip.
314 * It reads whole files and does zero-copy IO for stored files. A buffer is allocated
315 * for decompression.
316 * Do not use when the file may be very large.
318 class nsZipItemPtr_base {
319 public:
321 * Initializes the reader
323 * @param aZip Archive
324 * @param aEntryName Archive membername
325 * @param doCRC When set to true Read() will check crc
327 nsZipItemPtr_base(nsZipArchive *aZip, const char *aEntryName, bool doCRC);
329 uint32_t Length() const {
330 return mReadlen;
333 protected:
334 nsRefPtr<nsZipHandle> mZipHandle;
335 nsAutoArrayPtr<uint8_t> mAutoBuf;
336 uint8_t *mReturnBuf;
337 uint32_t mReadlen;
340 template <class T>
341 class nsZipItemPtr : public nsZipItemPtr_base {
342 public:
343 nsZipItemPtr(nsZipArchive *aZip, const char *aEntryName, bool doCRC = false) : nsZipItemPtr_base(aZip, aEntryName, doCRC) { }
345 * @return buffer containing the whole zip member or nullptr on error.
346 * The returned buffer is owned by nsZipItemReader.
348 const T* Buffer() const {
349 return (const T*)mReturnBuf;
352 operator const T*() const {
353 return Buffer();
357 * Relinquish ownership of zip member if compressed.
358 * Copy member into a new buffer if uncompressed.
359 * @return a buffer with whole zip member. It is caller's responsibility to free() it.
361 T* Forget() {
362 if (!mReturnBuf)
363 return nullptr;
364 // In uncompressed mmap case, give up buffer
365 if (mAutoBuf.get() == mReturnBuf) {
366 mReturnBuf = nullptr;
367 return (T*) mAutoBuf.forget();
369 T *ret = (T*) malloc(Length());
370 memcpy(ret, mReturnBuf, Length());
371 mReturnBuf = nullptr;
372 return ret;
376 class nsZipHandle {
377 friend class nsZipArchive;
378 friend class mozilla::FileLocation;
379 public:
380 static nsresult Init(nsIFile *file, nsZipHandle **ret,
381 PRFileDesc **aFd = nullptr);
382 static nsresult Init(nsZipArchive *zip, const char *entry,
383 nsZipHandle **ret);
385 NS_METHOD_(nsrefcnt) AddRef(void);
386 NS_METHOD_(nsrefcnt) Release(void);
388 int64_t SizeOfMapping();
390 protected:
391 const uint8_t * mFileData; /* pointer to mmaped file */
392 uint32_t mLen; /* length of file and memory mapped area */
393 mozilla::FileLocation mFile; /* source file if any, for logging */
395 private:
396 nsZipHandle();
397 ~nsZipHandle();
399 PRFileMap * mMap; /* nspr datastructure for mmap */
400 nsAutoPtr<nsZipItemPtr<uint8_t> > mBuf;
401 mozilla::ThreadSafeAutoRefCnt mRefCnt; /* ref count */
402 NS_DECL_OWNINGTHREAD
405 nsresult gZlibInit(z_stream *zs);
407 #endif /* nsZipArchive_h_ */