summaryrefslogtreecommitdiffstats
path: root/minzip/Zip.h
blob: 0b1c9d5321c5b4e298967f7f196d61d972836106 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Simple Zip archive support.
 */
#ifndef _MINZIP_ZIP
#define _MINZIP_ZIP

#include "inline_magic.h"

#include <stdlib.h>
#include <utime.h>

#include "Hash.h"
#include "SysUtil.h"

#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#else
struct selabel_handle;
#endif

/*
 * One entry in the Zip archive.  Treat this as opaque -- use accessors below.
 *
 * TODO: we're now keeping the pages mapped so we don't have to copy the
 * filename.  We can change the accessors to retrieve the various pieces
 * directly from the source file instead of copying them out, for a very
 * slight speed hit and a modest reduction in memory usage.
 */
typedef struct ZipEntry {
    unsigned int fileNameLen;
    const char*  fileName;       // not null-terminated
    long         offset;
    long         compLen;
    long         uncompLen;
    int          compression;
    long         modTime;
    long         crc32;
    int          versionMadeBy;
    long         externalFileAttributes;
} ZipEntry;

/*
 * One Zip archive.  Treat as opaque.
 */
typedef struct ZipArchive {
    int         fd;
    unsigned int numEntries;
    ZipEntry*   pEntries;
    HashTable*  pHash;          // maps file name to ZipEntry
    MemMapping  map;
} ZipArchive;

/*
 * Represents a non-NUL-terminated string,
 * which is how entry names are stored.
 */
typedef struct {
    const char *str;
    size_t len;
} UnterminatedString;

/*
 * Open a Zip archive.
 *
 * On success, returns 0 and populates "pArchive".  Returns nonzero errno
 * value on failure.
 */
int mzOpenZipArchive(const char* fileName, ZipArchive* pArchive);

/*
 * Close archive, releasing resources associated with it.
 *
 * Depending on the implementation this could unmap pages used by classes
 * stored in a Jar.  This should only be done after unloading classes.
 */
void mzCloseZipArchive(ZipArchive* pArchive);


/*
 * Find an entry in the Zip archive, by name.
 */
const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive,
        const char* entryName);

/*
 * Get the number of entries in the Zip archive.
 */
INLINE unsigned int mzZipEntryCount(const ZipArchive* pArchive) {
    return pArchive->numEntries;
}

/*
 * Get an entry by index.  Returns NULL if the index is out-of-bounds.
 */
INLINE const ZipEntry*
mzGetZipEntryAt(const ZipArchive* pArchive, unsigned int index)
{
    if (index < pArchive->numEntries) {
        return pArchive->pEntries + index;
    }
    return NULL;
}

/*
 * Get the index number of an entry in the archive.
 */
INLINE unsigned int
mzGetZipEntryIndex(const ZipArchive *pArchive, const ZipEntry *pEntry) {
    return pEntry - pArchive->pEntries;
}

/*
 * Simple accessors.
 */
INLINE UnterminatedString mzGetZipEntryFileName(const ZipEntry* pEntry) {
    UnterminatedString ret;
    ret.str = pEntry->fileName;
    ret.len = pEntry->fileNameLen;
    return ret;
}
INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) {
    return pEntry->offset;
}
INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) {
    return pEntry->uncompLen;
}
INLINE long mzGetZipEntryModTime(const ZipEntry* pEntry) {
    return pEntry->modTime;
}
INLINE long mzGetZipEntryCrc32(const ZipEntry* pEntry) {
    return pEntry->crc32;
}
bool mzIsZipEntrySymlink(const ZipEntry* pEntry);


/*
 * Type definition for the callback function used by
 * mzProcessZipEntryContents().
 */
typedef bool (*ProcessZipEntryContentsFunction)(const unsigned char *data,
    int dataLen, void *cookie);

/*
 * Stream the uncompressed data through the supplied function,
 * passing cookie to it each time it gets called.  processFunction
 * may be called more than once.
 *
 * If processFunction returns false, the operation is abandoned and
 * mzProcessZipEntryContents() immediately returns false.
 *
 * This is useful for calculating the hash of an entry's uncompressed contents.
 */
bool mzProcessZipEntryContents(const ZipArchive *pArchive,
    const ZipEntry *pEntry, ProcessZipEntryContentsFunction processFunction,
    void *cookie);

/*
 * Read an entry into a buffer allocated by the caller.
 */
bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry,
        char* buf, int bufLen);

/*
 * Check the CRC on this entry; return true if it is correct.
 * May do other internal checks as well.
 */
bool mzIsZipEntryIntact(const ZipArchive *pArchive, const ZipEntry *pEntry);

/*
 * Inflate and write an entry to a file.
 */
bool mzExtractZipEntryToFile(const ZipArchive *pArchive,
    const ZipEntry *pEntry, int fd);

/*
 * Inflate and write an entry to a memory buffer, which must be long
 * enough to hold mzGetZipEntryUncomplen(pEntry) bytes.
 */
bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive,
    const ZipEntry *pEntry, unsigned char* buffer);

/*
 * Inflate all entries under zipDir to the directory specified by
 * targetDir, which must exist and be a writable directory.
 *
 * The immediate children of zipDir will become the immediate
 * children of targetDir; e.g., if the archive contains the entries
 *
 *     a/b/c/one
 *     a/b/c/two
 *     a/b/c/d/three
 *
 * and mzExtractRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting
 * files will be
 *
 *     /tmp/one
 *     /tmp/two
 *     /tmp/d/three
 *
 * flags is zero or more of the following:
 *
 *     MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks
 *     MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback
 *
 * If timestamp is non-NULL, file timestamps will be set accordingly.
 *
 * If callback is non-NULL, it will be invoked with each unpacked file.
 *
 * Returns true on success, false on failure.
 */
enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 };
bool mzExtractRecursive(const ZipArchive *pArchive,
        const char *zipDir, const char *targetDir,
        int flags, const struct utimbuf *timestamp,
        void (*callback)(const char *fn, void*), void *cookie,
        struct selabel_handle *sehnd);

#endif /*_MINZIP_ZIP*/