blob: df5c49a6b774e6e343bf7762ac8e0e555ef9164f [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Andy McFadden80a4e242010-04-23 16:34:52 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
18 * Read-only access to Zip archives, with minimal heap allocation.
19 */
Carl Shapiro375fb112011-06-14 20:31:24 -070020#ifndef LIBDEX_ZIPARCHIVE_H_
21#define LIBDEX_ZIPARCHIVE_H_
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080022
23#include "SysUtil.h"
24#include "DexFile.h" // need DEX_INLINE
25
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080026/*
27 * Trivial typedef to ensure that ZipEntry is not treated as a simple
28 * integer. We use NULL to indicate an invalid value.
29 */
30typedef void* ZipEntry;
31
32/*
33 * One entry in the hash table.
34 */
Carl Shapirobfc97992011-04-27 14:16:08 -070035struct ZipHashEntry {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080036 const char* name;
37 unsigned short nameLen;
Carl Shapirobfc97992011-04-27 14:16:08 -070038};
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080039
40/*
41 * Read-only Zip archive.
42 *
Andy McFadden80a4e242010-04-23 16:34:52 -070043 * We want "open" and "find entry by name" to be fast operations, and
44 * we want to use as little memory as possible. We memory-map the zip
45 * central directory, and load a hash table with pointers to the filenames
46 * (which aren't null-terminated). The other fields are at a fixed offset
47 * from the filename, so we don't need to extract those (but we do need
48 * to byte-read and endian-swap them every time we want them).
49 *
50 * It's possible that somebody has handed us a massive (~1GB) zip archive,
51 * so we can't expect to mmap the entire file.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080052 *
53 * To speed comparisons when doing a lookup by name, we could make the mapping
54 * "private" (copy-on-write) and null-terminate the filenames after verifying
55 * the record structure. However, this requires a private mapping of
56 * every page that the Central Directory touches. Easier to tuck a copy
57 * of the string length into the hash table entry.
58 */
Carl Shapirobfc97992011-04-27 14:16:08 -070059struct ZipArchive {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080060 /* open Zip archive */
61 int mFd;
62
Andy McFadden80a4e242010-04-23 16:34:52 -070063 /* mapped central directory area */
64 off_t mDirectoryOffset;
65 MemMapping mDirectoryMap;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080066
67 /* number of entries in the Zip archive */
68 int mNumEntries;
69
70 /*
71 * We know how many entries are in the Zip archive, so we can have a
72 * fixed-size hash table. We probe on collisions.
73 */
74 int mHashTableSize;
75 ZipHashEntry* mHashTable;
Carl Shapirobfc97992011-04-27 14:16:08 -070076};
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080077
78/* Zip compression methods we support */
79enum {
80 kCompressStored = 0, // no compression
81 kCompressDeflated = 8, // standard deflate
82};
83
84
85/*
86 * Open a Zip archive.
87 *
88 * On success, returns 0 and populates "pArchive". Returns nonzero errno
89 * value on failure.
90 */
91int dexZipOpenArchive(const char* fileName, ZipArchive* pArchive);
92
93/*
94 * Like dexZipOpenArchive, but takes a file descriptor open for reading
95 * at the start of the file. The descriptor must be mappable (this does
96 * not allow access to a stream).
97 *
98 * "debugFileName" will appear in error messages, but is not otherwise used.
99 */
100int dexZipPrepArchive(int fd, const char* debugFileName, ZipArchive* pArchive);
101
102/*
103 * Close archive, releasing resources associated with it.
104 *
105 * Depending on the implementation this could unmap pages used by classes
106 * stored in a Jar. This should only be done after unloading classes.
107 */
108void dexZipCloseArchive(ZipArchive* pArchive);
109
110/*
111 * Return the archive's file descriptor.
112 */
113DEX_INLINE int dexZipGetArchiveFd(const ZipArchive* pArchive) {
114 return pArchive->mFd;
115}
116
117/*
118 * Find an entry in the Zip archive, by name. Returns NULL if the entry
119 * was not found.
120 */
121ZipEntry dexZipFindEntry(const ZipArchive* pArchive,
122 const char* entryName);
123
124/*
125 * Retrieve one or more of the "interesting" fields. Non-NULL pointers
126 * are filled in.
Andy McFadden80a4e242010-04-23 16:34:52 -0700127 *
128 * Returns 0 on success.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800129 */
Andy McFadden80a4e242010-04-23 16:34:52 -0700130int dexZipGetEntryInfo(const ZipArchive* pArchive, ZipEntry entry,
131 int* pMethod, size_t* pUncompLen, size_t* pCompLen, off_t* pOffset,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800132 long* pModWhen, long* pCrc32);
133
134/*
135 * Simple accessors.
136 */
137DEX_INLINE long dexGetZipEntryOffset(const ZipArchive* pArchive,
138 const ZipEntry entry)
139{
140 off_t val = 0;
141 dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, &val, NULL, NULL);
142 return (long) val;
143}
Andy McFadden80a4e242010-04-23 16:34:52 -0700144DEX_INLINE size_t dexGetZipEntryUncompLen(const ZipArchive* pArchive,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800145 const ZipEntry entry)
146{
Andy McFadden80a4e242010-04-23 16:34:52 -0700147 size_t val = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800148 dexZipGetEntryInfo(pArchive, entry, NULL, &val, NULL, NULL, NULL, NULL);
149 return val;
150}
151DEX_INLINE long dexGetZipEntryModTime(const ZipArchive* pArchive,
152 const ZipEntry entry)
153{
154 long val = 0;
155 dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, &val, NULL);
156 return val;
157}
158DEX_INLINE long dexGetZipEntryCrc32(const ZipArchive* pArchive,
159 const ZipEntry entry)
160{
161 long val = 0;
162 dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, NULL, &val);
163 return val;
164}
165
166/*
167 * Uncompress and write an entry to a file descriptor.
Andy McFadden80a4e242010-04-23 16:34:52 -0700168 *
169 * Returns 0 on success.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800170 */
Andy McFadden80a4e242010-04-23 16:34:52 -0700171int dexZipExtractEntryToFile(const ZipArchive* pArchive,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800172 const ZipEntry entry, int fd);
173
174/*
175 * Utility function to compute a CRC-32.
176 */
177u4 dexInitCrc32(void);
178u4 dexComputeCrc32(u4 crc, const void* buf, size_t len);
179
Carl Shapiro375fb112011-06-14 20:31:24 -0700180#endif // LIBDEX_ZIPARCHIVE_H_